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'
.
The User property provides programmatic access to the properties and methods of the IPrincipal interface. Because ASP.NET pages contain a default reference to the System. Web namespace (which contains the HttpContext class), you can reference the members of HttpContext on an .
ClaimsPrincipal exposes a collection of identities, each of which is a ClaimsIdentity. In the common case, this collection, which is accessed through the Identities property, will only have a single element.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With