Group claims with Azure AD and OAuth2 implicit grant in ADAL JS - angularjs

Background
We are developing a multi-tenant SaaS product in Azure which has an AngularJS front-end and Web API back-end. We use Azure AD for authentication and have hooked it up with ADAL JS (using the OAuth2 implicit grant). Being a multi-tenant application, we allow customers to authenticate against their own Azure AD (which may or may not be connected to an on-premise AD).
So far this all works nicely. ADAL JS takes the user to the Azure login page and once the user has authenticated, an OAuth2 token is issued. This JWT token is then sent with all API calls as a bearer token where we have our own claims transformation process for mapping the incoming claims from Azure to our application claims.
Rather than specify individual users in the claims transformation process, we try to do it by AD groups. This allows our customers to have security groups in their AD and then our application will use that to map to the correct application claims.
The problem
The JWT token we receive does not contain a groups property, despite having set groupMembershipClaims to SecurityGroup in the AAD application manifest. I have since read in this tweet from Vittorio that
The implicit grant will NOT send those claims, as it returns the token in the querystring - it's easy to blow past max length
Upon further investigation, I also found this StackOverflow answer from Vittorio that says
I verified and in the implicit grant case you will receive groups always via the overage claim. Please refer to https://github.com/AzureADSamples/WebApp-GroupClaims-DotNet/tree/master/WebApp-GroupClaims-DotNet - it will show you how to process the overage claim to retrieve groups.
I had a look at the JWT token and it does not include any overage claim (identified by _claim_names and _claim_sources). I'm definitely a member of two groups in my Azure AD.
I also now appear to have two conflicting statements about whether it is possible to get group information (whether directly or indirectly) in the implicit grant token.
Question 1: Should I get an overage claim that I can use to get group information? If so, do I need to do anything to ensure that claim gets sent to me?
Graph API
Whether I can get an overage claim with a link to the user in the graph API or whether I have to manually craft the link to get the user's groups, I'm still a little unsure how I authenticate with the graph API.
I need to contact the graph API from the back-end after receiving a request with a bearer token (from ADAL JS).
Question 2: Can I send the same bearer token to the graph API to read that user's directory information? Or do I need to authenticate directly from my application to the graph API tenant in the context of the application rather than the user?

apologies for the confusion here. I will double check the statement about the overage, but in any case - for the sake of unblocking you quickly, let's assume that you need to get the groups manually without the aid of the overage claim. You cannot reuse the token you send to your Web API. That token is scoped to your app, and any other recipient will (or should) reject it. The good news is that the flow through which your backend can request a new token scoped for the Graph is easy to implement. See https://github.com/AzureADSamples/WebAPI-OnBehalfOf-DotNet - the details in your case are a be a bit different (your web API has the audience == clientid of your app) but the topology and the code/calls involved are exactly the same. HTH! V.

Related

How to use Azure AD access_token and id_token

I have registered two applications in Azure AD, a .Net core web API and a single page react application. I configured these applications to get the id_token for the react client application and an access token for consuming the web API when the user signs in to the client application. I need to send user-specific information to my API when the user signs in (I need to get a unique id from the token to identify the user). Some document says we can't send the id_token to the API since it is issued for the client application. and some says we can't send the user-specific information via access token since it should be used for authorization purpose only.
Is there any other way to solve my problem?
In the context of Open Id connect, is it ok to send user-specific information via access token? I want a unique id from the token and store it in my system to identify the user. if it is ok to use the access token, Which claim is best suited for this purpose (sub or oid)?
You are right that you should not send the id_token to the API. One option is to include the necessary user information as claims inside the access token. Alternatively you could try to ask AzureAD for the user details when the API receives the access token. Azure for example provides the UserInfo endpoint for this.
See this page Microsoft identity platform UserInfo endpoint

Is there a way to get a list of Azure AD tenants from within a service principal?

I have created an app to get various information from Azure AD, such as users and groups. It lives in one of my tenants as an app registration. This works fine, but now I would also like my app to get a list of the ids of other tenants I have in my account.
I have given my app user_impersonation permission on Azure Service Management, and I am able to make
GET https://management.azure.com/tenants?api-version=2016-06-01 requests using my client credentials. However, when I make that call I get a list only containing the tenant that my app/service principal lives in. Is there a way I can use this API call to see other tenant ids from within my app?
Yes, you could do that with auth code flow instead of client credentials flow.
Since you are trying to get the tenants of your account rather than the app/service principal, you have to include the account information when doing the authentication.
Client credentials flow is App-only. Auth code flow is App+user.
See reference here to learn how to implement Authorization code grant (interactive clients).
And here is the document about OAuth 2.0 authorization code flow.
You need to Request an authorization code first and then Request an access token with the code from the previous step. Using this access token, you can list the tenants you have in your account.

Why do I need two AAD applications just to add roles into an access token?

