getting custom claims in Access Token for Client Server application in Azure AD? - azure

We have a client-server application that targets enterprise use cases mostly. We want to test if Azure AD is a valid IDP for our application that now supports authorization code flow but may be developed to support for authorization code with PKCE.
Our requirement is that we need 'preferred_username' and 'groups' as claims in the jwt based access tokens. The client application is a desktop based app (Win & linux) that authenticates users using any IDP speaking authorization code flow.
For POC, I used a trial account from Azure ad with default set of users in azure ad. Created security groups in the Azure Ad portal and added users to those groups. I registered apps as desktop/mobile based platforms and with an arbitrary redirect url. Under Token configuration, I added 'preferred_username' in access token as optional claim and 'groups' as part of both ID and Access Tokens.
I have set following in the application manifest:
"accessTokenAcceptedVersion": 2,
But these claims are never listed in the access tokens but only appear in ID token.
Is it possible to get these claims in access tokens, so the resultant access tokens can be used by our application?
Tried: Authorization code flow with PKCE for desktop/mobile app.
Expected claims preferred_username and groups in jwt Access token.
TLDR; Following below article, I am expecting an Access Token for my server:
https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-permissions-to-access-your-web-api
In my understanding:
Client App ---> Client App on Azure (with scope perms to Web Api)
Server App ---> Web API App on Azure (exposing scope)
CLient App permissions
Also, I think I am dealing with 2 issues here:
Get Custom Claims in Access Token with Authorization code (or Auth code + PKCE)
Access Token should be meant for my application ( and not MS Graph)

When creating a App registration, you have to add
groupMembershipClaims": "SecurityGroup",
To your manifest to access the security groups
https://learn.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-fed-group-claims
If you creating a enterprise application you can add Attributes & Claims within the single sign on settings.

Related

What is the flow of Azure AD based authentication in a project having SPA and web api?

I have a front end SPA (single page application) and back end api.
Each event in the SPA (like button click) invokes the respective api endpoint, and displays the result in the SPA.
I want to implement Azure AD based authentication so that only my Azure Tenant users are able to use the SPA/api.
Is the following flow correct approach to implementing such a feature:
User opens the SPA
User clicks on login button which opens Microsoft login popup
User enters Microsoft credentials in the popup, and if credentials are correct then user gets the JWT token
For every subsequent api request, the JWT token is placed in the bearer header
The endpoint validates the JWT token using Azure public key and rejects the request if token is missing or validation fails.
Is this flow correct and what is such a flow called?
There are several implementation steps that needs to be performed before you will have the flow that you have described:
User flow needs to be configured (Azure AD) - e.g. selfsignup allowed?
Backend and frontend applications needs to be registered (Azure AD)
Permissions and scopes needs to be added (Azure AD)
Backend API needs to be configured (e.g. API management) in order to validate the JWT token
I highly recommend to configure one of the Azure sample implementations end2end to get and idea of all the needed tasks: https://learn.microsoft.com/en-us/azure/active-directory-b2c/configure-authentication-sample-spa-app
The steps you outlined are correct.
An OAuth 2.0 "flow" outlines the steps to acquire a token from an Identity Provider (IdP). Since you are using a SPA, there are some restrictions on which flows you can use. A SPA can't act as a "Confidential Client" which is required for some flows. (Basically - the Client Secret required for the other flows would be visible in the browser network trace, so it's not "confidential".) The "Implicit Flow" used to be recommended for SPAs but it's less secure, so now the "Authorization code flow (with PKCE)" is recommended. Steps 2 & 3 in the question above are when you are executing the flow to acquire a token.
The authentication flow doesn't really address how you save and send the token to the API (#4 in the question), but the Microsoft Authentication Library (MSAL) helps with that - More information here - https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-spa-overview
In Azure AD, you'll want 2 App Registrations - one for your SPA and one for your API. The API App Registration will need to "Expose an API" which really means to define a scope. Your SPA App Registration will need to Add an "API Permission" to the scope you defined from your API App Registration. (It will show up in My APIs.) This relationship is how #5 in the question is enforced.
Many of the steps for setting up authentication in Azure AD and Azure B2C are similar but Azure AD is designed for authenticating users that are part of your organization. Azure B2C allows you to build a set of users that aren't members of a particular Azure AD organization.

Azure Active Directory Oauth 2.0 Client Credentials Flow with API Management Access Token issue

