Is it possible to use MSAL.js to get refresh token? - authentication

I want to integrate with Miscrosoft Outlook. I am able to login with MSAL.js and get an access token, but I am not able to get a refresh token. Is there a way to do it?

I'll assume that since you're using the MSAL.js (https://github.com/AzureAD/microsoft-authentication-library-for-js) that you're using implicit flow for authentication and authorization.
Implicit flow doesn't support refresh tokens, but you can request a new token silently. This is done similarly to how you request the token (id or access) in the first place. Unfortunately, I haven't found that MSAL.js does this transparently and I've needed to detect expired tokens and request the new tokens in my code. You can read more about refreshing tokens here.
Alternatively, if what you're implementing allows you to use one of the other MSAL libraries (for example, the .Net one) then you can use one of the other OAuth flows that explicitly support refresh tokens.

I couldn't find any answer in the MSAL.js documentation, however this source code comment suggests you can renew a token manually by passing only the clientId as your scope to acquireTokenSilent.
To renew idToken, please pass clientId as the only scope in the Authentication Parameters

I use msal v1.4.0
I remove 2 keys in storage (see picture) then call acquireTokenSilent again to get new access token.
Code to remove those 2 keys:
const keys = Object.keys(sessionStorage).filter(x => x.indexOf('authority') > 0)
keys.forEach(x => sessionStorage.removeItem(x))

Related

best practices for refreshing access tokens automatically

I'm building a react native app which uses the spotify web api. I'm using the authorization code flow to authorize a user. First I get a authorization code which can be used to obtain an access token and a refresh token. Everything works!
The problem is: an access token is only valid for a limited amount of time. That's where the refresh token comes in. I understand this concept, but I'm breaking my head about how to implement this.
Let's say a users opens the app, requests an access token and uses this for some time. Then, the user closes the app. After 15 minutes, the users opens the app again. The access token has now expired, so I need to request a new access token.
I've come op with several "solutions". Can someone point me to the correct solution?
Solution 1:
Every time the user opens the app, I request a new access token and use this. Problem: when the user uses the app longer than the valid time of the access token, I won't work anymore.
Solution 2:
I use the access token that's stored in the secure storage on every request. When a request comes back with 'access token invalid' (I don't know the exact error code but you guys know what I mean), I request a new access token with the stored refresh token, and then I send the previous command again (with the new access token). But my question here is: can I use some kind of "wrapper function" which checks the response of the request, and if the response is "access token invalid", it automatically requests a new access token and runs the previous request again.
I think certainly correct solution is solution 2,and i think its clear enough.
and for using solution 2 you need somthing like wrapper function,yes its intelligently.
so you should use interceptor:
what is interceptor ?
You can intercept requests or responses before they are handled by then or catch.
in link below there is a good example of implementing refresh token in axios interceptor:
https://gist.github.com/Godofbrowser/bf118322301af3fc334437c683887c5f
I agree that Solution 2 is the best, each time you do a request you can check to see if the Access Token has expired, and if it has then you can request a new Access Token using the Refresh Token as you mentioned and then make your request, in my own project I do this in a FormatRequestHeadersAsync method which calls a CheckAndRenewTokenAsync method where I perform the following check, here shown in C#:
if(AccessToken?.Refresh != null && (AccessToken.Expiration < DateTime.UtcNow))
{
AccessToken = await GetRefreshTokenAsync(
AccessToken.Refresh,
AccessToken.TokenType,
cancellationToken);
}
You can store the Access Token and the Refresh Token and then use something similar to this before you make each request to the API this will refresh your token and then you can store the new Access Token and the existing Refresh Token.

how to obtain a refresh token in Auth0 using Lock and react native

In a react native app, how do you obtain a refresh token. I see in the docs that you can call the refresh token endpoint directly via the delegation endpoint in the REST API - but is there a more abstracted way to do it using the Auth0 lock component? Perhaps some sort of setting that is "remember login" and does all the plumbing for you?
If not, then to implement it ourselves would we call the refresh token service on every app start? And if so, do we make REST call directly or should we do it through an auth0 library of some sort?
Is there sample code that uses the library that shows needed steps like
check that the existing token has not expired
obtain a refresh token
redeem refresh token for access token
Or, have these steps been abstracted away by the library in some way?
The id_token that you receive as the outcome of user authentication follows the OpenID Connect specification so it will include an exp claim that you can check in order to detect expiration.
exp: Expiration time on or after which the ID Token MUST NOT be accepted for processing. The processing of this parameter requires that the current date/time MUST be before the expiration date/time listed in the value. Implementers MAY provide for some small leeway, usually no more than a few minutes, to account for clock skew. Its value is a JSON number representing the number of seconds from 1970-01-01T0:0:0Z as measured in UTC until the date/time.
(emphasis is mine; source: OpenID Connect)
If the offline_access scope is included when performing the authentication process you should get a refresh token issued alongside the ID token.
According to react-native-lock documentation you can then use the authenticationAPI() method to get an Authentication API client that can be used to refresh user's token.
The specific call can be seen in the react-native-auth0 documentation:
.authentication('{YOUR_CLIENT_ID}')
.refreshToken('user refresh_token')
.then(response => console.log(response))
.catch(error => console.log(error));

What is the first parameter for Firebase.Auth.GoogleAuthProvider.GetCredential?

The new Firebase for Unity support has just been released into Beta and I am trying to implement Auth with it. I already have a Google sign-in that implements the oauth2 flow using an auth code from GooglePlayGames.PlayGamesPlatform.Instance.GetServerAuthCode and sending it to a server that exchanges it for an access token using the https://www.googleapis.com/oauth2/v4/token endpoint.
I assume this access token is the second parameter of the Firebase.Auth.GoogleAuthProvider.GetCredential method, but what is the ID Token that the first parameter is asking for? Is that the token obtained from GooglePlayGames.PlayGamesPlatform.Instance.GetIdToken (same as GoogleAuthUtil.GetToken, if my reading of the docs/code is correct)?
If this is the case, why are both required? I thought the access token was all that was needed to authenticate a user with google cloud services and that the ID Token was being phased out.
Edit: After some testing, I found that passing the ID Token obtained from GooglePlayGames.PlayGamesPlatform.Instance.GetIdToken does allow Firebase to authenticate. Problem is, it asks for the user's email address every time. I'd like to avoid this if possible.
What is the difference between GetToken, GetAccessToken and GetIdToken, aside from the fact that GetIdToken requires a callback?
I managed to "hack" this in order to get it working... But still i think the correct method should only be using GetServerAuthCode but I cannot make it work with that.
Do your normal process of getting idToken and AccessToken the first time, when you log in to firebase get the user's email and store it in playerprefs. Then the second time if you already have the email you do this:
AndroidJavaClass authUtil = new AndroidJavaClass("com.google.android.gms.auth.GoogleAuthUtil");
AndroidJavaClass unity = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
AndroidJavaObject currentActivity = unity.GetStatic<AndroidJavaObject>("currentActivity");
string idToken = authUtil.CallStatic<string>("getToken", currentActivity, PlayerData.Email, "audience:server:client_id:XXXXXXXXXX-xxxxxxxxxxxxxx.apps.googleusercontent.com"); // your client id, should be a number a dash and then a bunch of numbers and letters
string accessToken = authUtil.CallStatic<string>("getToken", currentActivity, PlayerData.Email, "oauth2:https://www.googleapis.com/auth/plus.me");
Hope it helps although it would be greatif someone posts a solution with GetServerAuthCode cause that is the correct way

How do I test refreshing my google access token using a refresh token

I am a fair way through implementing an actionscript OAuth library which I am initially testing with Google's Drive Api.
I know how you are supposed to refresh an access token using your refresh token but my question is how do I test it?
How do I make my access_token expire so that I test my code that catches the error, attempts a refresh and then re-loads the initial request? If I can only do this once a week (or however often they expire) it's going to take a while to get it right!
Thanks
If you're looking to test your code, you don't actually need to invalidate or expire the access token. Simply make a (say) Drive call with a null access token and you will receive the same 401 response that you would have got with an expired access token.
Well, judging by the lack of responses to this question I am assuming that there is no way to do this.
This page:
https://developers.google.com/youtube/v3/guides/authentication#installed-apps
describes how to revoke an access or refresh token by using this url:
https://accounts.google.com/o/oauth2/revoke?token={token}
but then says:
The specified token can be an access token or a refresh token. If the token is an access token and it has a corresponding refresh token, the refresh token is also revoked.
So if you just want to revoke an access token you aren't able to.
I think the only solution is to wait for the access token to expire (seems to take an hour) then go about testing your app.
I'll be very happy if anyone tells me a faster way to make the token expire.
I handle this testing by simply making note of an expired access_token. Then when I need to test how my app deals with an expired token I simply give the app that expired token to work with. This way, for example, I can test that requests with an expired token will fail as expected.
The easiest way of doing it is using the OAuth Playground 2.0
https://developers.google.com/oauthplayground/
In step 2 especially, you can try refreshing your access token with a refresh token.
Additionally, in the setting (the gear icon), you can set up your own OAuth Credentials to test it out for your own API project.
Im using nodemailer. When setting the options for the transporter object, you can specify an 'expires' time. There isn't any documentation I found on that option but I'm sure you can figure it out. :)
I haven't found a way to shorten the expiration time on an access token either.
In fact you can't even generate another refresh_token unless you revoke access. I don't think you can generate another refresh_token even if you let the access token expire, although I have to wait an hour to test this.
I did find out that if you send the refresh_token and the authorization token is still active, you just get the same live token back although the expiration time is reset.

How can I use Google's OpenID and/or OAuth services to login and allow access to APIs with only ever one prompt to the user?

