TheHvidsten
TheHvidsten

Reputation: 4448

Custom resource/claim not being returned in "userinfo"

I'm trying to add some custom claims to my IdentityServer4 flow, but I can't get them to show up in the /userinfo endpoint.

I'm only using "in memory" configuration for now, so in this I have created a new IdentityResource with my custom scope:

new IdentityResource {
    DisplayName = "My Custom Resource",
    Name = "mycustom",
    UserClaims = new List<string> {
        "mycustom.myvalue"
    }
}

And I've set my client to be able to use this:

new Client {
    AllowedScopes = {
        IdentityServerConstants.StandardScopes.OpenId,
        "mycustom"
    }
}

Then, whenever a login is successful, I do the following to sign in the user before redirecting back to /authorize/callback

await _events.RaiseAsync(new UserLoginSuccessEvent(
    "provider",
    "providerUserID",
    "subjectID",
    "name"));
await HttpContext.SignInAsync(
    "subject",
    "name",
    new AuthenticationProperties(),
    new Claim("mycustom.myvalue", "987654321"));

Now, I can do a full authorize flow with ?scope=openid+mycustom, but when I make the call to the userinfo endpoint, it does not return mycustom.myvalue

I'm probably only missing some minor detail, but I can't for the life of me figure out what... so what am I missing to get this to work?

Upvotes: 1

Views: 269

Answers (2)

Aviad P.
Aviad P.

Reputation: 32659

API resources are used to add claims to the access_token JWT.

Identity resources are used to add claims to the userinfo endpoint.

However, the userinfo endpoint is authorized using the access_token so it has no way to detect identity resource claims if they are not also included in the api resources that are included in the access_token.

So unless you override IProfileService and add claims manually, you have to include your identity resource claims in your api resource claims.

Upvotes: 0

Vidmantas Blazevicius
Vidmantas Blazevicius

Reputation: 4812

It doesn't work because when you add your claim via HttpContext.SignInAsync(..., new Claim("mycustom.myvalue", "987654321")) it is only retained whenever the user is actually present and the ClaimsPrincipal is created through the cookie authentication.

Because you are doing the roundtrip back to /userinfo it will only give you claims that the default IProfileService would normally return and it can't possibly know about that extra claim.

Try adding this claim to one of the TestUser directly (if you are using in memory users):

    public static List<TestUser> GetUsers()
    {
        return new List<TestUser>
        {
            new TestUser
            {
                SubjectId = "1",
                Username = "alice",
                Password = "password",

                Claims = new []
                {
                    new Claim("name", "Alice"),
                    new Claim("website", "https://alice.com"),
                    new Claim("mycustom.myvalue", "987654321")
                }
            }....

Upvotes: 0

Related Questions