Token are cached
Once ADAL.NET has acquired a token for a user for a Web API, it caches it, along with a Refresh token. Next time the application wants a token, it can first call
AcquireTokenSilentAsync to verify if an acceptable token is in the cache:- If there is such a token and it has not expired, it's returned, which is fast
- If there is a token but it has expired,
AcquireTokenSilentAsyncwill use the cached refresh token in order to refresh the access token (request another access token and refresh token from Azure AD). - If no token is in the cache,
AcquireTokenSilentAsyncwill throw anAdalSilentTokenAcquisitionException, and the application will need to callsAcquireTokenAsync(which might require some user interaction)
Note ADAL v2 used to expose the refresh token because you had to handle refresh yourself. With ADAL v3, this is done automatically by the library
AcquireTokenAsync gets token from the cache
Like
AcquireTokenAsync, in ADAL.NET, AcquireTokenSilentAsync has several overrides, which are not available for public client applications. You'll see them later. For the moment, let's get interested in the last three overrides, which are for public client applications.
Unsurprisingly, the overrides are similar to the public application client overrides of
AcquireTokenAsync, and they take as parameters:- The
resourcefor which you want an access token. you can pass here either the Resource URI of a Web API, or the clientId of the target Web API. Both work. - The
clientIdparameter is the clientId/applicationId of the public client application. userIdis optional. It's still set from the DisplayableId of a userparametersis also still optional to describe the desired user interaction (See the same parameterAcquireTokenAsync). If you specifyPromptBehaviorswhich would induce some user interaction (Always,SelectAccount), the token acquisition is, nevertheless done silently (equivalent toRefreshSession). This behavior is becauseAcquireTokenSilentis ... silent, and therefore there is no user interaction.
Recommended pattern to acquire a token
Now that you have seen both
AcquireTokenAsync, AcquireTokenSilentAsync, it's the right moment to present the recommended usage pattern for calling these methods. The idea is that you want to minimize the number of signings for the user, and therefore you'd want to:- first try to acquire a token silently,
- and if this call fails you try to get one interactively.
Note that,
AcquireTokenSilent does not need to be called in the Client credentials flow (when the application acquires token without a user, but in its own name)
Note that
AcquireTokenSilent can fail for several reasons, such as the cache does not contain a token for the user, or the token has expired and cannot be refreshed. For these reasons, a call to AcquireTokenAsync will usually get a token. But there are also issues such as network problems, STS unavailability, etc., which won't be directly solvable. You will see them in more details in the article about best practices for Handling errors.
In ADAL.NET the recommended pattern is the following code snippet for public client applications:
// STS
string cloud = "https://login.microsoftonline.com";
string tenantId = "331e6716-26e8-4651-b323-2563936b416e";
string authority = $"{cloud}/{tenantId}";
// Application
string clientId = "65b27a1c-693c-44bf-bf92-c49e408ccc70";
Uri redirectUri = new Uri("https://TodoListClient");
// Application ID of the Resource (could also be the Resource URI)
string resource = "eab51d24-076e-44ee-bcf0-c2dce7577a6a";
AuthenticationContext ac = new AuthenticationContext(authority);
AuthenticationResult result=null;
try
{
result = await ac.AcquireTokenSilentAsync(resource, clientId);
}
catch (AdalException adalException)
{
if (adalException.ErrorCode == AdalError.FailedToAcquireTokenSilently
|| adalException.ErrorCode == AdalError.InteractionRequired)
{
result = await ac.AcquireTokenAsync(resource, clientId, redirectUri,
new PlatformParameters(PromptBehavior.Auto));
}
}
No comments:
Post a Comment