IdentityServer / IdentityServer4.AccessTokenValidation

IdentityServer Access Token Validation for ASP.NET Core
Apache License 2.0
544 stars 214 forks source link

An item with the same key has already been added. Key: idsrv4:tokenvalidation:token #32

Closed mikeandersun closed 7 years ago

mikeandersun commented 7 years ago

This is my code to secure my api :

 app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
            {
                Authority = "http://localhost:5000",
                ScopeName = "api1",
                RequireHttpsMetadata = false
            });

but when call the api in an angular client with access token ('Authorization': 'Bearer ' + accesstoken) I get this error: An item with the same key has already been added. Key: idsrv4:tokenvalidation:token

What causes to idsrv4:tokenvalidation:token add more that one?

leastprivilege commented 7 years ago

It doesn't - are you sure you only have 1 instance of the middleware in your pipeline?

mikeandersun commented 7 years ago

The issue raises when ScopeName value not in client scopes, in the following code the api2 not added to the client scopes in IdentityServer4 server.

  app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
            {
                Authority = "http://localhost:5000",
                ScopeName = "api2",
                RequireHttpsMetadata = false
            });

IMO, wherever developer hard coded values like this case a log record or an exception raising is needs.

leastprivilege commented 7 years ago

I still don't understand why you would get the above exception.

mikeandersun commented 7 years ago

Change ScopeNamein this code on your resource server(api) project and call an api in it from a js client with Implicit flow.

 app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
            {
                Authority = "http://localhost:5000",
                ScopeName = "not_exits_in_client_scopes",
                RequireHttpsMetadata = false
            });
leastprivilege commented 7 years ago

I tried it - got back a 403 as expected...

brockallen commented 7 years ago

All set on this issue? Can we close?

cmills2000 commented 7 years ago

I am seeing this issue as well. Everything works fine locally, but when I deploy it, I get this issue and I'm not sure why. Only one instance of it in the middleware. What's more it seems to break [Authorize] attribute on my api, since now its completely open.

I have the "/Identity" test action and its returning claims for a login that I did via the web (/Account/Login), even in incognito mode. Perhaps there is a conflict between the IdentityServer authentication and the regular ASP.NET authentication. Weird that it works locally though.

brockallen commented 7 years ago

@cmills2000 You're deploying to azure? And @mikeandersun, did you only see this when deploying to azure, or did you also see it when it was local?

cmills2000 commented 7 years ago

Yes I am deploying to Azure.

On Dec 2, 2016 11:31 AM, "Brock Allen" notifications@github.com wrote:

You're deploying to azure? And @mikeandersun https://github.com/mikeandersun, did you only see this when deploying to azure, or did you also see it when it was local?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/IdentityServer/IdentityServer4.AccessTokenValidation/issues/32#issuecomment-264541371, or mute the thread https://github.com/notifications/unsubscribe-auth/AA3wUK68B6qZTRdKl_bTiY56ksKk7_HFks5rEHH6gaJpZM4KyXtE .

brockallen commented 7 years ago

I wonder if they're somehow re-using HttpContext instances. There was a similar issue in the ASP.NET Core to OWIN bridge layer, and this issue reminded me of it. Perhaps @Tratcher might know?

Tratcher commented 7 years ago

What's the stack trace for the error?

cmills2000 commented 7 years ago

System.ArgumentException System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(Object key) [external code] IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationMiddleware.d7. MoveNext() [external code] IdentityServer4.Hosting.IdentityServerMiddleware.d3.MoveNext() [external code] IdentityServer4.Hosting.FederatedSignOutMiddleware.d6.MoveNext() [external code] IdentityServer4.Hosting.AuthenticationMiddleware.d2.MoveNext() [external code] IdentityServer4.Hosting.BaseUrlMiddleware.d2.MoveNext() [external code] Microsoft.ApplicationInsights.AspNetCore.ExceptionTrackingMiddleware.d4. Move

On Fri, Dec 2, 2016 at 1:18 PM, Chris R notifications@github.com wrote:

What's the stack trace for the error?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/IdentityServer/IdentityServer4.AccessTokenValidation/issues/32#issuecomment-264565230, or mute the thread https://github.com/notifications/unsubscribe-auth/AA3wUGJeMS_UkZyaXwlhxoVjS7jmcfRJks5rEIs-gaJpZM4KyXtE .

cmills2000 commented 7 years ago

Ok, so I fixed this issue. I have a production site on Azure, and dev / staging slots as children on this site. On the staging site (the one which was breaking), I had forgot to set the "ASPNETCORE_ENVIRONMENT" = "Staging", so the IdentityServerAuthenticationOptions.Authority url was using the production url. Once I remembered to set the ASPNETCORE_ENVIRONMENT variable, the correct Authority was set and everythings works ok.

On Fri, Dec 2, 2016 at 2:36 PM, C.I.M. courtney.mills@gmail.com wrote:

System.ArgumentException System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(Object key) [external code] IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationMi ddleware.d7.MoveNext() [external code] IdentityServer4.Hosting.IdentityServerMiddleware.d3.MoveNext() [external code] IdentityServer4.Hosting.FederatedSignOutMiddleware.d6.MoveNext() [external code] IdentityServer4.Hosting.AuthenticationMiddleware.d2.MoveNext() [external code] IdentityServer4.Hosting.BaseUrlMiddleware.d2.MoveNext() [external code] Microsoft.ApplicationInsights.AspNetCore.ExceptionTrackingMiddleware.< Invoke>d4.Move

On Fri, Dec 2, 2016 at 1:18 PM, Chris R notifications@github.com wrote:

What's the stack trace for the error?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/IdentityServer/IdentityServer4.AccessTokenValidation/issues/32#issuecomment-264565230, or mute the thread https://github.com/notifications/unsubscribe-auth/AA3wUGJeMS_UkZyaXwlhxoVjS7jmcfRJks5rEIs-gaJpZM4KyXtE .

leastprivilege commented 7 years ago

Why would that environment setting make a difference? @Tratcher do you know?

cmills2000 commented 7 years ago

I dont think its the environment setting per se, its the AUTHORITY setting in the options. More specifically, each deployment site must have a unique url or domain name. Not sure if this is Azure-wide, or limited to sites within one machine or account.

On Dec 5, 2016 11:40 PM, "Dominick Baier" notifications@github.com wrote:

Why would that environment setting make a difference? @Tratcher https://github.com/Tratcher do you know?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/IdentityServer/IdentityServer4.AccessTokenValidation/issues/32#issuecomment-265082052, or mute the thread https://github.com/notifications/unsubscribe-auth/AA3wUHWdYXiVqeFcxRtktr9jSnSDYp2Gks5rFRFzgaJpZM4KyXtE .

mikeandersun commented 7 years ago

@brockallen , I am encountering with this error on local development yet. The new way that i can reproduce this error is using of X-Requested-With header. without XMLHttpRequest: Work fine. But when the token is invalid (expired) i get a 302 redirect to IdentityServer.

I try to detect Ajax call to apis to return a 401 and add the the header : $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; NOT works. And get a 500 error code. When i see the server error it is : ArgumentException: An item with the same key has already been added. Key: idsrv4:tokenvalidation:token Sorry for reopen this issue.

mikeandersun commented 7 years ago

Another way to reproduce the error :

  1. Login with implicit flow form an anuglar client. work fine.
  2. Sleep the computer and go to home :)
  3. Tomorrow turn the computer on. :)
  4. .Refresh your app.
  5. The error appears
leastprivilege commented 7 years ago

Why did you close it? It would be useful to tell us what the problem was...

mikeandersun commented 7 years ago

FYI, when the api route is wrong, i get the error!

leastprivilege commented 7 years ago

I need steps to repro that 


Dominick Baier

On Thu, Dec 22, 2016 at 2:39 AM +0100, "mikeandersun" notifications@github.com wrote:

Reopened #32.

— You are receiving this because you were assigned. Reply to this email directly, view it on GitHub, or mute the thread.

mikeandersun commented 7 years ago

@leastprivilege , @Tratcher , please do a try , may be there is an issue in startup routing! in startup.cs of my project. With Postman chrome extension :

  1. Call an api (e.g http://localhost:65000/api/products) with Authorization:Bearer eyJhbGciOiJSUzI1NiIsI..... header. The api route exists and token is valid and return the results correctly.

  2. Now change the api to this http://localhost:65000/api/products11111 that not exists and get this error:

ArgumentException: An item with the same key has already been added. Key: idsrv4:tokenvalidation:token
System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException(object key)
System.Collections.Generic.Dictionary.Insert(TKey key, TValue value, bool add)
IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__18.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware+<Invoke>d__18.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
SaasKit.Multitenancy.Internal.TenantResolutionMiddleware+<Invoke>d__3.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Builder.StatusCodePagesExtensions+<>c__DisplayClass6_0+<<UseStatusCodePagesWithReExecute>b__0>d.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.StatusCodePagesMiddleware+<Invoke>d__3.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware+<Invoke>d__5.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware+<Invoke>d__6.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware+<Invoke>d__7.MoveNext()
brockallen commented 7 years ago

We tried and can't repro it -- we just get 404 on the 2nd call. Can you re-test on the latest versions (rc5)? Also, what version of .NET are you hosting the API in?

mikeandersun commented 7 years ago

The test is with rc5. .NET version: 1.1.* Yes i have a an asp.net MVC with hosting APIs in it. What happens if the API not exists with this library? I think not related to the library and ASP.net routing must handle it and return a 404 error. I don't know when authorization middlewareinvoke, maybe miss sequence of middlewares causes this error. I'm developing a proof-of-concept, and will try more focus on this issue when get some results.

Tratcher commented 7 years ago

It looks like it's caused by UseStatusCodePagesWithReExecute. Your second request results in a 404 so the status code middleware intercepts the response, changes the path, and re-executes the request. This means IdentityServerAuthenticationMiddleware runs twice on the same request and conflicts with itself.

Possible solutions:

brockallen commented 7 years ago

Ah, brilliant find!

We also updated our MW to clear the key on the way out, so this should also take care of it. Of course, we shouldn't be encouraging folks to use UI rendering with APIs... but that's what you get with a unified web framework.

Thanks Chris.

mikeandersun commented 7 years ago

@Tratcher Your first solution fixed the problem .

Re-order your pipeline so IdentityServerAuthenticationMiddleware is before UseStatusCodePagesWithReExecute and doesn't get executed twice.

Thanks.