Search code examples
asp.net-coreidentityserver4

Sub claim missing from ProfileDataRequestContext.RequestedClaimTypes


In IdentityServer4 I have defined an IdentityResource with some claims:

new IdentityResource {
  Name = "userdata",
  UserClaims = new List<string> {
    JwtClaimTypes.Subject,
    JwtClaimTypes.Role,
    JwtClaimTypes.Email,
    JwtClaimTypes.Name
  }
}

And then add it to the scopes in the client configuration:

AllowedScopes = {
  IdentityServerConstants.StandardScopes.OpenId,
  "api1",
  "userdata"
}

In the client app I requested that scope:

.AddOpenIdConnect("oidc", options => {
  options.Scope.Add("openid");
  options.Scope.Add("userdata");
  options.Scope.Add("offline_access");
  options.Scope.Add("api1");
}

In IS4 I have implemented IProfileService to add some claims to the id_token.

public async Task GetProfileDataAsync(ProfileDataRequestContext context) {

  var sub = context.Subject.GetSubjectId();
  var user = await _userManager.FindByIdAsync(sub);
  if (user == null) {
    throw new ArgumentException("");
  }

  var principal = await _claimsFactory.CreateAsync(user);
  var userClaims = principal.Claims.ToList();

  var claims = new List<Claim> {
    userClaims.Find(x => x.Type == JwtClaimTypes.Subject),
    userClaims.Find(x => x.Type == JwtClaimTypes.Role),
    userClaims.Find(x => x.Type == JwtClaimTypes.Email),
    userClaims.Find(x => x.Type == JwtClaimTypes.Name),
    new Claim("iesseapetenantid", user.TenantId.ToString())
  };

  var requestedClaimTypes = context.RequestedClaimTypes;

  context.AddRequestedClaims(claims);
}

context.AddRequestedClaims(claims) filter the claims passed and add only the ones requested by the client.

The problem is that in context.RequestedClaimTypes the sub claim is missing but the other three are there: email, name and role.

enter image description here

Why is the "sub" claim missing?

Thanks!


Solution

  • The sub claim is the one required by the spec, so it's a part of the StandardScopes.OpenId. You do not need to setup or request it additionally.

    var sub = context.Subject.GetSubjectId();
    

    assumes that the sub claim is already within the context. If not, an exception will be thrown.

    All above is about IdentityResource and id_token. A token for ApiResource may be created without referencing a user.