How to make IdentityServer to add user identity to the access token?
Hooray, I found an answer, when I stumbled upon this page: https://github.com/IdentityServer/IdentityServer3.Samples/issues/173
Apparently, user identity is passed in "sub" claim in the access token. Because I blindly copied API sample, its configuration included
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
which essentially prevented my API from mapping "sub" claim to nameidentifier. After removing this line, HttpContext.User.GetUserId() of authenticated controller returns user ID correctly.
LOST
Updated on June 05, 2022Comments
-
LOST almost 2 years
Short: My client retrieves an access token from IdentityServer sample server, and then passes it to my WebApi. In my controller, this.HttpContext.User.GetUserId() returns null (User has other claims though). I suspect access token does not have nameidentity claim in it. How do I make IdentityServer include it?
What I've tried so far:
- switched from hybrid to implicit flow (random attempt)
in IdSvrHost scope definition I've added
Claims = { new ScopeClaim(ClaimTypes.NameIdentifier, alwaysInclude: true) }
in IdSvrHost client definition I've added
Claims = { new Claim(ClaimTypes.NameIdentifier, "42") }
(also a random attempt)
I've also tried other scopes in scope definition, and neither of them appeared. It seems, that nameidentity is usually included in identity token, but for most public APIs I am aware of, you don't provide identity token to the server.
More details: IdSrvHost and Api are on different hosts. Controller has [Authorize]. In fact, I can see other claims coming. Api is configured with
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); app.UseIdentityServerAuthentication(options => { options.Authority = "http://localhost:22530/"; // TODO: how to use multiple optional scopes? options.ScopeName = "borrow.slave"; options.AdditionalScopes = new[] { "borrow.receiver", "borrow.manager" }; options.AutomaticAuthenticate = true; options.AutomaticChallenge = true; });
Scope:
public static Scope Slave { get; } = new Scope { Name = "borrow.slave", DisplayName = "List assigned tasks", Type = ScopeType.Resource, Claims = { new ScopeClaim(ClaimTypes.NameIdentifier, alwaysInclude: true), }, };
And client:
new Client { ClientId = "borrow_node", ClientName = "Borrow Node", Flow = Flows.Implicit, RedirectUris = new List<string> { "borrow_node:redirect-target", }, Claims = { new Claim(ClaimTypes.NameIdentifier, "42") }, AllowedScopes = { StandardScopes.OpenId.Name, //StandardScopes.OfflineAccess.Name, BorrowScopes.Slave.Name, }, }
Auth URI:
request.CreateAuthorizeUrl( clientId: "borrow_node", responseType: "token", scope: "borrow.slave", redirectUri: "borrow_node:redirect-target", state: state, nonce: nonce);
and I also tried
request.CreateAuthorizeUrl( clientId: "borrow_node", responseType: "id_token token", scope: "openid borrow.slave", redirectUri: "borrow_node:redirect-target", state: state, nonce: nonce);