Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

access token / refresh token with MSAL

Tags:

msal

I'm moderately familiar with OAuth2 and the concepts of the AccessToken and RefreshToken.

It looks like MSAL is doing some work for us when using ClientApplicationBase.AcquireTokenSilentAsync().

I'm not clear as to whether it will always check the expiration of the current AccessToken and automatically refresh it (using the RefreshToken) on method call.

Regardless, is there a "best practice" for how often we should call AcquireTokenSilentAsync() ? Should we keep track of the expiration ourselves and call this method to update our bearer authentication header? Should we be calling AcquireTokenSilentAsync() on every Request? (doubtful)

I can't see how the GraphServiceClient (tangent topic, I know) using the DelegateAuthenticationProvider will do anything helpful WRT refreshing. Do we need to extend that class and perform our own refresh when the token is nearing expiration? I feel like this would/should be already in the SDK.

Thanks for any tips. -AJ

like image 232
AWeber Avatar asked Jul 13 '18 20:07

AWeber


People also ask

How do you refresh access tokens?

These client credentials and the refresh_token can be used to create a new value for the access_token . To refresh the access token, select the Refresh access token API call within the Authorization folder of the Postman collection. Next, click the Send button to request a new access_token .

How do I get Msal access token?

In MSAL, you can get access tokens for the APIs your app needs to call using the acquireTokenSilent method which makes a silent request(without prompting the user with UI) to Azure AD to obtain an access token.

How does Azure refresh token get access token?

Use the refresh token to get a new access token Access tokens are short lived, and you must refresh them after they expire to continue accessing resources. You can do so by submitting another POST request to the /token endpoint, this time providing the refresh_token instead of the code .

How do I refresh my MFA token?

Go to Services > Azure Partner (NCE) > Manage Refresh Token. In the Manual Update group, specify the authentication code that you received and click Update. Make sure that a message similar to Your refresh token has been successfully updated is shown.


1 Answers

Update Nov 2020

This answer was originally written for V2 of the MSAL client. Since then a V3 has been released which may work differently from V2.

Original answer

I'm not clear as to whether it will always check the expiration of the current AccessToken and automatically refresh it (using the RefreshToken) on method call.

A refresh token is automatically supplied when the offline_access scope is provided, if I understand this answer correctly

...you've requested the offline_access scope so your app receives a Refresh Token.

The description of AcquireTokenSilentAsync implies that when an refresh token is provided, it will check the expiration date on the token, and get a new one if it's expired or close to expiring.

If access token is expired or close to expiration (within 5 minute window), then refresh token (if available) is used to acquire a new access token by making a network call.

It will repeat this behavior until the refresh token is expired. Optionally you can force a refresh of the access token via the refresh token by utilizing the forceRefresh parameter on AcquireTokenSilentAsync

enter image description here

Lastly, I am going to quote this answer on SO since it gives a nice insight about MSAL and tokens

Just to make a small clarification, MSAL doesn't actually issue tokens or decide a token expiration, but rather ingests an acquires token from the Azure AD STS.

MSAL will automatically refresh your access token after expiration when calling AcquireTokenSilentAsync. .... The default token expirations right now are:

Access Tokens: 1 hour

Refresh Tokens: 90 days, 14 day inactive sliding window

(June 13th '17)

Regardless, is there a "best practice" for how often we should call AcquireTokenSilentAsync() ? Should we keep track of the expiration ourselves and call this method to update our bearer authentication header? Should we be calling AcquireTokenSilentAsync() on every Request?

The documentation also lists a 'Recommended call pattern' for calling the AcquireTokenSilentAsync. The documentation also mentions that

For both Public client and confidential client applications, MSAL.NET maintains a token cache (or two caches in the case of confidential client applications), and applications should try to get a token from the cache first before any other means.

Based on examples I've seen, including the recommended call pattern from the documentation, I would argue you could simply call AcquireTokenSilentAsyncand catch the MsalUiRequiredException as an indication that the token has expired and the user has to log in again.

I can't see how the GraphServiceClient (tangent topic, I know) using the DelegateAuthenticationProvider will do anything helpful WRT refreshing. Do we need to extend that class and perform our own refresh when the token is nearing expiration? I feel like this would/should be already in the SDK.

If I understand the DelegateAuthenticationProvider correctly, what it does is modify the requestMessage before we pass it to Graph. All we got to do is provide our access token with an authorization header for the request. We already know that when we fetch our access token, it is valid, so we can just add it.

        new DelegateAuthenticationProvider(async (requestMessage) =>
        {
            ConfidentialClientApplication cca = new ConfidentialClientApplication(_ClientId, _Authority, _RedirectUri, new ClientCredential(_ClientSecret), _UserTokenSessionCache.GetTokenCache(identifier, httpContext), _ApplicationTokenCache.GetTokenCache());
            AuthenticationResult result = await cca.AcquireTokenSilentAsync();
            requestMessage.Headers.Add("Authorization", result.CreateAuthorizationHeader());
            //OR
            requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", result.AccessToken);
        });

(There is no difference between either way of setting the headers)

I've been down this path and this does the trick for me. I highly advise reading their documentation, because it does gives a good insight in how to implement MSAL.Net.

I haven't had time yet to play around with the token durations yet. Nor the behavior if no refresh token is provided (if that's even possible)

I hope this helps!

like image 137
Bart de Ruijter Avatar answered Sep 21 '22 11:09

Bart de Ruijter