Identityserver4: Dotnet 2.0 migration sub claim is missing

Created on 5 Nov 2017  路  14Comments  路  Source: IdentityServer/IdentityServer4

  • [x] I read and understood how to enable logging

Issue / Steps to reproduce the problem

  • Migration from dotnet core 1.1 to 2.0.
  • Implicit grant
  • No in memory stores.

The Auth server successfully issues the token and redirect back to the client. The token looks are shown below.

When trying to make an api call using the token, one of the call gets user Id which uses
IdentityServer4.Extensions.PrincipalExtensions.GetSubjectId() method at which point it throws below error as shown in the log.
...

The AuthToken has got sub in the token as follows:

user : t
access_token : "eyJhbGciOiJSUzI1NiIsImtpZCI6Ijg5MjYwQjUzQTc1NUUyQzQ0N0Q5NDA0OTY..."
expires_at : 15098723469
id_token : "eyJhbGciOiJSUzI1NiIsImtpZCI6Ijg5MjYwQjUzQTc1NUUyQzQ0N0Q5NDA0OTY5NjQ3MTYzMTU..."
profile : AspNet.Identity.SecurityStamp :
"xxxxxx-xxxx-xxxx-xxx"
amr :["external"]
auth_time:15098703455
email:"[email protected]"
email_verified:false
idp:"local"
name:"foobar"
phone_number:"111"
phone_number_verified:true
preferred_username:"[email protected]"
role:"Admin"
sid:"c7c99cb4b62b33e9f88b02db3esdfsdf"
sub:"69"

Api.Startup.cs

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddJwtBearer(options =>
                    {
                        // base-address of your identityserver
                        options.Authority = "url_to_auth_server";

                        // name of the API resource
                        options.Audience = "api";
                        options.RequireHttpsMetadata = false;
                        options.TokenValidationParameters = new TokenValidationParameters()
                        {
                            ValidateLifetime = false,
                            ValidateIssuer = false,
                            ValidateAudience = false,
                        };
                    });

Tried https://github.com/IdentityServer/IdentityServer4/issues/1545 but no luck.

Relevant parts of the log file

ERR] Error occured while getting ...
System.InvalidOperationException: sub claim is missing
   at IdentityServer4.Extensions.PrincipalExtensions.GetSubjectId(IIdentity identity)
question

Most helpful comment

@TomCJones so did I thought. But I am getting http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier instead of sub.

So I had to update the API server startup.cs as follows and that fixed the issue.

        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); // <-- This is the fix
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddJwtBearer(options =>
                    {
                        // base-address of your identityserver
                        options.Authority = "url_to_auth_server";

                        // name of the API resource
                        options.Audience = "api";
                        options.RequireHttpsMetadata = false;
                        options.TokenValidationParameters = new TokenValidationParameters()
                        {
                            ValidateLifetime = false,
                            ValidateIssuer = false,
                            ValidateAudience = false,
                        };
                    });

@leastprivilege None of the claims collection had the sub/userId in it.

I sort of understand why that one line made it work but I would appriciate if someone put some details here.

All 14 comments

Sorry - this does not make any sense to me.

Can you describe in more detail what you are actually doing?

@leastprivilege Apologies about this. This happens when trying to make an api call. I have updated the text above.

why do you use IdentityServer4.Extensions.PrincipalExtensions.GetSubjectId() in your apis?

Inspect the user's claims in your API and see what you get.

@leastprivilege One of the requirement is to get user Id for each api request. I know GetSubjectId may not be best way to achieve this. So you are saying just create a custom claim for the userId and use that?

Btw I haven't done any coding to put the sub in the token this happens by IdentityServer so I thought I just use that. Is this not a good approach?

What I am saying is - why do you have a dependency on the IdentityServer DLL in your API. All this method does is search for the subject claim.

As I said - inspect the claims collection in your API and see what's on there.

Thanks for the quick response. I'll try that and update it here.

what's wrong with the sub? It's the one that's always there

@TomCJones so did I thought. But I am getting http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier instead of sub.

So I had to update the API server startup.cs as follows and that fixed the issue.

        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); // <-- This is the fix
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                    .AddJwtBearer(options =>
                    {
                        // base-address of your identityserver
                        options.Authority = "url_to_auth_server";

                        // name of the API resource
                        options.Audience = "api";
                        options.RequireHttpsMetadata = false;
                        options.TokenValidationParameters = new TokenValidationParameters()
                        {
                            ValidateLifetime = false,
                            ValidateIssuer = false,
                            ValidateAudience = false,
                        };
                    });

@leastprivilege None of the claims collection had the sub/userId in it.

I sort of understand why that one line made it work but I would appriciate if someone put some details here.

Thank Microsoft for that. They do a mapping of the inbound standard claims to their proprietary ones...

Glad you found it!

I'm getting the same issue when I upgraded to .net core 2.0. This was working fine pre 2.0.

I am using open id connect to authenticate against azure ad.

I can indeed use the above solution to get past the assertion errors, but then all the claims names are different than what they used to be.

Is there anyway to get the original behaviour back?

It appears as though azure ad does correct send claim types including a "sub" claim. As @leastprivilege mentions above, ms, for some reason, thinks it's a good idea translate inbound claims into their own bespoke claims.

@leastprivilege is there a reason for the need to assert a sub? Is that part of a spec?

OpenID Connect requires sub - from the spec
sub
REQUIRED. Subject Identifier. A locally unique and never reassigned identifier within the Issuer for the End-User, which is intended to be consumed by the Client, e.g., 24400320 or AItOawmwtWwcT0k51BayewNvutrJUqsvl6qs7A4. It MUST NOT exceed 255 ASCII characters in length. The sub value is a case sensitive string.

@activebiz -- I found your comment very helpful, though I remembered seeing another reference somewhere that was a bit more surgical and found that this worked great:

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings