Refresh Tokens do not seem to work on iOS
janschoelchAtOK opened this issue · 4 comments
Which Version of ADAL are you using ?
ADAL 5.2.7
Which platform has the issue?
Xamarin.iOS / Xamarin.Forms (iOS)
Tested on simulators and devices running iOS12.0, iOS13.0 and iOS13.3
What authentication flow has the issue?
- Desktop / Mobile
- Interactive (no broker)
- Integrated Windows Auth
- Username Password
- Device code flow (browserless)
- Web App
- Authorization code
- OBO
- Web API
- OBO
Is this a new or existing app?
This is a new app or experiment
Environment
- ADFS 2016 (that is why I can not use MSAL)
- An ASP.NET Core WebAPI
- An app that talks to the api and needs a token for that
Repro
We currently develop a Xamarin.Forms application in an environment where MSAL is not applicable (as we must use ADFS 2016 and no federation to AzureAD is possible...). We authenticate using ADAL.NET in a pretty standard manner (see code below).
private AuthenticationContext _context = new AuthenticationContext(_authority) { iOSKeychainSecurityGroup = NSBundle.MainBundle.BundleIdentifier };
public async Task<AuthenticationResult> AuthenticateAsync()
{
try
{
return await _context.AcquireTokenSilentAsync(
_resource,
_clientId,
).ConfigureAwait(false);
}
catch (AdalSilentTokenAcquisitionException)
{
return await _context.AcquireTokenAsync(
_resource,
_clientId,
new Uri(_returnUri),
new PlatformParameters(_rootViewController),
UserIdentifier.AnyUser,
_queryParams
).ConfigureAwait(false);
}
catch (AdalServiceException e)
{
return null;
}
catch (AdalException e)
{
return null;
}
}
The token lifetimes are configured as follows:
- Access Token lifetime: 1 hour
- Refresh Token lifetime: 2 days
Expected behavior
On Android, this works without any issue (our Android code is almost the same - we only differ in PlatformParams as these are platform specific). After e.g. 2 hours (AT is expired), ADAL uses the RT and replaces the AT in the token cache by a new one. This is when the user can see the ADAL popup for a blink of a second - but there are no credentials needed to be entered.
Actual behavior
On iOS, after the AT is expired, the login UI is shown again and asking the user to enter her/his credentials. It seems like ADAL is not using or (de-)serializing the RT correctly. I can see in the logs that there is an 401 error - this also appears on Android (where I am able to get an AT by the RT).
Possible Solution
No idea!
Additional context/ Logs / Screenshots
Here are the outputs of ADAL:
0200 com.package.sample[94169:550497318] 2020-05-07T15:17:21.3064140Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: ADAL PCL.iOS with assembly version '5.2.7.0', file version '5.2.7.0' and informational version '5.2.7' is running...
2020-05-07 17:17:21.306654+0200 com.package.sample[94169:550497318] 2020-05-07T15:17:21.3066410Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: === Token Acquisition started:
CacheType: Microsoft.IdentityModel.Clients.ActiveDirectory.TokenCache (1 items)
Authentication Target: User
2020-05-07 17:17:21.308871+0200 com.package.sample[94169:550497318] 2020-05-07T15:17:21.3088500Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: Loading from cache.
2020-05-07 17:17:21.310762+0200 com.package.sample[94169:550497318] 2020-05-07T15:17:21.3107460Z: 00000000-0000-0000-0000-000000000000 - AdalLoggerBase.cs: Deserialized 1 items to token cache.
2020-05-07 17:17:21.310889+0200 com.package.sample[94169:550497318] 2020-05-07T15:17:21.3108790Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: Looking up cache for a token...
2020-05-07 17:17:21.310980+0200 com.package.sample[94169:550497318] 2020-05-07T15:17:21.3109690Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: An item matching the requested resource was found in the cache
2020-05-07 17:17:21.311079+0200 com.package.sample[94169:550497318] 2020-05-07T15:17:21.3110680Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: A matching entry was found in the cache
2020-05-07 17:17:21.311160+0200 com.package.sample[94169:550497318] 2020-05-07T15:17:21.3111500Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: An expired or near expiry token was found in the cache
2020-05-07 17:17:21.311249+0200 com.package.sample[94169:550497318] 2020-05-07T15:17:21.3112380Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: A matching item (access token or refresh token or both) was found in the cache
2020-05-07 17:17:21.311344+0200 com.package.sample[94169:550497318] 2020-05-07T15:17:21.3113330Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: Refreshing the AT based on the RT.
2020-05-07 17:17:21.311424+0200 com.package.sample[94169:550497318] 2020-05-07T15:17:21.3114160Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: Refreshing access token...
2020-05-07 17:17:21.328627+0200 com.package.sample[94169:550497300] 2020-05-07T15:17:21.3286060Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: Response status code does not indicate success: 401 (Unauthorized).
2020-05-07 17:17:21.328794+0200 com.package.sample[94169:550497300] 2020-05-07T15:17:21.3287820Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: A service exception occurred
2020-05-07 17:17:21.328923+0200 com.package.sample[94169:550497300] 2020-05-07T15:17:21.3289120Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: IsDeviceCode? False
2020-05-07 17:17:21.329023+0200 com.package.sample[94169:550497300] 2020-05-07T15:17:21.3290110Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: Service returned error
2020-05-07 17:17:21.329106+0200 com.package.sample[94169:550497300] 2020-05-07T15:17:21.3290970Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: TokenResponse ? True
2020-05-07 17:17:21.329203+0200 com.package.sample[94169:550497300] 2020-05-07T15:17:21.3291930Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: Error Code(s): 401
2020-05-07 17:17:21.329294+0200 com.package.sample[94169:550497300] 2020-05-07T15:17:21.3292850Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: Re-throwing a service exception with token response details
2020-05-07 17:17:21.329547+0200 com.package.sample[94169:550497300] 2020-05-07T15:17:21.3295350Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: Either a token was not found or an exception was thrown.
2020-05-07 17:17:21.329693+0200 com.package.sample[94169:550497300] 2020-05-07T15:17:21.3296820Z: 16448135-e06f-cc14-9a69-835dd9334c30 - AdalLoggerBase.cs: Cannot invoke the broker directly, may require install ...
- ADAL finds and access token, but it is expired
- ADAL proceeds to refresh the RT
- ADFS returns a 401 error
The 401 error is concerning. ADAL does not retry 401 errors. I suppose you could attempt to retry the silent call to see what happens. ADAL does not parse tokens, it just extracts them.
Is ADFS configured in a special way, or with proxy settings or smth?
Not enough info and cannot reproduce this.
@bgavrilMS It was indeed connected to proxy configuration issues. Thanks for pointing this out, this saved us days and days of research.
And the story gets even better as we finally managed to migrate to MSAL last week! :-)
Thank you for following up @janschoelchAtOK !