如何在发送REST请求时从ASP.NET Identity获取UserId
Great question! Your existing options A and B are solid, but there are a few more practical approaches to get the UserId for external applications authenticating with your ASP.NET Identity API. Let’s go through them:
1. Include UserId in the JWT Token Payload
Since ASP.NET Identity uses JWT tokens by default, you can embed the UserId directly into the token’s claim set when generating it. This way, external apps don’t need to call any additional API endpoints—they can simply decode the JWT to extract the UserId.
To implement this, modify the GrantResourceOwnerCredentials method in your ApplicationOAuthProvider class to add a NameIdentifier claim (which maps to UserId):
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) { var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>(); ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password); if (user == null) { context.SetError("invalid_grant", "The user name or password is incorrect."); return; } ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, OAuthDefaults.AuthenticationType); // Add UserId as a claim oAuthIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())); AuthenticationProperties properties = CreateProperties(user.UserName); AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties); context.Validated(ticket); }
External apps can then decode the access_token using a JWT library (like System.IdentityModel.Tokens.Jwt in .NET) to retrieve the nameid claim value, which is the UserId.
2. Extend the /token Endpoint Response to Include UserId
Instead of making external apps decode the JWT, you can add the UserId directly to the JSON response returned by your /token endpoint. This lets apps get the UserId in the same call where they retrieve the token.
Configure this in your Startup.Auth.cs file by hooking into the OnTokenEndpointResponse event:
app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions { // Existing configuration (TokenEndpointPath, Provider, etc.) TokenEndpointPath = new PathString("/token"), Provider = new ApplicationOAuthProvider(PublicClientId), // Add UserId to the token response OnTokenEndpointResponse = context => { var userIdClaim = context.Identity.FindFirst(ClaimTypes.NameIdentifier); if (userIdClaim != null) { context.AdditionalResponseParameters.Add("userId", userIdClaim.Value); } return Task.CompletedTask; } });
Now when external apps call http://myapiURL/token, the response will include an extra userId field alongside the existing properties like access_token and userName.
3. Extend the UserInfo Endpoint Without Modifying the ViewModel
If you prefer not to alter the UserInfoViewModel (your option A), you can return an anonymous object from the GetUserInfo() method that includes the UserId along with the existing fields:
public IHttpActionResult GetUserInfo() { var userId = User.Identity.GetUserId(); var user = UserManager.FindById(userId); return Ok(new { Email = user.Email, HasRegistered = true, LoginProvider = user.Logins.FirstOrDefault()?.LoginProvider, UserId = userId }); }
This keeps your existing ViewModel intact while still exposing the UserId through the API/Account/UserInfo endpoint.
Which Approach to Choose?
- Option 1 or 2: Best if you want to minimize API calls (external apps get UserId when they fetch the token, no extra requests needed).
- Option 3 or your original option A: Ideal if you want to keep UserId tied to the user info endpoint for consistency.
- Your option B: Works well if you need a dedicated endpoint for just retrieving UserId, but it adds an extra API call compared to the above methods.
内容的提问来源于stack exchange,提问作者Ali

