IdentityServer / IdentityServer3.AccessTokenValidation

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

Support for IdentityServer4 Tokens in IdentityServer3.AccessTokenValidation #108

Closed zngreg closed 7 years ago

zngreg commented 7 years ago

Hi,

I hope this is the right platform to ask this question. I have IdentityServer4 server and now I need to add a .net 4.6.1 Web Api as a scope (Resource), In the the scope itself I can't reference IdentityServer4.AccessTokenValidation so I figured I need IdentityServer3.AccessTokenValidation. My problem is that I can't seem to successfully validate a token generated in an IdentityServer4 using this library since I'm getting Error 401 Unauthorized when accessing secured api calls even with a valid token on a request header.

If there's anyone experienced a similar issue and managed to get it sorted or else if it's relevant for this repository and there's a way I can be assisted i will greatly appreciate it.

leastprivilege commented 7 years ago

You need to turn on logging to see what's going on. Do that and let us know.

https://identityserver.github.io/Documentation/docsv2/consuming/diagnostics.html

wojciechrak commented 7 years ago

Hi, I have a similar issue. I have IdentityServer4, and an access_token obtained through client credentials flow. But my WebAPI does not validate it. I am running IdSrv4 in Kestrel and I don't see any activity when invoking WebAPI.

Logs:

Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationMiddleware Error: 0 : Authentication failed
System.InvalidOperationException: Sequence contains no elements
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
   at IdentityServer3.AccessTokenValidation.DiscoveryDocumentIssuerSecurityTokenProvider.<RetrieveMetadata>b__1(JsonWebKey key) in c:\local\identity\server3\AccessTokenValidation\source\AccessTokenValidation\Plumbing\DiscoveryDocumentIssuerSecurityTokenProvider.cs:line 152
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ResolveIssuerSigningKey(String token, SecurityToken securityToken, SecurityKeyIdentifier keyIdentifier, TokenValidationParameters validationParameters) in c:\workspace\WilsonForDotNet45Release\src\System.IdentityModel.Tokens.Jwt\JwtSecurityTokenHandler.cs:line 1295
   at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters) in c:\workspace\WilsonForDotNet45Release\src\System.IdentityModel.Tokens.Jwt\JwtSecurityTokenHandler.cs:line 940
   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()
    ProcessId=11520
    DateTime=2016-10-08T09:16:56.2685575Z

Edit

I figured it out. I had to add .SetSigningCredential(cert) in IdentityServerBuilder chain. Previously I had .SetTemporarySigningCredential().

For my cert I am using a localhost cert (I think it's from ISSExpress). How can I generate a proper (self-signed) certificate then?

fjunqueira commented 7 years ago

@wojciechrak can you post your server and client configs? Even using .SetSigningCredential(cert) i get the exact same error you had.

Thanks!

UPDATE:

Nevermind, i forgot to app.UseCookieAuthentication(), it is working now.

wijnsema commented 7 years ago

I keep getting this same error. My Identity Server 4 is working OK in a number of scenarios. However I need to validate the token on a .NET Full Framework Web Api, for which I use the IdentityServer3.AccessTokenValidation, giving the before mentioned error:

Microsoft.Owin.Security.OAuth.OAuthBearerAuthenticationMiddleware Error: 0 : Authentication failed
System.InvalidOperationException: Sequence contains no elements
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
   at IdentityServer3.AccessTokenValidation.DiscoveryDocumentIssuerSecurityTokenProvider.<RetrieveMetadata>b__1(JsonWebKey key) in c:\local\identity\server3\AccessTokenValidation\source\AccessTokenValidation\Plumbing\DiscoveryDocumentIssuerSecurityTokenProvider.cs:line 152
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ResolveIssuerSigningKey(String token, SecurityToken securityToken, SecurityKeyIdentifier keyIdentifier, TokenValidationParameters validationParameters) in c:\workspace\WilsonForDotNet45Release\src\System.IdentityModel.Tokens.Jwt\JwtSecurityTokenHandler.cs:line 1295
   at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateSignature(String token, TokenValidationParameters validationParameters) in c:\workspace\WilsonForDotNet45Release\src\System.IdentityModel.Tokens.Jwt\JwtSecurityTokenHandler.cs:line 940
   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()
    ProcessId=17344
    DateTime=2016-11-16T11:37:30.4829567Z

I tried using https, since there is no RequireHttpsMetadata = false option in this middleware, but that didn't help. Also tried the .SetSigningCredential(cert), didn't work either.

Isn't this a bug? The log shows an InvalidOperationException because there are no elements in the sequence. It would be better to check the sequence and generate a more informative error message.

No criticism, just trying to help.

Ronald Wijnsema

oakdemirci commented 7 years ago

Happy new year to everyone... I got {"Response status code does not indicate success: 401 (Unauthorized)."} error from a .NET framework web api. I can make ASP.net Core web api calls btw. I want to ask your help and opinion. x509certificate is a local created cert. I updated IdentityServer3.AccessTokenValidation to v2.13.0 Regards and thanks for your great effort.

IdentityServer 4 side:

public void ConfigureServices(IServiceCollection services)
        {
                services
                .AddIdentityServer()                
                //.AddTemporarySigningCredential()
                .AddSigningCredential(x509Certificate)
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryClients(Config.GetClients())
                .AddAspNetIdentity<ApplicationUser>();
}

Config.cs

public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource("AuthorizationWebApi","Authorization Web API .NET Core"),
                new ApiResource("AuthorizationWebApiNetFramework","Authorization Web API NET Framework")
            };

        }
    public static IEnumerable<Client> GetClients()
    {
        return new List<Client> {
            new Client
            {
                ClientId = "MYUX",
                ClientName = "MYUX MVC Client",
                AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
                RequireConsent = false,
                ClientSecrets= {new Secret("abcdef".Sha256()) },
                RedirectUris = { "http://localhost:5002/signin-oidc" },
                PostLogoutRedirectUris = {"http://localhost:5002"},

                AllowedScopes = {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,                        
                    "custom.profile",
                    "AuthorizationWebApi",
                    "AuthorizationWebApiNetFramework"
                },
                AllowOfflineAccess = true
            }
        };
    }

.NET Framework APİ Side

 public void Configuration(IAppBuilder app)
        {
            //ConfigureAuth(app);
            app.UseCookieAuthentication(new CookieAuthenticationOptions());
            app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
            {
                Authority = "http://www.saglikolsun.com:5000",
                ValidationMode = ValidationMode.ValidationEndpoint,
                RequiredScopes = new[] { "AuthorizationWebApiNETFramework" }

            });
            //configure web api
            var config = new HttpConfiguration();
            config.MapHttpAttributeRoutes();

            //require authentication for all controllers

            config.Filters.Add(new AuthorizeAttribute());

            app.UseWebApi(config);
        }

Calling side:

try
            {
                ViewData["Message"] = "Authorization Test.";
                var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");
                var authorizationApiClient = new HttpClient();
                authorizationApiClient.SetBearerToken(accessToken);
                var content = await authorizationApiClient.GetStringAsync("http://localhost:13243/values");
                return View();
            }
            catch (Exception ex)
            {
                throw;
            }
leastprivilege commented 7 years ago

We had a bug in the .net core middleware - that is fixed now -

you can exercise all framework/middleware/token type combination in this test project:

https://github.com/IdentityServer/CrossVersionIntegrationTests

Let me know if you run into problems.