Get User Info From Access Token WebApi Asp.net Core - asp.net-core

I'm using the new ASP.NET Core Identity API Authorization found in dotnet-core3-preview, the docs are found here https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity-api-authorization?view=aspnetcore-3.0
I'm succesfully running the typical login process, and the token are set and sent in the Bearer token. However rightnow I have an api end point that should return some user details from the database, so I'm trying to extract the user id from the token to query the database.
Yet, I'm not able to find the id in any of the claims, as per my screenshot below, how can I accomplish this?
[HttpGet]
[Authorize]
public async Task<IActionResult> GetUserByToken(){
var ls = User.Claims.AsQueryable();
return Ok(ls);
}

The user id could be find in claim : http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier :
var userID = User.Claims.Where(a => a.Type == ClaimTypes.NameIdentifier).FirstOrDefault().Value;
That id value equals Id column in AspNetUsers table which created by ASP.NET Identity .

I prefer using this instead which is shorter:
var userId = User.FindFirst(ClaimTypes.NameIdentifier).Value

Related

Update logged Identity claims when add new claims

I have a .net core web api application with angular. I use AspNetCore Identity. I have a claim table with userId and value colums. The createnewuser method call from angular site, and they call to register user method. There no any problem here.
I wanna add new claim into httpcontext current user claims list.
I'd tried but it is not help me.
Added a claim to an existing HttpContext User
But I can see added new claim into _httpContext.HttpContext.User.Claims when re-authenticate with new token. How can I see add new claim into current identity (_httpContext.HttpContext.User.Claims)?
And I got current user Id value from httpontext.
var parentId = _httpContext.HttpContext.User.Claims?.FirstOrDefault(p => p.Type == "uid");
if (parentId != null && parentId.Value != null)
{
await _IdentityService.AddClaimAsync(new RegisterRequest()
{
"newclaim" = "new-claim-key",
userId = parentId.Value
});
I think best wasy get claims from db who logged used like that:
var claimList = userManager.
GetClaimsAsync(await_userManager.GetUserAsync(_httpContext.HttpContext.User))
Although this is not a very accurate method, it is the most reliable method. This way you can get the latest claim list in db

.net core 3.1 & identity issue (claims nameidentifier has an id that doesn't match any user, while claims name is right)

I'm having an issue in an area of my website where i need to retrieve the user Id, i tried both by using the HttpContext.User and the injected IHttpContextAccessor, both give me an id that 1) doesn't match the user and 2) doesn't even exist in my database!
I also tried injecting a UserManager and calling GetUserId on it and that too gives me the wrong id (once again, no clue where from, it's not in the database). Calling GetUserAsync on it returns null.
I'm not using anything special nor fancy, the default page included with idendity core to log in, just a context that inherits from IdentityDbContext, and the login part works just fine as those pages are behind an Authorize tag and do force me to log in. If i was getting an error to begin with i could dig but i'm just getting an Id that seems to come from nowhere and am at a loss at where to look.
Here's what the claims look like when calling
HttpContext.User.Claims.ToList()
[0]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: f478bf7a-1734-494c-aad6-0882ab24007f} <-- this id is not present in AspNetUsers table
[1]: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name: EDITED OUT FOR PRIVACY} <-- my correct username (my email)
[2]: {AspNet.Identity.SecurityStamp: EDITED OUT}
[3]: {http://schemas.microsoft.com/ws/2008/06/identity/claims/role: Administrator} <-- correctly finds my role too
You can use the following code to get the UserId
using System.Security.Claims;
using Microsoft.AspNetCore.Identity;
var claimsIdentity = (ClaimsIdentity)this.User.Identity;
var claim = claimsIdentity.FindFirst(System.Security.Claims.ClaimTypes.NameIdentifier);
var userId = claim.Value;
I had that problem for using this in ExternalLoginCallback:
var user = new SmileAppUser { UserName = email, Email = email };
await _signInManager.SignInAsync(user, isPersistent: false);
Try to retrieve the user from the database to include the id in the claims with SignInAsync.

Adding and accessing claims in asp net core 3.0 using built in Identity server

I'm currently failing at wrapping my head around claims. I have a ASP.Net Core 3 project with the angular template and users stored in app.
I want to add claims to my users, reading up on I thought it would be easy, just add something along the lines of
await _UserManager.AddClaimAsync(user, new Claim(AccountStatic.ClaimTypes._Claim_Id, user.Id));
When you create the user, and then get it back using the below line once they are logged in again:
User.FindFirst(AccountStatic.ClaimTypes._Claim_Id)?.Value;
This does however not work. I can see the claims being written to AspNetUserClaims table in my database but it's not there in the users claims when they log in. There are a few other claims there, but not the ones I have added.
Do I need to define somewhere which of the users claims get included when they log in?
Edit.
I found a post stating that I need to add claims using a DI AddClaimsPrincipalFactory. So I added this class.
public class UserClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser>
{
public UserClaimsPrincipalFactory(UserManager<ApplicationUser> userManager,IOptions<IdentityOptions> optionsAccessor): base(userManager, optionsAccessor)
{}
//https://levelup.gitconnected.com/add-extra-user-claims-in-asp-net-core-web-applications-1f28c98c9ec6
protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
{
var identity = await base.GenerateClaimsAsync(user);
identity.AddClaim(new Claim(AccountStatic.ClaimTypes.Claim_Id, user.Id ?? "[no id]"));
return identity;
}
}
And if I step through the code I can see the claims being added here. But in the Controller my custom claims are not present.
internal string GetUserId()
{
if (User.Identity.IsAuthenticated == false)
return null;
return User.FindFirst(AccountStatic.ClaimTypes.Claim_Id)?.Value;
}
Update. Ok I find this very strange. I have been trying to do what others claim work but for me nothing gets me the users name or id. inspecting the User I get the following. Nothing here contains any reference to the logged in user.
Update 2:
Just noticed that there is actually an Id in there: {http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier: ed107a11-6c62-496b-901e-ed9e6497662a} Seems to be the users id from the database. Not sure how to access it yet though.
These return null.
User.FindFirst(JwtRegisteredClaimNames.NameId)?.Value;
User.FindFirst("nameidentifier")?.Value;
User.FindFirst("NameIdentifier")?.Value;
Another update
I'm using a UserClaimsPrincipalFactory and breakingpointing it and looking at the Claims I can see that all of the ones I want are there. But again, these are not available in my API controllers as seen in the first picture.
I finally understood the problem, in large parts thanks to Ruard van Elburgs comments, and the answer he made in the linked question IdentityServer4 Role Based Authorization.
The problem is that the claims are not added to the access token.
There are two tokens, the access token and the identity token.
- Ruard van Elburg
They key to understanding what was going on was finding out that there are two tokens, and that they contain different claims and have different purposes.
You can force claims from one token to also be included in the other if you deem it necessary.
The solution to my problem was to add this in Startup.ConfigureServices
services
.AddIdentityServer(options => {})
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{
foreach (var c in options.ApiResources)
{
// the string name of the token I want to include
c.UserClaims.Add(AccountStatic.ClaimTypes.Claim_Id);
}
});
I still have not figured out how to get the Identity token, but as I'm now including the user Id in the access token my problems are solved for the moment.

Use UserManager GenerateUserTokenAsync to create custom tokens with extra data

I am using ASP.NET Core 2.2 and I need to generate custom tokens in my application.
Asp.Net Core Identity UserManager can generate classic tokens like EmailVerification, ...
But it has also a method to generate tokens with different purposes (MSFT Docs):
public virtual System.Threading.Tasks.Task<string> GenerateUserTokenAsync (TUser user, string tokenProvider, string purpose);
I need to generate a token with the following information:
Purpose = AddUserToProject
User = A given user
ProjectId = The Project Id to which the User should be added.
RoleId = The Role Id of the User in the Project
On GenerateUserTokenAsync I can add the User and the Purpose ...
But I'm not sure how to add (3) and (4) e.g. ProjectId and RoleId.
And how can I retrieve it later so I can actually perform the action.
How should I do this?
You can create a custom token provider, and then instruct ASP.NET Core to use that. Create a class that implements IUserTokenProvider<TUser, TKey>. Then, you can either explicitly use it:
var token = await _userManager.GenerateUserTokenAsync(user, "MyCustomTokenProvider", purpose);
Or you can sub it in for any or all of the Identity token providers in ConfigureServices:
services.AddIdentity<IdentityUser, IdentityRole>(o => {
o.Tokens.PasswordResetTokenProvider = nameof(MyCustomTokenProvider);
// rinse and repeat for other token providers you want to change
// see: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity-configuration?view=aspnetcore-2.2#tokens
})
.AddTokenProvider<MyCustomTokenProvider>(nameof(MyCustomTokenProvider));
[1]:

Web Api 2,Claims always null in my inheritance Apicontroller

I am using the Web Api 2 Auth template in my project.I want to get the user id when the client request with Api Key. My question is :
1 How can I get the api client user's Id.
-Is right or wrong resolve it through the Api requesting ?
-or take the userId in the http header directly?
-or query it from database using the Api key?
2 I create the MyApiController inherit from ApiController,I want to get the claims in it.So I write some code in it.like this
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
var principal = Request.GetRequestContext().Principal as ClaimsPrincipal;
CorpId = (from c in principal.Claims where c.Type.Contains("CorpId") select c.Value).FirstOrDefault();
UserId = (from c in principal.Claims where c.Type.Contains("UserId") select c.Value).FirstOrDefault();
}
I found the claim is null in the MyApiController. But when I do it in the action controller,It worked ?
You'd rather get request specific data when the request is executed (i.e. in Controller.Get method), not when the controller is created. Or use a filter attribute if values are not needed in controller method.