Identityserver4: How can I retrieve the AuthenticationProperties in a controller/service after SignInAsync is called?

Created on 16 Jan 2018  路  13Comments  路  Source: IdentityServer/IdentityServer4

Hello, we call AuthenticationManagerExtensions.SignInAsync and we pass it a list of claims. We see down in the pipeline a new ClaimsPrincipal is built up and all the AdditionalClaims seem to be there.

Now, we want to get at all these later in our ProfileService. Is this possible?

question

All 13 comments

How does this make any sense? I call SignInAsync and get a success but when i try to trigger AuthenticateAsync to get access to the authenticateContext.Properties (aka all the original claims) it says None and false success.

HttpContextAccessor.HttpContext.SignInAsync(100000. ToString(), "fake-user", IdentityServer4.IdentityServerConstants.DefaultCookieAuthenticationScheme, new AuthenticationProperties() {
 RedirectUri = "ExternalLoginCallback", Items = {
  {
   "returnUrl",
   "localhost"
  },
  {
   "scheme",
   IdentityServer4.IdentityServerConstants.DefaultCookieAuthenticationScheme
  }
 }
}, new System.Collections.Generic.List < System.Security.Claims.Claim > () {
 new System.Security.Claims.Claim(IdentityModel.JwtClaimTypes.Email, "[email protected]")
}.ToArray());
// Success! AuthenticationScheme: idsrv signed in.


HttpContextAccessor.HttpContext.AuthenticateAsync(IdentityServerConstants.DefaultCookieAuthenticationScheme);
// Succeeded: false!!!! None: true

Now, we want to get at all these later in our ProfileService. Is this possible?

Did you check the Subject? http://docs.identityserver.io/en/release/reference/profileservice.html

I am not sure why this is but when using the MvcHybrid sample, there are two calls out to UserInfo, the first one (via ClaimsProviderAccessToken per logs) I notice that context.Subject.Claims has all of the initial claims set from the start. But I noticed on the second call (via UserInfoEndpoint per logs) only has sub, auth_time, idp and amr.

If I set AlwaysIncludeUserClaimsInIdToken this obviously fixes the issue, but I don't want to set that on every client. I am in this pickle because I do not have a UserStore. I do not need or want one. All my attributes come back from SAML2 and I map them to claims and store them via SignInAsync. So why is it so hard to retrieve this after I store them?

This might be a better question to help me get on track: Why is this 0?

HttpContextAccessor.User.Claims.Count()

Why aren't the claims getting stored?
https://github.com/IdentityServer/IdentityServer4/blob/dev/src/IdentityServer4/IdentityServerUser.cs#L95

When you pass the ClaimsIdentityto ClaimsPrincipal, I would expect them to be stored and can easily be retrieved when cracking open the identity from anywhere in the app via HttpContextAccessor.

I just figured it out thanks to a lot of googling, I need to call AddAuthentication BEFORE the call to AddIdentityServer. Because AddAuthentication is the middleware that sets the HttpContext.User. I noticed that this is NOT the case in the quickstarts https://github.com/IdentityServer/IdentityServer4.Samples/blob/release/Quickstarts/Combined_AspNetIdentity_and_EntityFrameworkStorage/src/IdentityServerWithAspIdAndEF/Startup.cs#L72

is it bad if I do this??

You don't need to call AddAuthentication - this is done inside AddIdentityServer.

You get the claims you issued during SignIn from the ProfileDataRequestContext in your profile service.

@leastprivilege

You don't need to call AddAuthentication - this is done inside AddIdentityServer.

I noticed it, but i first thought maybe it was in the wrong order. Upon deeper investigation, the client configuration option AlwaysIncludeUserClaimsInIdToken actually determines if HttpContextAccessor.HttpContext.User.Claims gets populated at all whatsoever. I wish I did not have to use AlwaysIncludeUserClaimsInIdToken to populate HttpContextAccessor.HttpContext.User.Claims.

You get the claims you issued during SignIn from the ProfileDataRequestContext in your profile service.

I am not using a UserStore so I need ALL of the claims originally set during SignInAsync. When using the MvcHybrid sample client, on the second call to UserInfo (the one that says in the logs "Get profile called for subject ######### from client MVC Hybrid with claim types [ ... ] via UserInfoEndpoint") the claims in ProfileDataRequestContext are different.

The watch is on: context.Subject.Claims, results {System.Security.Claims.ClaimsPrincipal.<get_Claims>d__21} System.Collections.Generic.IEnumerable<System.Security.Claims.Claim> {System.Security.Claims.ClaimsPrincipal.<get_Claims>d__21}

First call:

2018-01-19_09-21-13-blur

Second call:

2018-01-19_09-21-24

You can easily test this with IdentityServer4 and IdentityServer4.Samples -> Clients -> MvcHybrid. Because of this I cant trust ProfileDataRequestContext and I notice that even though MvcHybrid Sample Client wants the email scope, my ProfileService implementation is not capable of providing it since the claims I need are no longer in there for some reason. Is there a way I can get access to all the claims I originally set during SignInAsync?

Why do calls to /authorize/token have no cookies sent with them? I might have been wrong about AlwaysIncludeUserClaimsInIdToken above as well. There is so much going on and sometimes the state gets so screwed up that I get inconstant results when restarting, deleting grants, and testing. At this point, I am painstakingly walking through each request in the middleware to determine the source of my issue.

Why do calls to /authorize/token have no cookies sent with them

You might wan to spend some time reading the OIDC and OAuth2 specs for how the endpoints are used.

As for helping you with your situation, you might want to consider consulting as you will get focused answers for your scenarios.

The issue tracker is not meant for general support, and instead is for reporting bugs and feature requests for IdentityServer.

Upon reviewing more of the docs, and specs, I am going to conclude that what I desire is simply not possible.

When performing a back-channel request for an auth_token, all we have is the code which contains only 4 claims pictured above. There is no session, so there is no way to retrieve the original attributes unless we cache them or otherwise persist them in some way.

Thank you so much for figuring this out. Saved me quite some time

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings