1
votes

We are having issues getting the refresh tokens to work. Initially the user logs in using the web view from ADAL and gets a token. That token is used to call the Web API until it expires. Instead of getting a new token without the web prompt as we would expect, an error is logged on the server and the user is shown the login web prompt again.

From what we have read you are supposed to use AcquireTokenAsync on every call and let ADAL handle the tokens/refresh tokens.

Here is the error we get on the server when ADAL tries to get a new token using the refresh token. We've tried searching for that error but don't find much.

Encountered error during OAuth token request.

Additional Data

Exception details: Microsoft.IdentityServer.Web.Protocols.OAuth.Exceptions.OAuthInvalidScopeException: MSIS9330: The OAuth access token request received is invalid. A 'scope' parameter was received in the request and AD FS does not support any scope. Received scope: 'openid'. at Microsoft.IdentityServer.Web.Protocols.OAuth.OAuthToken.OAuthRefreshTokenRequestContext.Validate()

Are we missing something ? Is there a way to set the scope or does this just not work with the current versions we are using ? ADAL is the one making the post with the scope to the ADFS server.

We are NOT using Azure AD !

The call from the view controller in the iOS app:

PlatformParameters p = new PlatformParameters(this);

AuthenticationContext authContext = new AuthenticationContext("https://adfs.domain.com/adfs", false);

AuthenticationResult _authResult = await authContext.AcquireTokenAsync("https://webapi.domain.com", "E1CF1107-FF90-4228-93BF-26052DD2C714", “http://anarbitraryreturnuri/”, p);

Startup.Auth.cs in Web API:

public void ConfigureAuth(IAppBuilder app)
        {
            app.UseActiveDirectoryFederationServicesBearerAuthentication(
                new ActiveDirectoryFederationServicesBearerAuthenticationOptions
                {
                    MetadataEndpoint = ConfigurationManager.AppSettings["ida:AdfsMetadataEndpoint"],
                    TokenValidationParameters = new TokenValidationParameters()
                    {
                        ValidAudience = ConfigurationManager.AppSettings["ida:Audience"],
                    },
                }
        }

Here are the pieces we have:

  • Windows Server 2012 R2 with ADFS 3.0(on premises)
  • SsoLifetime = 60
  • TokenLifetime(relying party) = 10
  • ADAL 3.13.8
  • .NET Web API
  • Xamarin iOS app

Here are some of the posts we used to get this working:

http://www.cloudidentity.com/blog/2013/10/25/securing-a-web-api-with-adfs-on-ws2012-r2-got-even-easier/

http://www.cloudidentity.com/blog/2015/08/13/adal-3-didnt-return-refresh-tokens-for-5-months-and-nobody-noticed/

1

1 Answers

1
votes

The issue is in the ADAL source code. The error from the server log was pretty specific:

A 'scope' parameter was received in the request and AD FS does not support any scope. Received scope: 'openid'. The ADAL library sends a scope parameter when it tries to get a refresh token. ADFS 3.0 doesn't support the openid scope so it fails.

Download the ADAL code from github -- https://github.com/AzureAD/azure-activedirectory-library-for-dotnet

Open AcquireTokenHandlerBase.cs located here:

enter image description here

Remove the scope from the SendTokenRequestByRefreshTokenAsync call:

protected async Task<AuthenticationResultEx> SendTokenRequestByRefreshTokenAsync(string refreshToken)
    {
        var requestParameters = new DictionaryRequestParameters(this.Resource, this.ClientKey);
        requestParameters[OAuthParameter.GrantType] = OAuthGrantType.RefreshToken;
        requestParameters[OAuthParameter.RefreshToken] = refreshToken;
        //requestParameters[OAuthParameter.Scope] = OAuthValue.ScopeOpenId; **This line causes refresh to fail**

        AuthenticationResultEx result = await this.SendHttpMessageAsync(requestParameters).ConfigureAwait(false);

        if (result.RefreshToken == null)
        {
            result.RefreshToken = refreshToken;
            PlatformPlugin.Logger.Verbose(this.CallState,
                "Refresh token was missing from the token refresh response, so the refresh token in the request is returned instead");
        }

        return result;
    }

Clean and rebuild the projects. Replace the nuget references with the new DLLs. Make sure to include the platform DLL in the Xamarin iOS project.

enter image description here

Now when ADAL tries to get a refresh token it should succeed.

enter image description here