Search code examples
azure-active-directoryazure-api-managementazure-ad-graph-api

How do I check if the user from a non-Graph Azure AD token is a member of an email distribution list in an APIM policy


Have an API in Azure API Management (APIM). The API operation validates a JWT generated by Azure Active Directory (AAD) using a scope from a backend app registration (the scope is NOT User.Read). Note: client id is another app registration which is an authorized app of that backend scope.

After the JWT is validated, am I able take that token, extract user info out of it and verify if the user is part of a email distribution list (DL)? If so, how to do it within an APIM policy?

I am aware of MS Graph APIs. Using Postman I can confirm the DL is listed in the tenant's groups and can get its group ID. I can also confirm the user is a member of the group. The bit I'm stuck with for Graph API is that it needs a different token to the one supplied by the client application (due to he scopes being from different domains custom app registration vs graph) and I'm stuck at this point. Should I make the client app also get a graph token and pass it in a separate header, or is there way to orchestrate things from within APIM or something else?


Solution

  • The non-APIM part of this solution is provided by a Microsoft article. I've summarised those and combined with the APIM parts in the following steps:

    1. In Azure, create a new Azure App Registration (note the client id for later)
    2. Under "Certificates and secrets", add a client secret (note the secret for later)
    3. Under "API Permissions", add a new MS Graph Application Permission (can be User.Read.All, Group.Read.All, GroupMember.Read.All depending on your situation). MS Graph's "groups" includes both AD groups and Distribution Lists (DL). Note: don't use Delegated permission.
    4. Application permissions allow the authorized app to enquire about any user/group. You will need an Azure Admin to Grant Admin Consent for the App Registration to have the chosen Application Permission.
    5. Now in Azure APIM, go to your API and edit the inbound policy.
    6. Validate the JWT from the user making the call (See validate-jwt or newer validate-azure-ad-token) to ensure the User is authorized to call this API.
    7. Extract the oid claim from the JWT (this is the user ID I'll use for the graph call) and save it in a variable using set-variable policy
    8. Add a send-request policy request an auth token for MS Graph using client-credentials flow (this is when you'll need the client id and secret from earlier App registration). Note: secrets should be stored in a secure store like KeyVault but that is outside the scope of this answer.
    9. Extract the access_token field from the JSON response body and put it in a variable using set-variable policy.
    10. Create another send-request policy, but this time to the MS Graph endpoint. For User.Read.All permission you'd use /users/<userIdFromJwtOidClaim>/memberof/<groupId>. MS Graph v1.0 API Reference, and pass the access_token in the Authorization header using <set-header> element.
    11. A status code of 200 indicates the user is a member of the group. IIRC A status code of 403 indicates the user isn't a member of the group.
    12. Use a choose policy to perform logic depending on the user's group membership.
    13. Use return-response policy to send a response back to the user.