claims mapping of extension properties in access token in azure - azure-web-app-service

I am able to use claims mapping to add extenstion properties into an id_token. Is there a way to do that in an access token ? (Or is my only option to call Graph for that) ?

Assigning the claimsMappingPolicy to the servicePrincipal which represents the client app will add custom claim into id token. In order to add the custom claim into access token, you need to assign the claimsMappingPolicy to the servicePrincipal which represents the backend API, just like what you have done in the client app.
See detailed steps from this answer.
Please note that it only applies to the scene that you are trying to call your own API which is protected by AAD. If you are calling Microsoft Graph, you cannot make it work because it's impossible to configure claimsMappingPolicy from Microsoft Graph side.

Related

Best way to authorize with AzureAD app registration: roles or group claims when only one AD group is required for access

I have an AzureAD application registration for my front end SPA. I am using Angular with Microsoft’s #azure/msal-angular v2 authentication library. My app registration has all the necessary redirect URIs and configured for proper OAuth2 OpenID Connect using authorization code flow with PKCE. My app is using the Microsoft Graph API with only the User.Read scope. I can authenticate just fine. If my app, however, is only available for one group of people, defined by an AD group and assigned to the Users and Groups section in Azure, what is the best way to validate the logged in user is authorized? I’ve tried enabling optional group claims for the access token, but those don’t come through for some reason. I then tried adding roles-I have an “admin” role, which is the only one I need. This role is assigned to the AD group I mentioned earlier. The roles claim does come back, and I can use that, but this seems silly when I should be able to just validate if the logged in user is in my AD group. The roles approach does have the nice feature of just assigning users different roles to validate authorization for development purposes, but not sure if there’s a better way.
At some point there will be an API I need to plug in. Would it be best to get the claims from that and use that for validation?
Is there a scope or setting I’m missing? Am I achieving this all wrong? Thank you to all who reply.
At this point, you have a SPA that calls a MS 1st party API, which is MS Graph.
Since you are acquiring an accessToken to MS Graph, this accessToken can not be changed - it is meant to be decoded and validated by MS Graph itself, so you will not be able to add any extra claim on that token since you do not control the resource.
Also, your client should treat the accessToken as an opaque string, you should never rely on any claim from the accessToken on the frontend.
You can read more about it here:
https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens
If you want to do some sort of authorization on the frontend, like deciding which routes your user will have access to, you need to rely on the idToken. For the idToken, you can enable the Groups claim and get a list of groups that the user is a member of.
If, as mentioned, later down the line you need to create a custom API and call it from your SPA, then, on that scenario, you can indeed add the Groups claim to the accessToken, because it will be a resource that you control, and then authorize the requests that hit your API based on that claim
MS has a sample that shows exactly how to use security groups for access control, using an Angular frontend with a .NET Core Web API. Give it a check here:
https://github.com/Azure-Samples/ms-identity-javascript-angular-tutorial/blob/main/5-AccessControl/2-call-api-groups/README.md

Include Azure AD B2C aud claim in call to custom claim REST API

TL;DR: {OIDC:ClientId} is always the calling Application. I also need to know the "audience" application. Is there a claim resolver for this?
In more detail:
Here's the problem:
Application A and Application B are both registered in the same Azure AD B2C tenant.
A separate REST API (we'll call it "claims API") feeds custom claims into Azure AD B2C tokens. These claims must vary dependent on the application that consumes the token.
I use the {OIDC:ClientId} claims resolver to send the clientId of the requesting application to the claims API, like in this answer.
When Application A requests an access token for Application B, the Claims API receives the client ID for application A. However, I need to load claims for Application B, since that's the application that will actually consume the token. So the question is, how can I get the clientID for the target application as well as the requesting application?
I have considered using the {OIDC:scopes} claim resolver to solve this issue. That might work, but it seems a little like a hack. Are there any better options?
Per this document, it appears that {OIDC:scopes} is the only available option for this. And with some further thought, that makes sense, since some scopes might be requested that are outside the current tenant (Microsoft Graph API, for instance). In that case, it would not be possible to supply a clientId for the target application.
{OIDC:scopes} is a single string with all of the requested scopes separated by spaces. To detect when an access token is being generated for a different application than the current one, a simple string search on the scopes field is sufficient. If the App ID URI of an application is present in the scopes string, an access token is being requested for that application.

How to fetch Azure ID Token to use for authorization within webapi?

We are about to run D365 CRM in Azure and now we are trying to find out how to authorize a call to our onprem api.
The scenario is simplified like; A user is saving an annotation in D365 CRM and when that happens we also want to make a call to our onprem api.
We want to make the call using the Azure ID Token (to be specific NOT Access Token). This is to authorize the user when accessing the api.
Is it possible to get the ID Token and send that with the call? We have so far only managed to pick up the Access Token which is not good enough. How should we do to retrieve the ID Token?
You are mixing fundamental concepts of OAuth / OpenID Connect. You must use an access_token when calling an API. The purpose of id_token is not make authorization decision in an API, but to obtain basic information about the user in Client App.
You can find a really good formulated and compact article on the subject here.
When you have the access_token and when it is the proper one, it includes all the information you need:
Which is the calling application
Who is the acting end user
What authorizations (application roles or scopes) are granted
Any additional information (that could be part of the id_token) can be obtained using the Microsoft Graph on the back-end side of your API.
Here are some more references that will be helpful:
Microsoft Identity Platform id_token reference
Microsoft Identity Platform access_token reference
Pay attention to the claims references in both token types.

Having trouble getting Azure AD user's groups

I'm currently using node.js passport library to authenticate using the OIDC Strategy with an azure registered app using a client ID and secret.
http://login.microsoftonline.com/{org id}/v2.0/.well-known/openid-configuration
I am not having any trouble getting the user profile back of the person who logged in, but I am hitting a wall when trying to get the groups. In my app, I need to authorize the user based on their active directory groups. I am getting back this piece of json:
"_claim_names\":{\"groups\":\"src1\"},\"_claim_sources\":{\"src1\":{\"endpoint\":\"https://graph.windows.net/{org guid}/users/{user guid}/getMemberObjects\"}}
I'm not sure what I need to do using this to get the groups. I tried generating a bearer token, passing that in a header, and getting the groups but it says I am unauthorized using Postman. Do I need certain permissions in the app? Also why is it using graph.windows.net when I'm trying to use graph.microsoft.com?
Is there an easier way to do this once the user has logged in?
Overage indicator claim when user is member of many groups
The claim you're getting back as part of json shared in question is an overage indicator claim.
"_claim_names\":{\"groups\":\"src1\"},\"_claim_sources\":{\"src1\":{\"endpoint\":\"https://graph.windows.net/{org guid}/users/{user guid}/getMemberObjects\"}}
It means that the user is member of many groups and instead of including information about all the groups as part of token (which would make the token too big), you will need to query that information separately.
Read more about it here: Access Tokens Reference
How to get groups information?
Your application needs to make a separate call to Microsoft Graph API to get the groups information for user.
Relevant Microsoft Graph APIs
user: getMemberObjects
user: getMemberGroups
Check member groups
Permissions Required by your application
Each of the API links above mention the required delegated or application permissions that are required as part of documentation.
You will need to update your app registration in Azure AD to require the relevant permissions (and also go through Admin consent, in case the permission required needs admin consent)
Token to call Microsoft Graph API
You mention that you've tried generating a bearer token, passing that in a header, but you got Unauthorized error.
Once you're done with the permission changes for your application, acquire a token specifically for Microsoft Graph API from your application. The bearer token used to access your application may not directly work with Microsoft Graph API.
Also make sure you go through Admin consent in case any of the permissions require Admin consent. If it's a single tenant application, "grant permissions" directly from azure portal by an administrator should work, in case of multi-tenant app you can use the Admin consent endpoint.
Code Sample: Here is a quick tutorial for calling Microsoft Graph using Node.js.. you may find other good ones as well.
Azure AD Graph API (graph.windows.net) vs Microsoft Graph API (graph.microsoft.com)
You have a valid question about the endpoint.. "Also why is it using graph.windows.net when I'm trying to use graph.microsoft.com?"
General recommendation is to use the newer Microsoft Graph API, unless the functionality/information you're looking for isn't available with Microsoft Graph and only Azure AD Graph API can help. Read more about recommendation and comparison here: Microsoft Graph or Azure AD Graph
Since information about groups is available in v1 endpoint for Microsoft Graph already (not beta), you should make use of Microsoft Graph API.
Here are a couple of related SO posts: SO Post 1 and SO Post 2

Add claims into token Azure B2C

What are ways to include custom claims (user subscriptions or roles list as example) in a token before issuing it in Azure AD B2C, provided that claims are stored somewhere on own server (not available in B2C)?
Goal to have claims in the token to avoid additional round trip to the storage on every request.
Investigation on the topic brought me to following ways:
Add custom attribute via Graph API, configure to include in JWT. Attribute values should be kept in sync with our datastorage.
Custom Sign-In Policy like in this article https://learn.microsoft.com/en-us/azure/active-directory-b2c/active-directory-b2c-rest-api-step-custom but if I got it right, additional Step 6 is a user journey to publicly available API in non restricted way (request not secured by secret, might be used to get user claims by presented UserId)?
IdentityServer4 Federation gateway http://docs.identityserver.io/en/release/topics/federation_gateway.html that will allow to add any claims before issuing.
The first two mechanisms you outlined are the most common and recommended ways to include custom claims in an Azure AD B2C issued token:
Add a custom attribute and include it in the JWT. You can enable the custom attribute via the B2C UI or via the Graph API. You'd need to build your own mechanism to keep the value of this attribute in B2C in sync with your external source via the Graph API.
You can use a custom policy to add a step in your authentication flow to call a Rest API to obtain the claim and include it in the token. This call to the Rest API will be performed by the Azure AD B2C service and NOT the user's browser, so it'll be a service-to-service call (versus a client-to-service call), keeping any secrets you use for authentication with your Rest API safe (such as a Azure function code).

Resources