Search code examples
c#asp.netjwt

why ClaimTypes is a uri in identity


I'm using .net6's aspcore service to test jwt functionality.

I found that the Claims when I authorize are represented by uri here. Why is this? Although the string can be customized, why is the default type provided is uri?

{
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier": "2",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name": "ssq",
  "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress": "[email protected]",
  "http://schemas.microsoft.com/ws/2008/06/identity/claims/version": "1",
  "http://schemas.microsoft.com/ws/2008/06/identity/claims/role": "admin",
  "exp": 1652891588,
  "iss": "Issuer",
  "aud": "Audience"
}

After parsing, I found that the keys obtained are all uri, and accessing these uri displays the same content.

The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.

Why is this so? Why use uri to represent it? Wouldn't this make the generated jwt characters very long?

I also searched for some information and read RFC7519 rfc-editor.org/rfc/rfc7519.html (JSON Web Token (JWT)) There is a section about Claim Names in this standard. “All the names are short because a core goal of JWTs is for the representation to be compact.

Very confused, why does Microsoft do this? Does anyone know why? thank you very much!


Solution

  • Why?

    As already mentioned in comments, they are URIs and intended to provide enough uniqueness to avoid accidental conflicts with other possible claims providers.

    The super-long claims types as shown are usually related to some standards which designed for uniqueness and verboseness over brevity. I would have liked the commonly used ones to have prioritized compactness more, but it's too late to change that.

    The standard ones, while using http scheme for some unfathomable reason, are generally not URLs and there are no resource behind that link.

    Should you use the long standard claim types?

    For your own-defined claim types, usually not. But DO include a simple namespace to provide uniqueness against accidental third party claim hopping in. A good practice is to include company/product, a la Fabrikam.CRM.MyId.

    When you already get those longish claims types, then retaining is beneficial for these main reasons:

    "It just works". As they are standards-based, then they usually play nicely with other tools. I.e. ClaimsIdentity.Name by default looks up name from http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name. This can be changed, of course, but if you use the standard claim, you don't have to and things "just work". Or when you pull in claims from some identity provider then most likely this is what you get. Its simpler to just use what you have.

    Passing claims to outside Should you pass your claims to 3-rd parties then usually they expect the standard ones again and things are more complicated and may break more easily if you require claim mapping at the boundary. Or they will just puke at you in some unintelligible way.

    Claim type length is usually not a problem. It's generally harmful to optimize things which are not broken. For most applications the claims type length impact is negligible.

    Familiarity Being standard, they have a clear meaning and are generally well understood by anyone encountering them. Which cannot be said for claims like nbf with value like 1699346757 (hint: JWT nbf).

    Claim mapping

    If you don't care much of the above reasons then you can always map the incoming claim types to your own shorter types. I often do.

    If using ASP.NET core then IClaimsTransformation might be helpful for you.