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,
AcquireTokenSilentAsync
will 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,
AcquireTokenSilentAsync
will 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
resource
for 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
clientId
parameter is the clientId/applicationId of the public client application. userId
is optional. It's still set from the DisplayableId of a userparameters
is also still optional to describe the desired user interaction (See the same parameterAcquireTokenAsync
). If you specifyPromptBehaviors
which would induce some user interaction (Always
,SelectAccount
), the token acquisition is, nevertheless done silently (equivalent toRefreshSession
). This behavior is becauseAcquireTokenSilent
is ... 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