I have had been struggling to make my Azure Active Directory Oauth 2.0 Client Credentials Flow work with API Management. but I get authenticated via postman too. But in return I do not get any access token just a bunch of HTML. How can I fix this? The settings of the applications are exactly as per the documents including the validation of JWT Policy.
Basically I want my client apps to connect with my azure API's using Oauth 2.o without any consent using provided client id/secret. I'm trying to set this up for now with ECHO API provided out of the box with API Management console.
thanks
Postman Access token Error Screen
To use application permissions with your own API (as opposed to Microsoft Graph), you must first expose the API by defining scopes in the API's app registration in the Azure portal. Then, configure access to the API by selecting those permissions in your client application's app registration. If you haven't exposed any scopes in your API's app registration, you won't be able to specify application permissions to that API in your client application's app registration in the Azure portal.
For an example, if I sent scope parameter with custom name like https://testwebapp.in/.default without configuring same as application ID URI in Azure AD then is an expected behavior and you will get error AADSTS500011.
scope parameter in the request should be the resource identifier (application ID URI) of the resource you want, affixed with the .default suffix. For the Microsoft Graph example, the value is https://graph.microsoft.com/.default. This value tells the Microsoft identity platform that of all the direct application permissions you have configured for your app, the endpoint should issue a token for the ones associated with the resource you want to use.
Reference: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow#application-permissions

Azure AD auth + Angular/MSAL + ASP .NET Core best practices of tokens revocation

We are working on a web application. At client side we have Angular application that has integrated MSAL library for Azure AD authentication. At backend we have Asp .Net Core application that integrates MSFT Graph API service and sends http requests to Graph API on behalf of authenticated user. Main purpose for this Graph API requests is to manage App Roles assignments. So, our client side has UI for App Roles assignments management. Access token we receive from Azure AD contains set of assigned App Roles. Client side UI rendered according this set of App Roles (some menu items are hidden for low privileged roles).
Current task is invalidate/revoke client side token once user's App roles set updated.
Implemented steps: token lifetime decreased to 10 mins (minimal of allowed values).
Right now we are trying to use RevokeSignInSessions method of Graph API. It seems to be working for Azure Portal but does not for our client side. Seems that portal has some special settings for handling tokens.
Question: Is there any recommended way to go with such requirements?
If you use Azure AD for authentication, you should get an access token and a refresh token.
If you wish to revoke the refresh token, you can use power shell: Revoke-AzureADUserAllRefreshToken, or AAD Graph API : POST https://graph.windows.net/{tenant id}/me/invalidateAllRefreshTokens?api-version=1.6 HTTP/1.1.
However, the access token cannot be revoked, and it will automatically expire after 1 hour.

Credentials prompt for access to Azure management APIs

