runtime: System.Security.Claims.Claim value type incorrect
The type of System.Security.Claims.Claim.Value
is to string
which is contrary to the spec:
Claim Value The value portion of a claim representation. A Claim Value can be any JSON value.
This is big problem for us while creating a .NET Core app for a large established ecosystem where JWTs have object claims.
The problem is exacerbated by the fact that now System.IdentityModel.Tokens.Jwt library is dependent on this implementation in the way it deserialises JWTs into ClaimsIdentity
and then into ClaimsPrincipal
… (e.g. here or here)
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Comments: 25 (18 by maintainers)
As far I understand the correct way of processing a raw JWT into a principal is by executing this:
Here’s an example JWT:
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiIsImlzRW5jcnlwdGVkIjoiRmFsc2UiLCJ4NXQiOiI1M0VENjE1NTUwNTlBRDg3QUE4MkNBNTYwRTQ4QkIxMkM1MzdGOUY1IiwidmVyIjoiMi4xIn0.eyJhdWQiOiJIZWxpeC5TZWN1cml0eS5VdGlsIiwiaWF0IjoiMTQ3MjA5NjU1Ny43NDM3NiIsIm5iZiI6IjE0NzIwOTY1NDQuNzU3NTkiLCJDbGFpbVNldHMiOlt7IkNsYWltcyI6eyJzZXJ2ZXJJZCI6IkhlbGl4LkNvbnRhaW5lcnMuRGV2Iiwic2VydmVyVmVyc2lvbiI6ImRldiIsImlzc1g1dCI6IjUzRUQ2MTU1NTA1OUFEODdBQTgyQ0E1NjBFNDhCQjEyQzUzN0Y5RjUifSwiUHJvdmlkZXIiOiJIZWxpeC5Db250YWluZXJzLkRldi52ZGV2IiwiU2NoZW1hIjoiSGVsaXguQ29udGFpbmVyIiwiVmVyc2lvbiI6IlYxIn1dLCJpc3MiOiJIZWxpeC5Db250YWluZXJzLkRldi52ZGV2IiwiZXhwIjoiMTQ3MjA5Nzc0NC43NTg1OSIsInNzaWQiOiJjNmJkNzY3ZjE4YWU0ZTQyOTliMmY4YjJmNzhmODU1NSJ9.W8ARsO3IKMO_CBl5fMkgTEkPmoZZvjaX46-mmVHqT5hQAbQVBmnc18B9VxsSS34YKVE2dBQwZHjhu2ROSOCKeuHOqHjjS_HuSdDLOdi7rJUdpKw1GE-lBqxzUPojAlUvLRlq7KjbwipXd7bJyMk7chVU9r548pmljDAlm7SOqmM-qcZ8X0sgQcDxxZoacJiL9xQpbJPi9CVHC_ms2LJhm6AFcCNTlRZNgAmMvoIBWfjXVsVC92HFgqd_qTpMvudTs216LIfslpJC0WiU4SFWKV2Bt5rGGVVqSe4vXb4W1Si58t8ORcepRnkZ1jkEuKf2VpHTEw0ylwX_BLqnnKdavQ
Decoded to JSON:
Once raw JWT is loaded into an instance of
JwtSecurityToken
it has the followingPayload
:However its
Claim
are as follows:The
ClaimSets
claim is serialised back to string…Now a
JwtSecurityTokenHandler
takes the deserialised JWT and loads it into an instance ofClaimsIdentity
:At the end of all of this, the principal has all claims serialised back to
string
which is incorrect and extremely inefficientOne of the primary reasons is that we need to serialize an identity into a cookie. We can’t serialize and deserialize arbitrary types. There are also several other operations we do like merging multiple ClaimsPrincipals into a single principal.
@RussKie The last two sentences were related to asp.net users. For users of IdentityModel, we have extensibility that allows you to create your own custom ClaimsIdentity returned from ValidateToken. Both JwtSecurityTokenHandler.CreateClaimsIdentity and TokenValidationParameters.CreateClaimsIdentity are virtual and between the two, you can have a custom ClaimsIdentity OR CustomClaims. We do not have a delegate for CreateClaimsIdentity, as we do for many other overloads. Deriving is necessary.
I am the only one seeing the problem with this? 😱
As an end-consumer app developer I should not be locked in dealing with strings, it is just too impractical. I should be dealing with whatever objects fit my business requirements. Ultimately in the code the developers don’t deal with JWTs (it is a mere transport object), they deal the identities.
To put this in a context. Previously HTTP context would expose the user as
IPrincipal
(https://github.com/Microsoft/referencesource/blob/master/System.Web/HttpContext.cs#L1237). Now in OWIN/.NETCore HttpContext it is no longer the case, it isClaimsPrincipal
. This means I can’t substitute it with a custom principal. Because I can’t put my custom principal I can’t expose my custom identity as it is now ofClaimsIdentity
type. And the ClaimsIdentity only provides me with strings…For example:
I can no longer do anything like this in OwinContext / .NETCore HttpContext…
I don’t agree with the current implementation of ClaimsIdentity - it is too rigid. Either it has to support more than just string claims or there has to be a mechanism for me to inject my custom principal/identity which support other than string claims. So far I haven’t found any ways to achieve this cleanly. 😢