Recently I ran into a puzzling issue while connecting an application to ADFS using its built-in OpenID Connect support. The login worked fine, the user got authenticated, but the ID token contained almost nothing I needed. No group claims, no custom attributes, just the basics.
The claim rules were configured correctly. So where were my claims?
Where did my claims go?
ADFS keeps a strict separation between the two tokens. The claims you define through the issuance transform rules end up in the access token. The ID token gets a much smaller set by default.
If your application reads the ID token to get user information, you have two options:
- Call the userinfo endpoint with the access token
- Ask ADFS to copy the access token claims into the ID token
This is where the allatclaims scope comes in.
What does allatclaims do?
When the authorization request includes scope=allatclaims, ADFS customizes the ID token so it includes the claims from the access token, based on your claim rules.
That’s all it does. It doesn’t add new claims, it only moves them to a place where your application can read them without an extra call.
Remark: The ID token is only returned when the request also includes the openid scope. allatclaims on its own does nothing useful.
Step 1: Grant the scope in ADFS
The scope has to be configured on the application group. In the ADFS Management console, open your application group, edit the server application and add allatclaims next to openid on the permissions.
Or with PowerShell:
Grant-AdfsApplicationPermission `
-ClientRoleIdentifier "<client-id>" `
-ServerRoleIdentifier "<web-api-identifier>" `
-ScopeNames "openid","allatclaims"
Step 2: Send the scope in the request
Configuring the scope is not enough. The application also has to ask for it. This is the part that is easy to forget.
The raw authorization request looks like this:
https://<adfs-server>/adfs/oauth2/authorize/
?response_type=code
&client_id=<client-id>
&redirect_uri=<redirect-uri>
&scope=openid allatclaims
In ASP.NET Core, add it to the OpenID Connect options:
.AddOpenIdConnect(options =>
{
options.Authority = "https://<adfs-server>/adfs";
options.ClientId = "<client-id>";
options.ResponseType = "code";
options.Scope.Add("openid");
options.Scope.Add("allatclaims");
})
Step 3: Check your claim rules
Because allatclaims copies what is in the access token, your claim rules on the Web API decide what you get. If a claim is missing from the ID token, look at the issuance transform rules first. Decode the access token and see if the claim is in there.
Tip: Paste both tokens in jwt.ms side by side. It makes it obvious which claims moved over.
Remark: More claims means a bigger token. If you push all your group memberships into the ID token, it can grow quickly. For users with lots of groups, the userinfo endpoint can be the better option.
