2

In my Client I have the following set up.

services.AddAuthentication(options =>
    {
        options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        //options.DefaultSignInScheme = "Cookies",
    })
    .AddCookie()
    .AddOpenIdConnect(options =>
    {
        options.Authority = "...";
        options.ClientId = "...";
        options.SaveTokens = true;
        options.ClientSecret = "secret";
        options.SignInScheme = "Cookies";
        options.Scope.Add("openid");
        options.Scope.Add("profile");
        options.Scope.Add("roles");
        options.ResponseType = "code id_token";
        options.GetClaimsFromUserInfoEndpoint = true;
        options.Events = new OpenIdConnectEvents()
        {
            OnTokenValidated = tokenValidatedContext =>
            {
                var identity = tokenValidatedContext.Principal.Identity
                    as ClaimsIdentity;

                var targetClaims = identity.Claims.Where(z =>
                    new[] {"sub"}.Contains(z.Type));

                var newClaimsIdentity = new ClaimsIdentity(
                    targetClaims,
                    identity.AuthenticationType,
                    "given_name",
                    "role");

                tokenValidatedContext.Principal =
                    new ClaimsPrincipal(newClaimsIdentity);

                return Task.CompletedTask;
            },
            OnUserInformationReceived = userInformationReceivedContext =>
            {
                return Task.FromResult(0);
            }
        };
    });

My client at the level of IdentityServer is defined as follows.

new Client()
{
    ClientName = "My App",
    ClientId = "mymagicapp",
    AllowedGrantTypes = GrantTypes.Hybrid,
    RedirectUris = new List<string>()
    {
        "https://..."
    },
    AllowedScopes =
    {
        IdentityServerConstants.StandardScopes.OpenId,
        IdentityServerConstants.StandardScopes.Profile,
        "roles"
    },
    ClientSecrets = { new Secret("secret".Sha256()) },
    PostLogoutRedirectUris =
    {
        "https://..."
    }
}

The new "roles" scope is added as per below.

public static IEnumerable<IdentityResource> GetIdentityResources()
{
    return new List<IdentityResource>()
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile(),
        new IdentityResource("roles", "Your role(s)", new List<string>(){"role"})
    };
}

A user is defined as follows.

new TestUser()
{
    SubjectId = "abcdef",
    Username = "Jane",
    Password = "password",
    Claims = new List<Claim>()
    {
        new Claim("given_name", "Jane"),
        new Claim("family_name", "Doe"),
        new Claim("role", "FreeUser")
    }
}

After logging in to my MVC client, in the Controller the User.Claims object does not contain role claim.

However, in the OnUserInformationReceived the userInformationReceivedContext's User object does contain the role claim.

What am I missing?

sakura-bloom
  • 4,524
  • 7
  • 46
  • 61
  • I have a suggestion - try with another claim name for the first tests. Role claim is part of the OpenId. Just to be sure that there is no duplication, start with something else, until you figure it out, and then change it back to what you need. – m3n7alsnak3 Mar 14 '18 at 20:17
  • Thanks for the suggestion. I renamed `role` (and `roles` IdentityResource) to something else, and it still does not show up on `User.Claims`. It seems that the user claims are not processed for some reason. – sakura-bloom Mar 14 '18 at 20:27
  • Oh I think I got it - in the Client at the IdentityServer level, set `AlwaysIncludeUserClaimsInIdToken` to true (it defaults to false) – m3n7alsnak3 Mar 14 '18 at 20:48
  • Yes, this will probably fix the problem, but it will increase the size of cookie. This is what I'm trying to avoid. – sakura-bloom Mar 16 '18 at 01:55

1 Answers1

2

Based on

the solution was to add options.ClaimActions.MapJsonKey("role", "role"); inside .AddOpenIdConnect(options => ...)

From the second link:

2.0 no longer adds all possible information from the user-info endpoint, it was causing major cookie bloat leading to login issues. There is now a system called ClaimActions where you can select which elements you want to map from the user info doc to claims. See OpenIdConnectOptions.ClaimActions.

sakura-bloom
  • 4,524
  • 7
  • 46
  • 61