I've been using the Azure fluent management APIs (https://github.com/Azure/azure-libraries-for-net) with some success in .NET Core.
However, I want to prompt the user to enter some credentials for a Microsoft account. Those credentials would have access to one or more Azure tenants / subscriptions, so I'd like to be able to use the result to browse and manage resources there.
This is something very close to what I would believe Azure Data Studio does: you can enter some Azure creds, and your resources will appear in the app.
I'm trying to understand the best approach for this. There seem to be a billion sites out there when you talk about Azure AD app registrations, but I haven't found a fruitful specific search query yet. I know I can register an app, get a client ID and client secret. I know I can set it to be usable by organisational accounts in the current tenant, or all tenants.
I can add the "Azure Service Management (delegated permissions : user_impersonation)" permission to my API permissions section for the app, but what's next?
If I use Microsoft.Identity.Client (as in https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-v2-netcore-daemon), I run into some questions:
AcquireTokenForClientAsync doesn't prompt the user - I guess because it's getting a token for the app to act with its own permissions?
AcquireTokenOnBehalfOfAsync wants a JWT.. great! I'll pass the one I got from AcquireTokenForClientAsync! Nope, AADSTS70002: Error validating credentials. AADSTS500137: The token issuer doesn't match the api version: A version 1 token cannot be used with the v2 endpoint.
I don't know what scope I want. https://management.azure.com/user_impersonation is apparently invalid.. https://management.azure.com/.default works, but is that right? It's a guess, combo of the former and a .default suffix I found for Graph API scopes online. Any docs on this?
I ultimately get a JWT and tenant ID back. I can't find a way to use a JWT with the Fluent management APIs.. and my account (for instance) is associated with 3 tenants or 5 different tenants / directories - so how do I choose?
That's just what I've tried, the appropriate route might be a different one. In summary: I want a .NET Core Console app to request user credentials, and then get access to the Azure resources they have access to, in order to perform some resource management.
AcquireTokenForClientAsync doesn't prompt the user - I guess because it's getting a token for the app to act with its own permissions?
You are using the OAuth 2.0 client credentials grant to access web-hosted resources by using the identity of an application. This type of grant commonly is used for server-to-server interactions that must run in the background, without immediate interaction with a user .
AADSTS70002: Error validating credentials. AADSTS500137: The token issuer doesn't match the api version: A version 1 token cannot be used with the v2 endpoint.
Azure AD provide two service : Azure AD V1.0 and Azure AD V2.0 . Please refer to Comparing the Azure AD v2.0 endpoint with the v1.0 endpoint . You can't use v1 token to acquire v2's token in a on-behalf-of flow .
AcquireTokenOnBehalfOfAsync wants a JWT.. great! I'll pass the one I got from AcquireTokenForClientAsync
AS pointed above , That function is used to acquire an access token for this application (usually a Web API) from the authority configured in the application, in order to access another downstream protected Web API on behalf of a user using the OAuth 2.0 On-Behalf-Of flow. So you can't use app token which acquire using Client Credential flow .
https://management.azure.com/.default works, but is that right? It's a guess, combo of the former and a .default suffix I found for Graph API scopes online. Any docs on this?
You are using the Azure Active Directory v2.0 and the OAuth 2.0 client credentials flow , when sending a POST request to the /token v2.0 endpoint ,the scope should be :
The value passed for the scope parameter in this request should be the resource identifier (Application ID URI) of the resource you want, affixed with the .default suffix. For the Microsoft Graph example, the value is https://graph.microsoft.com/.default. This value informs the v2.0 endpoint that of all the direct application permissions you have configured for your app, it should issue a token for the ones associated with the resource you want to use.
Please check the Get a tokensection in above document .
I ultimately get a JWT and tenant ID back. I can't find a way to use a JWT with the Fluent management APIs..
AFAIK , currently Azure AD V2.0 apps can use:
Its own API
Microsoft Outlook APIs
Microsoft Graph API
Azure AD V2.0 currently doesn't support Azure management APIs .
So you problem is you need to allows work and school accounts from Azure AD and personal Microsoft accounts (MSA) which works with Azure AD V2.0 , but you can't use Azure management APIs . You can use Azure management APIs in Azure AD V1.0 but it allows only work and school accounts to sign in to your application , unless you invite Microsoft accounts as guest user in Azure AD V1.0 ,but you need to configure to point to the tenant-specific endpoint :https://login.microsoftonline.com/{TenantId_or_Name}). during authentication if you want to login with MSA in v1.0 apps.
Update:
You can use Code flow and azure ad v1.0 endpoint , user will be redirect to AAD's login page and enter their credential. Here is code sample for .net Core .
With Azure AD V1.0 endpoint , requests are sent to an endpoint that multiplexes across all Azure AD tenants: https://login.microsoftonline.com/common . When Azure AD receives a request on the /common endpoint, it signs the user in and, as a consequence, discovers which tenant the user is from. See document here . But in this scenerio ,you can only use work and school accounts(AAD) account to login .
The code sample in your link is using Azure Service Principal for Authentication , no interactive user login . You can use OpenID Connect Owin Middleware for authentication in .net Core applications as shown here .

How to access Azure B2C openId protected API by multiple client Application

I secure my nodeJs API with Azure B2C. I have two web application which accesses my API.
the two Web application has its own application Id in Azure B2C. Also, those can generate access_token with B2C.
But when I validate those access_token in my API I have to put application id of the web application witch generate the access_token as an audience.
But the audience does not support array. I can only put one application id.
How do I solve this?
If I secure an API with B2C I only can make requests from one web application?
The audience (aud) claim for an access token identifies the intended recipient (i.e. the API application) of the access token.
At a high-level, you must:
Register the API application in order for any client application to acquire an access token for use with the API application.
Grant access by one or more client applications to the API application.
Configure the application identifier for the API application as the expected audience for the API middleware.
The Azure AD B2C: Requesting access tokens article describes how a client application can acquire an access token for use with an API application.

Resources