11

I am using Asp.Net Core and ASP.NET Identity and when I get a Claim type I get something like

"type":"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
"value":"123"

How to get only the simple type name, e.g.:

"type":"nameidentifier",
"value":"123"

I know this is possible I just can't find the solution.

Jesse
  • 3,522
  • 6
  • 25
  • 40
Miguel Moura
  • 36,732
  • 85
  • 259
  • 481
  • Define "simple type name", please. The one that you receive is a well-known claim type and is supposed to go by that name. – n0rd Jul 23 '16 at 05:11
  • Do you know what is solution for this problem for asp.net core? – Tonven Jul 12 '18 at 22:34

7 Answers7

19

I was looking for this answer when I came across this documentation:

When you inspect the claims on the about page, you will notice two things: some claims have odd long type names and there are more claims than you probably need in your application.

The long claim names come from Microsoft’s JWT handler trying to map some claim types to .NET’s ClaimTypes class types. You can turn off this behavior with the following line of code (in Startup).

This also means that you need to adjust the configuration for anti-CSRF protection to the new unique sub claim type:

AntiForgeryConfig.UniqueClaimTypeIdentifier = Constants.ClaimTypes.Subject;
JwtSecurityTokenHandler.InboundClaimTypeMap = new Dictionary<string, string>();

I added this code to the Startup.cs of my client and it shortened the claimtypes.

Update:

For newer versions of IdentityModel, the property is called DefaultInboundClaimTypeMap:

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

Make sure you run this line before you set up your Identity configuration.

Community
  • 1
  • 1
Jesse
  • 3,522
  • 6
  • 25
  • 40
5

If you want to get nameidentifier value, code:

User.FindFirst(ClaimTypes.NameIdentifier).Value
adem caglin
  • 22,700
  • 10
  • 58
  • 78
  • I think you miss understand me ... What I am looking for is to get the short name of the claim type, so instead of having http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" I would have simply nameindentifier. Not sure if there is a standard way to do this. – Miguel Moura Apr 05 '16 at 10:44
  • Above solution does what you need. – Ratheesh Sep 12 '20 at 06:51
2

Try this

public static class ClaimsPrincipalExtentions
{

    private const string ShortNameProperty = "http://schemas.xmlsoap.org/ws/2005/05/identity/claimproperties/ShortTypeName";

    public static IEnumerable<Claim> GetClaimsByShortTypeName(this ClaimsPrincipal cp, string name)
    {
        return cp.Claims.Where(x => x.GetShortTypeName() == name);
    }

    public static string GetShortTypeName(this Claim claim)
    {
        string shortName;
        return claim.Properties.TryGetValue(ShortNameProperty, out shortName) ? shortName : claim.Type;
    }

}
  • Unsure if i miss understood the question. I was under the impression you where after the "ShortName" correct? ie, "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" would return "emailaddress" ? Any reason you need the soap namespace? If you are creating your own claim types and not using soap, (ie jwts) you shouldn't use the namespace with out setting the short name as it will bloat your tokens. It was for this reason Microsoft introduced the short name property value. – James Harper Jun 15 '16 at 11:47
  • 1: If you want to find the short name of a in build Microsoft claim, use the code i posted above 2: If you are making your own claims, and don't have a reason for the soap namespace, don't add namespace, your claim will still be valid 3: If you require the soap namespace, you will have to set the "short name" property on the property bag of the the claim. If you are using jwts the tokens should be created using the short name rather then the type string – James Harper Jun 16 '16 at 07:12
  • Thanks. This solutions helps when you create claims mapping – cdmnk Jul 27 '18 at 13:55
0
using System.IdentityModel.Tokens.Jwt;

var claim = new Claim(ClaimTypes.NameIdentifier, "1");
if (JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.TryGetValue(claim.Type, out string type))
{
    var shotrClame = new Claim(type, claim.Value, claim.ValueType, claim.Issuer, claim.OriginalIssuer, claim.Subject);
}

var claim = new Claim("nameid", "1");
if (JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.TryGetValue(claim.Type, out string type))
{
    var longClameType = new Claim(type, claim.Value, claim.ValueType, claim.Issuer, claim.OriginalIssuer, claim.Subject);
}

sourcs: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/blob/d2361e5dcd1abbf6d0ea441cdb2e7404166b122c/src/System.IdentityModel.Tokens.Jwt/ClaimTypeMapping.cs#L61

0

I wanted to use the short name for logging, so I used this:

var name = JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.FirstOrDefault(x => x.Value == myclaim.Type).Key ?? c.Type;

It might not be exactly what was originally sent in the JWT (ex, "sub" might become "nameid"), but it does provide something more readable than "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier".

Brian
  • 37,399
  • 24
  • 94
  • 109
0

Also, this is an alternative to the

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();

HttpContext.User.Claims doesnt match JWT Token - "Sub" changes to "NameIdentifier"

M Akin
  • 446
  • 6
  • 18
-2

System.IO.Path.GetFileName(claim.Type)

Andrew Gale
  • 63
  • 1
  • 7