Reputation: 337
i'm having trouble trying to figure out how to properly use the userinfo endpoint. my example uses identity server 4 as an authorization server.
let's say i have a js app that displays an authenticated user's location. let's assume that i have some user store which provides claims including the users' location. the iprofileservice interface has been implemented so that GetProfileDataAsync retrieves the users claims from the user store for the user.
the js app needs to have access to the user's location claim. one way to do this would be to add an identityresource to ids e.g.
new IdentityResource("test", new [] {"location"})
then add the scope to the js client e.g.
new Client
{
ClientId = "js",
AllowedScopes =
{
IdentityServerConstants.StandardScopes.OpenId,
"test"
}
}
then configure the oidc library to request that scope e.g.
var config = {
authority: "http://localhost:5000",
client_id: "js",
redirect_uri: "http://localhost:5003/callback.html",
response_type: "id_token token",
scope:"openid test",
post_logout_redirect_uri : "http://localhost:5003/index.html",
};
doing so would mean that the id_token would contain the location claim and this would be accessible as part of the users' profile. the same claim would be returned when calling the userinfo endpoint with the access token received during authentication.
however i have repeatedly read (here, for instance) that you should put as few claims as possible in to the identity token and then use the userinfo endpoint to retrieve additional claims. the linked article seems to imply that this behavior is available by default in identity server.
so in order to do that, using the example code i mentioned above, i'd remove the 'test' scope from the requested scopes for the oidc config. this means that the id token will no longer be populated with the location claim. however when the userinfo endpoint is called, the 'test' scope is not in the access token, so the location claim will not be put in the response.
basically my question is how are you supposed to ask for claims to be omitted from the id token, but returned from the userinfo endpoint?
the oidc spec also seems to imply that you should be able to request specific claims using the "claims" request parameter, but i cant find any documentation around this for identity server (or auth0 for that matter).
Upvotes: 4
Views: 6964
Reputation: 18482
If you request an identity token only, all claims will be in that token. If you request both an id_token and a token, only the basic claims will be in the id_token, and all other claims can be retrieved from the userinfo endpoint.
This is was the spec suggests.
https://leastprivilege.com/2016/12/14/optimizing-identity-tokens-for-size/
Upvotes: 2
Reputation: 6415
One way I've accomplished this is by the use of IdentityResource
versus ApiResource
.
For example, in your startup > ConfigureServices
services.AddIdentityServer(x =>
{
x.IssuerUri = webServerSettings.Host;
})
.AddSigningCredential(webServerSettings.CertificateSubjectDn)
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryIdentityResources(Config.GetIdentityResources());
And then in my config having something like this for GetApiResources
:
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource
{
Name = "MyApi",
ApiSecrets = { new Secret("somesecret".Sha256()) },
UserClaims = {
JwtClaimTypes.GivenName,
JwtClaimTypes.FamilyName,
JwtClaimTypes.PreferredUserName
},
Description = "some description",
DisplayName = "my api display name",
Enabled = true,
Scopes = { new Scope("MyApiScope") }
},
new ApiResource("otherAPI", "Some other API"),
};
}
but also have this for GetIdentityResources
:
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId(),
// The identity scope defines the claims available at the client by calling the
// userinfo endpoint, and does not need to match the claims available to the API
// which are defined as part of the ApiResource above
new IdentityResource
{
Name = "MyApiIdentityScope",
UserClaims = {
JwtClaimTypes.Email,
JwtClaimTypes.EmailVerified,
JwtClaimTypes.PhoneNumber,
JwtClaimTypes.PhoneNumberVerified,
JwtClaimTypes.GivenName,
JwtClaimTypes.FamilyName,
JwtClaimTypes.PreferredUserName
}
}
};
}
By doing this, calls to GetProfileDataAsync
will have different RequestedClaimTypes
depending on whether this is coming through the UserInfo endpoint, or just from a request for a token.
Upvotes: 0