IdentityServer / IdentityServer3.AccessTokenValidation

OWIN Middleware to validate access tokens from IdentityServer3
Apache License 2.0
91 stars 149 forks source link

Unauthorized issue with latest SDk #140

Closed aviisingh closed 7 years ago

aviisingh commented 7 years ago

I am facing issue related to authentication for rest endpoint(web api + owin) with latest SDK. Works fine for some days but starts failing with unauthorized response(for each request) after some days for the same deployment and best part is redeployment of same package fixes the issue. Any idea for this behaviour?

leastprivilege commented 7 years ago

what's an SDK?

Did you turn on logging?

aviisingh commented 7 years ago

IdentityServer3.AccessTokenValidation 2.14.0 I dint enable logging.

sasachan commented 7 years ago

Hi @leastprivilege , I will replay the problem shared by @aviisingh.

I have enabled the logs via - appBuilder.SetLoggerFactory(new ConsoleLoggerFactory()); really good to know the internals. Based of this and real-time debugging I've realized the RAS keys are not matching. I have attached logs in detail at the bottom.

We have Identity server 4- with RSA keys are rolling out twice a day or at predefined window inside identity server 4 (not using x509) the client/resource do not know.

Now, if an service (OWIN based WebAPI-2) start and during this process connect to identity service welknown endpoint and for metadata that point of time it should have the information about keys it should respect to- After this it will start logic of default of "RetrieveMetadata" i.e refresh meta only after a day - (I think if im not really wrong)

Once RSA keys are refreshed at identity server, any following client should get accesstoken based of refreshed RSA keys. And this has a gap with the pattern to cache the keys at service (OWIN based WebAPI-2) "RetrieveMetadata".

What are the best practice to anticipate this scenario where Identity server RSA keys roll-out is alinged to service (OWIN based WebAPI-2) "RetrieveMetadata

` private void RetrieveMetadata() { if (_syncAfter >= DateTimeOffset.UtcNow) { return; }

        _synclock.EnterWriteLock();
        try
        {
            var result = AsyncHelper.RunSync(async () => await _configurationManager.GetConfigurationAsync());

            if (result.JsonWebKeySet == null)
            {
                _logger.WriteError("Discovery document has no configured signing key. aborting.");
                throw new InvalidOperationException("Discovery document has no configured signing key. aborting.");
            }

            var tokens = new List<SecurityToken>();
            foreach (var key in result.JsonWebKeySet.Keys)
            {
                var rsa = RSA.Create();
                rsa.ImportParameters(new RSAParameters
                {
                    Exponent = Base64UrlEncoder.DecodeBytes(key.E),
                    Modulus = Base64UrlEncoder.DecodeBytes(key.N)
                });

                tokens.Add(new RsaSecurityToken(rsa, key.Kid));
            }

            _issuer = result.Issuer;
            _tokens = tokens;

            _syncAfter = DateTimeOffset.UtcNow + _refreshInterval;
        }
        catch (Exception ex) 
        {
            _logger.WriteError("Error contacting discovery endpoint: " + ex.ToString());
            throw;
        }
        finally
        {
            _synclock.ExitWriteLock();
        }
    }`

Trace:

Authentication failed System.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10505: Unable to validate signature. The 'Delegate' specified on TokenValidationParameters, returned a null SecurityKey. SecurityKeyIdentifier: 'SecurityKeyIdentifier ( IsReadOnly = False, Count = 1, Clause[0] = System.IdentityModel.Tokens.NamedKeySecurityKeyIdentifierClause ) ' Token: '{"alg":"RS256","kid":"GI0fdt0P/SJzjdwGYZ1Iv/s10OsPL+uRBOg7EnHwrkA=","typ":"JWT"}.{"nbf":1489390896,"exp":1489392696,"iss":"https://fogscloud-iden.azurewebsites.net","aud":["https://fogscloud-iden.azurewebsites.net/resources","tid"],"client_id":"109133ee-c515-4418-b77c-87eb3a2d3299","http://schemas.microsoft.com/ws/2008/06/identity/claims/role":"TenantReader","aid":"0bd7028000ff4d8f8160a91068ae80ce","tid":"06165d47899848428317d1c3eeb2fcbf","scope":["tid"]}'. at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters) in c:\workspace\WilsonForDotNet45Release\src\System.IdentityModel.Tokens.Jwt\JwtSecurityTokenHandler.cs:line 935 at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateToken(String securityToken, TokenValidationParameters validationParameters, SecurityToken& validatedToken) in c:\workspace\WilsonForDotNet45Release\src\System.IdentityModel.Tokens.Jwt\JwtSecurityTokenHandler.cs:line 671 at Microsoft.Owin.Security.Jwt.JwtFormat.Unprotect(String protectedText) at Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationHandler.<AuthenticateCoreAsync>d__0.MoveNext()Authentication failed System.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException: IDX10505: Unable to validate signature. The 'Delegate' specified on TokenValidationParameters, returned a null SecurityKey. SecurityKeyIdentifier: 'SecurityKeyIdentifier ( IsReadOnly = False, Count = 1, Clause[0] = System.IdentityModel.Tokens.NamedKeySecurityKeyIdentifierClause ) ' Token: '{"alg":"RS256","kid":"GI0fdt0P/SJzjdwGYZ1Iv/s10OsPL+uRBOg7EnHwrkA=","typ":"JWT"}.{"nbf":1489390896,"exp":1489392696,"iss":"https://fogscloud-iden.azurewebsites.net","aud":["https://fogscloud-iden.azurewebsites.net/resources","tid"],"client_id":"109133ee-c515-4418-b77c-87eb3a2d3299","http://schemas.microsoft.com/ws/2008/06/identity/claims/role":"TenantReader","aid":"0bd7028000ff4d8f8160a91068ae80ce","tid":"06165d47899848428317d1c3eeb2fcbf","scope":["tid"]}'. at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters) in c:\workspace\WilsonForDotNet45Release\src\System.IdentityModel.Tokens.Jwt\JwtSecurityTokenHandler.cs:line 935 at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateToken(String securityToken, TokenValidationParameters validationParameters, SecurityToken& validatedToken) in c:\workspace\WilsonForDotNet45Release\src\System.IdentityModel.Tokens.Jwt\JwtSecurityTokenHandler.cs:line 671 at Microsoft.Owin.Security.Jwt.JwtFormat.Unprotect(String protectedText) at Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationHandler.<AuthenticateCoreAsync>d__0.MoveNext()'fogscloud.Cloud.Platform.Configuration.Api.exe' (CLR v4.0.30319: fogscloud.Cloud.Platform.Configuration.Api.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.Runtime\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Runtime.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'fogscloud.Cloud.Platform.Configuration.Api.exe' (CLR v4.0.30319: fogscloud.Cloud.Platform.Configuration.Api.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_64\Microsoft.ServiceFabric.Data.Interfaces\v4.0_5.0.0.0__31bf3856ad364e35\Microsoft.ServiceFabric.Data.Interfaces.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.

leastprivilege commented 7 years ago

Why are you rolling your keys that often??

regardless - the way Microsoft implemented discovery caching is, that they either wait of the cache to expire (24h by default) - or wait for a problem during signature validation.

If one of the events happen, the next time the discovery document is needed, it is being re-loaded from the server.

Is that in sync with your observations?