Ideally in OAuth you should issue claims like the user's groups to access tokens so that they are readily available to APIs to use for authorization:
- You assign a client a custom scope like
orders, to represent an area of data.
- You create a custom claim like
groups and associate it to the scope.
- When the authorization server issues access tokens with the scope, it reads the user's account, retrieves group values and issues them as claims.
ENTRA ID
Entra ID requires vendor specific logic that adds complexity. If you try to issue group claims, I believe that Entra ID returns group object IDs as explained in this stack overflow answer.
To get group names you may need to send an access token to the Graph endpoint at https://graph.microsoft.com/v1.0/groups. You then get a response with items such as those listed below:
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#groups",
"value": [
{
"id": "ae0796f2-0b56-4511-8bd7-f86dedf6e2d7",
"createdDateTime": "2025-07-22T07:26:56Z",
"description": "Members of the DevOps team",
"displayName": "devops"
}
]
}
It is a little tricky though, since Graph requires its own type of access token, whereas you usually need a different access token for your own APIs. To get a Graph access token you are likely to need to use the On Behalf Of Flow. The following Node.js code demonstrates the approach, where an API swaps the incoming access token for a new one:
const formData = new URLSearchParams();
formData.append('grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer');
formData.append('client_id', this.configuration.graphClient.clientId);
formData.append('client_secret', this.configuration.graphClient.clientSecret);
formData.append('assertion', accessToken);
formData.append('scope', 'openid profile');
formData.append('requested_token_use', 'on_behalf_of');
const options = {
url: this.configuration.tokenEndpoint,
method: 'POST',
data: formData,
headers: {
'content-type': 'application/x-www-form-urlencoded',
'accept': 'application/json',
},
};
const response = await axios.request(options);
const graphAccessToken = response.data.access_token;
Finally, you need an app registration in Entra ID to represent the component that makes the Graph API groups request. That entry needs the GroupMember.Read.All permission and also provides the client ID and secret for the above OBO request.

SUMMARY
I suggest that you experiment to get the groups from Entra ID and then decide where to put the code. In NGINX this would be a subrequest which can be tricky to implement. I would try to avoid sending a secure value like groups in plain HTTP headers, since it allows an exploit to send its own groups. Instead, aim for APIs to receive the groups either in the access token (preferred) or by calling the Graph endpoint.