Refreshing Token using AcquireTokenSilentAsync fails only in Service API but works on a Console App
haricr opened this issue · 1 comments
If you think that your issue falls into the above categories, please fill in the form below.
Which Version of ADAL are you using ?
Microsoft.IdentityModel.Clients.ActiveDirectory.4.5.1
Which platform has the issue?
net45
What authentication flow has the issue?
- Web API - OBO
Is this a new or existing app?
This is a new app
Repro
I wrote to library that exposes following API
a. perform OBO for user token. Serialize and save the accessToken and TokenCache
b. refresh the token by deseriazling the cache
When i test this library using console App everything works fine
Then i exposed this library as a Service API. In the service API, the refresh always fails with error
Microsoft.IdentityModel.Clients.ActiveDirectory.AdalSilentTokenAcquisitionException: Failed to acquire token silently as no token was found in the cache. Call method AcquireToken
at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenSilentHandler.SendTokenRequestAsync()
I am calling the refresh 2 mins after the token generation, I validated with logs that the token cache is getting deserialized.
Code to refresh
RefreshTokenCache tokenCache = new RefreshTokenCache(tokenCacheData, this.Logger);
AuthenticationContext context = new AuthenticationContext(authority.AbsoluteUri, tokenCache);
ClientAssertionCertificate credential = new ClientAssertionCertificate(this.AppId, this.Certificate);
AuthenticationResult authResult = await context.AcquireTokenSilentAsync(this.Audience, credential, new UserIdentifier(oid, UserIdentifierType.UniqueId));
Token Cache
public class RefreshTokenCache : TokenCache
{
public string SerializedCache { get; set; }
public RefreshTokenCache(string cache)
{
this.AfterAccess = AfterAccessCacheNotification;
this.BeforeAccess = BeforeAccessCacheNotification;
this.SerializedCache = cache;
}
public void BeforeAccessCacheNotification(TokenCacheNotificationArgs args)
{
if (!string.IsNullOrEmpty(this.SerializedCache))
{
char[] cacheData = this.SerializedCache.ToCharArray();
this.Deserialize(Convert.FromBase64CharArray(cacheData, 0, cacheData.Length));
}
}
public void AfterAccessCacheNotification(TokenCacheNotificationArgs args)
{
this.SerializedCache = Convert.ToBase64String(this.Serialize());
}
}
Expected behavior
I am not sure what is the difference between running in Console App and exposing it as Service APIs
Actual behavior
Microsoft.IdentityModel.Clients.ActiveDirectory.AdalSilentTokenAcquisitionException: Failed to acquire token silently as no token was found in the cache. Call method AcquireToken
at Microsoft.IdentityModel.Clients.ActiveDirectory.Internal.Flows.AcquireTokenSilentHandler.SendTokenRequestAsync()
@haricr, did you read https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/wiki/Token-cache-serialization#custom-token-cache-serialization-in-web-applications--web-api ? the article in general explains the differences between a token cache for public client applications and for confidential client applications.