Search code examples
c#asp.net-coreopenid-connectidentityserver4

Claims for IdentityServer4 user not included in JWT and not sent to Web Api


Following the official IdentityServer4 documentation, I reached the point where I have an MVC client app, IdentityServer4 and a Web Api (resource server running). IS4 homepage displays all claims for the user, and when calling the api with the access token, we again get as a result all the user's claims.

Sample code is available here, although it's probably not necessary, and I'm just missing something obvious.

Anyway, for simplicity's sake let's not get claims from the DB and just assign a random hardcoded one:

public class ProfileService : IProfileService
{
    public Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        context.IssuedClaims.Add(new System.Security.Claims.Claim("role", "admin"));
        return Task.FromResult(0);
    }
    ...
}

I register the custom Profile service in the startup file and now when I'm logged in on IS4, I see the additional claim.

However, when calling the web api (resource server), this additional claim is not included in the JWT. Code for api call:

    public async Task<IActionResult> CallApiUsingUserAccessToken()
    {
        var accessToken = await HttpContext.Authentication.GetTokenAsync("access_token");

        var client = new HttpClient();
        client.SetBearerToken(accessToken);
        var content = await client.GetStringAsync("http://localhost:5001/identity");

        ViewBag.Json = JArray.Parse(content).ToString();
        return View("json");
    }

(All the api does is return the list of User.Claims). My added claim is not in there, and when I debug the code and pick the access token string and decode it on jwt.io, there's no such claim again.

Question is : what am I missing? is the HttpContext.Authentication.GetTokenAsync bad for my use case, and if so - what is the substitute I'm supposed to use?

Edit: Here are the OpenId Connect Options (on the MVC client):

        app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
        {
            AuthenticationScheme = "oidc",
            SignInScheme = "Cookies",

            Authority = "http://localhost:5000",
            RequireHttpsMetadata = false,

            ClientId = "mvc",
            ClientSecret = "secret",

            ResponseType = "code id_token",
            Scope = { "api1", "offline_access" },

            GetClaimsFromUserInfoEndpoint = true,
            SaveTokens = true
        });

Solution

  • I guess the reason is that you haven't assigned any claims to your API. This is why we don't call the profile service at all.

    This is a common problem and a little inconsistent since we are always calling the profile service for identity tokens.

    We changed this behavior in 1.0.2

    https://github.com/IdentityServer/IdentityServer4/releases/tag/1.0.2

    Please try again and see if this gives you the expected result.