angular Microsoft authentication library issue - microsoft-graph-api

I am using MICROSOFT AUTHENTICATION LIBRARY in our angular 10 project. I have used MSAL loginPopup() function to login the user in our active directory. But sometimes When I click the login function msal login pop appear and when I close the parent window it does not redirect in the next page stuck there and on the browser debugger console window it shows this error
(ERROR BrowserAuthError: hash_empty_error: Hash value cannot be processed because it is empty. Please verify that your redirect URI is not clearing the hash. Given Url:)

What worked for me in my ReactJS application was to set the redirectUri to a blank page or a page that does not implement MSAL. If your application is only using popup and silent APIs you can set this on the PublicClientApplication config like below:
export const msalConfig = {
auth: {
clientId: process.env.REACT_APP_CLIENTID,
authority: `https://login.microsoftonline.com/${process.env.REACT_APP_TENANTID}`,
redirectUri: 'http://localhost:3000/blank.html'
},
cache: {
cacheLocation: "localStorage"
}
}
If your application also needs to support redirect APIs you can set the redirectUri on a per request basis:
msalInstance.loginPopup({
redirectUri: "http://localhost:3000/blank.html"
})

After some research I found out that the problem was related to the redirect Uri, and most resources pointed to adding a blank page as the redirect Uri in a popup flow. However most of the answers were related to React. I tried a few options for adding a blank html page but it was not so simple. I did not want to waste much time on this issue, because the app is new and we might go with the redirect flow in the future.
Then I remembered that the problems started when we configured the home page, which is the redirect target, to be authenticated with MSAL Guard.
Since I couldn`t easily add a blank html page, I added a blank-page component configured in the Router with blank-page path. The component had no functionality and was not related to MSAL, MSAL Guard or MSAL Interceptor.
This solved it for me. I hope this helps.

Related

Google Identity Services: How to preserve session

I'm migrating a web app that interacts with the google drive js api to the new Google Identity Services API and following this quickstart guide. GIS is mandatory, since the old one will no longer be in use from March 2023.
In this guide, there is only one small note mentionning to preserve the logged in state after page reload:
Note: After the initial user authorization, you can call gapi.auth.authorize with immediate:true to obtain an auth token without user interaction.
However, there's no clear code example how to do that, furthermore one can find in the migration guide, that gapi.auth2.authorize() is deprecated.
Using One Tap (a div with the id "g_id_onload") is not a solution, because I need an extended scope (to access later on google drive)
Storing the access token in localstorage (as mentionned in some threads) is no option, since it violates the oauth model
Calling requestAccessToken() after every page reload without user interaction is not an option, because 1st the popup is not shown at all (blocked in all major browsers) and 2nd if allowed the popup is shown and hiding immediately (bad ui)
Can somebody give me an example where GSI is used via JS that preserves sessions through page reloads?
It seems that Google Identity Services is not yet production ready or am I wrong?
In order to help:
Google 3P Authorization JavaScript Library: in this link we can check all the methods the new library has (it does not refresh token, etc..)
This doc says the library won't control the cookies to keep the state anymore.
Solution
Firstly I need to thanks #Sam O'Riil answer.
As Sam described: "you can somehow save access token and use it to speed-up things after page reload."
Given the the Google's exampe, we should call initTokenClient in order to configure the Google Auth and the requestAccessToken to popup the auth:
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
prompt: 'consent',
callback: tokenCallback
});
tokenClient.requestAccessToken({prompt: ''})
In your tokenCallback you can save the credentials you get somehow, e.g.:
const tokenCallback(credentials) => {
// save here the credentials using localStorage or cookies or whatever you want to.
}
Finally, when you restart/reload your application and you initialize the gapi.server again, you only need to get the credentials again and set token to gapi, like:
gapi.load('client', function() {
gapi.client.init({}).then(function() {
let credentials = // get your credentials from where you saved it
credentials = JSON.parse(credentials); // parse it if you got it as string
gapi.client.setToken(credentials);
... continue you app ...
}).catch(function(err) {
// do catch...
});
});
Doing it, your application will work after the reload. I know it could not be the best solution, but seeing what you have and the library offers, I think that's you can do.
p.s.: the token expires after 1 hour and there is no refresh token (using the implicit flow) so, you will have to ask the user to sign-in again.

Flutter Auth on iOS hangs when retrieving token with code exchange

I have the following code in flutter trying to retrieve an oauth2 token via auth code with PKCE flow:
final FlutterAppAuth appAuth = FlutterAppAuth();
final request = AuthorizationTokenRequest(
B2C_CLIENT_ID,
B2C_REDIRECT_URI,
discoveryUrl: 'https://$B2C_DOMAIN/.well-known/openid-configuration',
scopes: ['openid', 'profile', 'offline_access'],
// promptValues: ['login']
);
final AuthorizationTokenResponse result =
await appAuth.authorizeAndExchangeCode(request);
When this code is run in iOS, the browser opens and I can see it tries to load the signin page, but then immediately closes. No exceptions are thrown or anything. The code basically hangs at appAuth.authorizeAndExchangeCode almost like it doesn't know that the browser has closed.
I am not sure what could be causing this.
The code correctly determines the url for showing credentials using the discoveryUrl (i.e. it makes the http request first using the discoveryUrl) but not sure why it basically hangs after.
I am using azureb2c for authentication here.
Edit
Ok turns out this is a problem with using azure b2c in particular as tried it with a different identity provider and works fine.
I managed to locate the issue and fix it now a login page shows in the browser. After entering credentials, browser closes, but code still hangs on appAuth.authorizeAndExchangeCode(request); and does not proceed.
Also found existing issue. on github: https://github.com/MaikuB/flutter_appauth/issues/182
I managed to solve this following the below answer on the Github repository of the flutter_appauth plugin.
https://github.com/MaikuB/flutter_appauth/issues/182#issuecomment-840707729
Eventually, all I had to do was to add a trailing slash to the redirect url parameter in AuthorizationTokenRequest.
(It looks like Azure AD appends on a trailing slash to the redirect url which causes the validation in AppAuth to fail).
My app worked correctly with the slash both on Android and iOS.
P.S. If this doesn't work for someone, try to adjust the redirect url in your App Registration as suggested in the respective thread https://github.com/MaikuB/flutter_appauth/issues/223.
I suspect this is related to the call to resumeExternalUserAgentFlow, so here is a plan of action for you:
Follow the steps in my blog post to get the AppAuth Swift + Carthage sample working - which also uses a Private URI Scheme. Use my online configuration details as specified in the blog post and you should have a working solution. I have just verified that my instructions still work.
Update the same sample to use your Azure AD configuration and see if it still works. If so then there is nothing wrong with AppAuth and the problem is in the Flutter layer.
If the Swift sample fails when you update to Azure AD configuration, add some print messages for the URL being supplied to resumeExternalUserAgentFlow in the AppDelegate class, and see if this is different to the original redirect URI. If the redirect URIs are different, reset to the original value and hopefully that will resolve things.

Auth0 checkSession call to renew return an HTML error page

I have a Single Page App using Auth0 Implicit Flow with Silent Authentication. I got the authentication part working just fine, but when I try to implement checkSession method to renew the session in the background (as per https://auth0.com/docs/libraries/auth0js/v9#using-checksession-to-acquire-new-tokens), the AJAX call to the auth0.com domain returns a 400 HTML error instead of a JSON one.
webAuth.checkSession({}, function (err, authResult) {
...
});
The error is Oops!, something went wrong, which I can see in my browser devtools Network Response tab.
There could be a misconfiguration in the system or a service outage. We track these errors automatically, but if the problem persists feel free to contact us.
Please try again.
I am not sure why there would be an HTML response, and not sure what I might be doing wrong. I have added my page's domain to the "Allowed Web Origins" list on the Auth0 application settings.
What I was missing was providing the redirectUri parameter to the checkSession call.
I also found out that I could find logs to these errors by going to the "Logs" menu on the Auth0 dashboard.

OKTA sign in widget is not rendering on page routing in Angular 7 application

I am using Angular 7.2 with #Okta/Okta-angular 1.2.1 and #okta/okta-signin-widget 2.19.0 into my angular application.
On first load of application, I am able to see the login widget but if start routing on other pages (which is not required authentication) and coming back on login page again either via app routing or via browser back button then unable to see the login okta-signin-widget. It's not re-rendering on page.
I found this problem also in okta-sign-in widget sample code. (https://github.com/okta/samples-js-angular/tree/master/custom-login)
Please provide suggestion to handle this issue.
I found the solution for this problem after adding below code into my login component:
ngOnDestroy(){
this.OktaSignInwidgetObject.remove();
}
where this.OktaSignInwidgetObjectis the instance of intial configuration object:
this.OktaSignInwidgetObject= new OktaSignIn(
{
baseUrl: 'https://{yourOktaDomain}'
/** other Configuration*/
}
);

BrowserField2 - salesforce oauth2 failing at Accept/Deny stage

I have a BlackBerry java-based app that works with salesforce data and uses oauth 2 for authentication. It has been working fine until recently when users have been complaining that once they get to the accept/deny salesforce oauth page, clicking on Accept button displays a salesforce 404 page.
I attached a debugger to the bb simulator (OS7) and found that everything was working fine up to the point where a POST is made to salesforce on pressing the ACCEPT button in the final stage of authentication/authorisation via salesforce oauth2 user agent flow. At this point, the post would succeed and the response body would contain some markup with a small JavaScript block that just performs a document.location.href assignment to force the browser to navigate to a new URL. I noticed that the URL was not what I was expecting - I was expecting to see the redirect_uri callback address + the access token etc data appended to the end of it (as per the sf oauth2 documentation). What I saw instead was a URL that when navigated to leads the user back to a login page with a message saying that they are attempting to access a resource that requires authentication.
If I perform the same flow in say chrome the URL after the post is what I expect. This all used to work just fine so I am confused as to why it would stop working all of a sudden. I've heard that Salesforce changed their oauth 2 implementation back in late 2011 slightly so I wonder if this has broken my client although I don't see how.
As an experiment I removed all of my code except for an embedded BrowserField and made it navigate to the oauth URL as constructed by combining consumer key and various other values as per the documentation and it still fails with a 404 page at the point of clicking on the accept button after a successful login.
If I try the same bootstrap oauth URL in the built in bb browser the full authentication flow works fine and I am eventually redirected to the final callback URL with access token information appended.
Has anyone else out there had trouble with oauth2 user agent flow on BrowserField (from field2 package)?
Have you tried using the "scope=mobile" parameter? This parameter puts you into a very simplified oauth flow that is optimized for blackberry...we've found they generally have trouble getting through the richer flows designed for iOS/Android. That said, I haven't heard of them having issues on BB7...only the 5 and sometimes 6 series
If that fails, could you open a support case with us?
Try also "display=mobile" and "scope=api web" (with a space), depending on what you are trying to access after OAuth.

Resources