I am attempting to create a login system for my website that permits both authentication via Google's API and access to any of the OAuth-supported Google Data APIs while ideally only showing the user one prompt ever, no matter if he's creating an account or logging into his existing one. I want to minimize the number of times he's asked for approval.
I am aware that Google provides Hybrid OpenID/OAuth for this purpose, but the issue is that every time I add OAuth extensions to my OpenID request, it never remembers the user's approval for that request. Is there any way for the approval to be remembered when I am doing Hybrid OpenID/OAuth? If I just do OpenID without OAuth extensions, everything is remembered just fine and it doesn't keep bugging the user with the prompt.
Here are the pertinent extensions I'm sending in addition to my OpenID request, which result in me getting an OAuth request token (good) but cause the approval to never get remembered (bad).
PHP syntax:
$args["openid.ns.ext2"] = 'http://specs.openid.net/extensions/oauth/1.0';
$args["openid.ext2.consumer"] = 'www.MYSITE.com';
$args["openid.ext2.scope"] = 'http://www-opensocial.googleusercontent.com/api/people/';
$args["openid.mode"] = 'checkid_setup';
$args["openid.realm"] = 'http://www.MYSITE.com/';
Is it normal for Hybrid OpenID/OAuth to act this way (not remembering the last OAuth authorization)? What is the best way to get around this? I have thought of storing cookies on the user's computer to link to somewhere in my database so I could use the last access token again, etc... (the issue here being I don't know whose token to look up unless I know who the user is...a circular problem). And doing an OpenID-only request to get his user ID to see if he has an account in order to look up his access token, followed by an OpenID+OAuth request (if an access token for him isn't stored) would result in two prompts, which really wouldn't help.
It also seems like Hybrid only supports OAuth 1.0, which I think is fine until 2015, so it's not an issue right now for me. I am assuming they will support OAuth 2.0 in the future.
Is checkid_immediate relevant to this in any way? I'm just not sure how to use this to accomplish what I want.
I would suggest using OAuth 2.0. This supports getting both identity and access to APIs -- so accomplishes the same end goal, but is much easier than OAuth 1 Hybrid.
Take a look here:
https://developers.google.com/accounts/docs/OAuth2Login
The scopes you're trying to access are included in the URL (see "Forming the URL"). The referenced doc lists the scopes required for getting identity/profile information. You can simply add additional scopes to the string, comma-delimited in order to request access to other APIs. The resulting access token will access both the APIs and identity information (via the UserInfo API endpoint mentioned).
That said, what you're trying to do with OpenID 2.0/OAuth 1 hybrid should work-- and the user should see a checkbox for "remembering" the authorization. If you really want to debug this further, it'd be helpful to have a webpage you can point to which kicks off this authentication+authorization flow so we can see what's happening.
I figured out that checkid_immediate (and x-has-session, not sure if that's needed or even working) is allowing me to determine whether or not a user is logged in without prompting him, and if he is, it is giving me a claimed_id by which I can identify the user. That's exactly what I needed. The original question is solved, but I do want to figure out how to use identify with OAuth 2.0 because I have already implemented that.
Furthermore, I've noticed that when using OpenID/OAuth that the user still gets asked to authorize OAuth even after he's authorized OpenID. I can't see the advantage to the hybrid approach from the user's perspective.
If the user is logged out of Google, that's a total of three prompts just to sign up for my website and grab his name and profile image.
If anyone wondered, here are the steps necessary to get Hybrid OpenID/OAuth completely working (an overview). I was confused thoroughly throughout this process, so I hope this helps someone.
Do normal OpenID handshake and add on AX extensions for OAuth 1.0.
Use 'checkid_immediate' to permit probing for an active Google session without prompting the user. Use *claimed_id* as a unique identifier to link the user to your database.
If 'setup_needed' is returned, use 'checkid_setup' so the user is prompted and verified before continuing.
This leaves you with two possibilities. *checkid_immediate* returning immediately giving you a claimed_id, or a claimed_id coming through after *checkid_setup* (basically sign-up) succeeds.
Hybrid OpenID/OAuth 1.0 will give you an authorized request token.
Use the authorized request token to get an access token (you only need to call OAuthGetAccessToken)
Use that OAuth 1.0 access token to do whatever you want.
I was successful in using OAuthGetAccessToken to get an access token from the authorized request token my Hybrid OAuth dance, omitting the 'oauth_verifier' parameter (irrelevant to Hybrid).
I was successful in using OAuthGetAccessToken to get an access token after my Hybrid OAuth dance, omitting the 'oauth_verifier' parameter (irrelevant to Hybrid).
In a PHP/Zend environment:
$config = array(
'accessTokenUrl' => 'https://www.google.com/accounts/OAuthGetAccessToken',
'consumerKey' => $consumer_key,
'consumerSecret' => $consumer_secret
);
$consumer = new Zend_Oauth_Consumer($config);
$zendRToken = new Zend_Oauth_Token_Request(); // create class from request token we already have
$zendRToken->setToken($requestToken);
try{
$accessToken = $consumer->getAccessToken(array(
'oauth_token' => $requestToken,
// 'oauth_verifier' => '', // unneeded for Hybrid
'oauth_timestamp' => time(),
'oauth_nonce' => md5(microtime() . mt_rand()),
'oauth_version' => '1.0'
), $zendRToken);
} catch (Zend_Oauth_Exception $e){
echo $e->getMessage() . PHP_EOL;
exit;
}
echo "OAuth Token: {$accessToken->getToken()}" . PHP_EOL;
echo "OAuth Secret: {$accessToken->getTokenSecret()}" . PHP_EOL;