As shown by many samples I have two AAD application registrations, one for my javascript-based front end, and one for my JSON-only web APIs.
If I fully trust my client AAD application, why does AAD require me to create a second AAD application for my web APIs?
For example, assuming I add specific roles to my client AAD application, if client signs in with AAD and gets an id token and access token containing my roles, it only needs to send the access token to my APIs. The API only needs to crack the JWT, validate the audience, issuer, tenant, roles permissions, and signature. In this world, no client secret is needed in the web APIs, a second AAD application registration not needed, and still no call to AAD from my APIs. Unfortunately, without two AAD applications, I cannot figure out a way to have AAD include roles into my access token.
If I didn't fully trust the issuer from mucking with claims, I can see why I would need two AAD applications and a client secret. But since I do trust my AAD application and the signature of the JWT, why the extra complexity? Or maybe there is a way to do this that I haven't found?
Thanks!
Responding to Marc here because just not enough characters in the comments field -- The sample you referenced is an excellent sample, specifically the JavaScript one calling the Web API. It is what I am doing right now in fact. However, the problem is that Web API in the sample is open to anybody who has authenticated on the tenant. I need to secure the Web API down to certain individuals in the tenant, and simply checking the client/app id is not sufficient as anybody who can create an AAD app can fake it.
So what I need to do is have roles added to the the access token so I know that my application authenticated the user, and that user has been granted the required roles. For example, here is a Microsoft sample. And even here a Microsoft video walking through the process.
If I don't have two AAD applications w/client secret, the roles claims is never provided in the access token. It is always provided in the id token, but not the access token.
I feel like I am missing something obvious here. If AAD would just put the roles I requested into the JWT when I authenticated against it, and I validated its signature, audience, issuer, and roles, I wouldn't need any of this extra complexity?
Ah, I think I understand where you are going: you would like to control which users can access an API, no matter what client app they are using to access the API with. That's a function of the API - you cannot control that through AAD. In AAD you can control which users can access which applications (UI) using either user access restrictions (enterprise tab) or role-based access. However, access to an API is controlled in AAD at the calling application level via scopes. APIs are never accessed directly by users but only by other apps so controlling access permissions at user level would cause admin havoc. So, you can control what permissions a user has in the app they are using and you can control what permissions that application (client) has in other applications (APIs, resource servers) it is using.
In other words: role is about user access to UI, scope is about one apps' access to another.
App secrets provide added security for getting tokens - they have no bearing on what permissions are included in the token.
Can you provide a link showing that two apps are needed? That should only be the case if the API you want to call is not provided by the web app which served the JS to the browser. None of the 'official' samples require you to register two apps (Graph API, used in some of these samples is a separate API and it is already registered). A problem with tokens passed from the browser is that they were acquired by a public client, not using any secrets apart from user creds. Therefore, they are easier to steal and re-use. Your own back-end app may want to use a secret to get its own token (extension grant) to call yet another API using a token that does not reside in a public client.

Why do i need to create a Multi-Tenant App?

I have been doing some R&D on using the MicrosoftGraphAPI to fetch the skus subscribed by my organization.
I have created an app as described in the documentation. I did all the steps in the above link except 'Assign application to role'.
Using postman am able to get the oauth2 token by sending a post request using the link
https://login.microsoftonline.com/<mytenantid>/oauth2/token
with the client_id, client_secret, resource(https://graph.microsoft.com) and grant_type(client_credentials) parameters.
After this token is obtained I can fire a get request https://graph.microsoft.com/v1.0/subscribedSkus with the Authorization header set as Bearer {token} which will return the SKUs subscribed by my organization.
So far so good. :-)
Now the requirement is I need to fetch the subscribed SKUs by one of the client (let's say having the azure ad tenant id 'ABCDEFG') of my organization.
I can successfully do that by registering an app in the client's tenant 'ABCDEFG' with the same steps as above.
This approach is fine if my organization has say 1 or 2 clients.
However, if the client numbers are more than say 30 this approach of registering an application in each Azure AD instance is not feasible.
If the application that I registered in my organizations AAD was multi-tenant then how should it help me?
What will be the steps needed to obtain the access token for each tenant?
Can somebody assist with some detailed explanation?
Since you need application-level access, you would assign one of the Application permissions listed in the documentation for getting SKUs: https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/subscribedsku_list.
Directory.Read.All, Directory.ReadWrite.All
In this case you should require the Read Directory Data (Directory.Read.All) application permission.
Then you mark your app as multi-tenanted.
Now then in order for another org to use your app, they will have to be on-boarded.
You will need some kind of page where their administrator can click a button/link to start using your app.
This should redirect the admin to:
https://login.microsoftonline.com/common/oauth2/authorize?client_id=your-client-id&prompt=admin_consent&response_type=code+id_token&redirect_uri=url-where-to-send-user-back
Once they sign in, they will be presented with a consent screen, where they can approve the permissions that your app requires.
If and when they do that, they will be redirected back to your app (to the URL you specified) and you can use the Id token to know which Azure AD tenant registered.
During this process a service principal for your app is created in their tenant, and the required permission is granted to it.
This means you can then get an access token for their tenant from: (using the same credentials)
https://login.microsoftonline.com/their-tenant-id/oauth2/token
Remember that access tokens are specific to an Azure AD tenant, so you will have to get an access token for each tenant.
One thing I would like to point out is that you should instead try to use delegated permissions if possible.
The application permission given here gives quite large access to your app, and some admins might not use your service for that reason alone.
Delegated permissions are more complex to handle, but allow your app to act on behalf of a user instead of purely as itself.

Is Azure OAuth 2 auth code grant an authentication protocol

Sorry I am still very confused, read everywhere telling me oath is a authorisation protocol but it appears using the azure ad oauth code grant, it does promote a login screen to authenticate against the directory, so is it not an authentication process? what is the relationship between the open id connect? thanks!!
the OAuth2.0 protocol has several flows that an identity provider (in your case Azure AD) may implement to support auth.
The Auth Code flow is in fact one of these used by apps to get access tokens for some api. The flow is quite simple, an app redirects the user to the identity providers /authorize endpoint. At this point the user enters their credentials, and the site redirects back to your application with an authorization code and can also issue an ID Token that represents a user (This is the OpenID Connect part). The app takes this code, and POSTs it to the /token endpoint and will be issued an access token and refresh token. With the access token, your app can access whatever api you've requested access for.
For Azure AD specifically, Microsoft has built libraries that handle all these flows and token caching so most of the complexity is abstracted away. There's some simple code samples that you can checkout that you may find helpful. The authentication protocols and scenarios doc for Azure AD may also be really helpful for conceptual information.

Resources