简体   繁体   中英

Extract values from HttpContext.User.Claims

I'm trying to extract an email address from HttpContext.User.Claims and I'd like to ask for help to come up with a better way to code this (maybe using LINQ?)

The way I'm doing it now seems very hacky.

var userClaimsList = HttpContext.User.Claims.ToList();

// List is of varying length but email is always 3rd from the bottom.
int emailPosition = userClaimsList.Count()-3; 
string searchString = "preferred_username: "; 

// dirtyEmail = "preferred_username: xyz@emailcom"
string dirtyEmail = userClaimsList[emailPosition].ToString();
string cleanEmail = dirtyEmail.Replace(searchString, "").ToLower().Trim();

I've tried the LINQ solutions recommended in another post but receive the error Operator == cannot be applied to operands of type 'Claim' and 'string' .

Claim objects are a bit more than just a simple string, and what you are looking at in the userClaimsList is a list of these claim objects.

Claims are mostly pairs of a claim type and a claim value , and when you look for certain information about a user, you should use the claim type to identity the user property you are looking for.

What you do in your code is assume that the claim you are looking for is the third to last, which by itself is already a dangerous assumption since you cannot be sure that this will always be the case: claims are generally considered unordered and you should look for them by type. And once you get the type, you then .ToString() it, which essentially reduces all the information the Claim type has down to a single string of the format claimType: claimValue . You can use that, but it's really inefficient when the object itself as a much better way of accessing the claim value.

Since you are looking for the prefix "preferred_username: " , I assume that preferred_username is the claim type you are looking for. In that case, you could look up that claim like this:

var claim = HttpContext.User.Claims.First(c => c.Type == "preferred_username");
var emailAddress = claim.Value;

The use of First will throw an exception if a claim with that type was not found. If you don't want that, you can use FirstOrDefault and then check whether claim is null .

There are also a few helper extensions that allow you to extract claims directly. In this case, you could use FindFirstValue on the user to get the claim value directly:

var emailAddress = HttpContext.User.FindFirstValue("preferred_username");

In case a claim with that type was not found, FindFirstValue will return null , so emailAddress could be null in this case.

What you are doing is not only assuming something you cannot ensure, but also much harder than needed:

// note: HttpContext.User == User
var cleanEmail = User.FindFirst(ClaimTypes.Email)?.Value;

If the data is not on the email claim type, check the corresponding type and use that instead. In your case, it seems that it should be preferred_username :

var cleanEmail = User.FindFirst("preferred_username")?.Value;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM