How to add roles claim in access_token , currently it is coming in id_token? - azure

I am following Authentication code flow with PKCE and my Identity provider is Azure Active directory.
I have created a App , "client-app" from App Registrations. In the manifest I have added appRoles like the following.
"appRoles": [
{
"allowedMemberTypes": [
"User"
],
"displayName": "StoreGroupManager",
"id": "47fbb575-859a-4941-89c9-0f7a6c30beac",
"isEnabled": true,
"description": "Consumer apps have access to the consumer data.",
"value": "StoreGroupManager"
}
]
I am assigning this role StoreGroupManager to Users. Now when I follow Authorization code flow with PKCE and obtain the id_token , refresh token and access_token. I can see that the id_token has a claim roles but not the access_token.
I need to have roles claim claim in the access_token. Can this be possible?
The following is the decoded id_token.

Roles will be in the access token if the app registration for the API that the access token is for defines those roles and they are assigned to the user.
So if you use the same app registration for the client and API, they should be there.
But if you have separate app registrations for the client and API, you will need to define the role in both apps and assign the user to it on both of them as well.

Related

Azure AD B2C Authorization support based on Scope/Role

We want to achieve an authorization at our APIs.
Ex. We have API-A and API-B and both are exposed to our different consumers.
We have setup of scope based authorization in place with IdentityServer4 where we decorate endpoints with different policies. With IdentityServer4 we are able to achieve this as IdentityServer4 token has scopes claims present in all the grant types but with Azure AD, we found we can't have scope claim in token generated with Client Credential flow.
In our case, Web API B is also exposed to consumers and again they have scope based authorization. To call, Web API B from Web API A we use client credential flow and it will not have scopes claim in token so we are not able to authorize our call to Web API B.
How to achieve scope based authorization with Azure AD in microservices architecture where we call other context APIs from one context.
When you are using client credential flow and using
application permission , you get roles and not scope i.e; scp claim in the token.
Application permissions are sort of roles given to the application
itself and the scope in client credentials should be used as
api://<APP_ID>/.default . They only apply when doing client
credentials authentication, where no user is involved.
See quickstart to configure app access web-apis
Scopes are usually delegated permissions that only apply when a
user is involved in the login process. They allow you to act on
behalf of a user i.e; In the user context only, we will get
scp claims in case of client credential flow.
See azure-ad-scope-based-authorization
So , If you want delegated permissions then you will have to use implicit grant flow instead of client credentials.
As scopes in expose an api page are for Authorization Code Grant flows and where the user is involved, in this case (client credential) its not possible, we have to add our own scopes that is availible for applications to use which are indirectly called roles that we need to add in the manifest itself under approles in the app registration or through the app roles blade.
ex:
{
"appRoles": [
{
"allowedMemberTypes": [
"Application"
],
"displayName": "Read all todo items",
"id": "f8dxxxxxxxxxxxxf98",
"isEnabled": true,
"description": "Allow the application to read all todo items as itself.",
"value": "Todo.Read.All"
}
]
}
After that , those has to be granted admin consent.
So now when requesting a token with a default scope of api://<app id>/.default the "scopes" are returned in the roles claim.
So we can use role claim for authorization purpose.
Also as a work around
Try to make sure to add additional scope like profile, offline_access open_id.
And give response_type=token instead of id_token
Example request:
......&redirect_uri=https://jwt.io&scope=openid profile offline_access&response_type=token&prompt=login
References:
Scope-based authorization in your API with Azure AD – the IT generalist (wordpress.com)
Scope is not being added to Access Token returned from Azure Ad - Stack Overflow
EDIT:
To call a web api from other , there need to be scopes defined in
one api i.e (api2 that you want to call) and those scopes need to be
selected in calling api(api1) . Please go through the process
here
When login in first Api include scope in the request and also try
response type as Token and see if scp available or then with idtoken
https://tenant.b2clogin.com/tenant.onmicrosoft.com/oauth2/v2.0/authorize?p=B2C_1_TenantSignUpIn&client_id=<appid>&nonce=defaultNonce&redirect_uri=https://jwt.ms&scope=openid offline profile https://tenant.onmicrosoft.com/b2capi/write https://tenant.onmicrosoft.com/b2capi/read https://tenant.onmicrosoft.com/b2capi/user_impersonation&response_type=id_token&prompt=login.
Please note that scopes are present as roles depending on the flow
type.

How to get user role claims in postman from Azure active directory?

I have a few users added to my Azure AD account, I would like to get the roles and user information on these users by calling an Azure API from Postman in the form of claims. I tried calling the following URL with the parameters as :
https://login.microsoftonline.com/myTenantId/oauth2/token
Body:
grant_type : password,
client_id : client id,
client secret : client secret
I receive the access_token in the encoded format in the response, When I decode it on https://jwt.io/ I see the decoded data, but there's no user roles in the access_token.
I would like to get the user information and the roles in the form of claims in same response.
What approach would I need to take on this ?
If the role you mentioned refers to directory role, the answer is no, it won't be returned in the token. Just like juunas said, you can call graph api to get directory role information.
If the role you mentioned refers to application role, the answer is yes, you can get the role information in id_token. The prerequisite is that you have assigned some roles to the user.
Here are the detailed steps. You can also refer to this article.
edit the manifest to add some custom roles.
Something like this.
{
"allowedMemberTypes": [
"User"
],
"displayName": "Test",
"id": "c200e304-fff3-49f1-a4df-e406741ea680",
"isEnabled": true,
"description": "Bla bla",
"value": "test"
}
2.assign users to roles.
Click Enterprise applications->All applications->
Click your application->click Users and groups->click Add user
role assign.
Here is the request to get id_token.
You will find the roles in id_token.

Microsoft graph and Azure Ad user authentication

I have an application registered in Azure ad.
When i do ADAL with the following details i get a authoriazation token to use with microsoft graph api.
`username = 'admin#domain.com'
password = 'password123'
client_id = application id from azure ad
client_secret = keys from application on azure ad
tenant = directory id from azure ad`
Using this token i can fetch the list of all sites in my sharepoint account.
Below is the endpoint i call to fetch the sites with the bearer token:
https://graph.microsoft.com/v1.0/sites?search=*
But when I just do the client authentication using token generated using below endpoint Iam not able to access the sites list.
login.microsoftonline.com/tenant_id/oauth2/v2.0/token
`grant_type : client_credentials
clientid : client_id
clientsecrte : client_secret
scope : https://graph.microsoft.com`
It does not return all of the sites.
Is there a way of getting all sites list with just client authentication.
Or can i get a token for user authentication without user password.
Here is the token decoded that i am using:
{
"aud": "https://graph.microsoft.com",
"iss": "https://sts.windows.net/586145ec-0428-4da6-8061-fb114257ab70/",
"iat": 1528949458,
"nbf": 1528949458,
"exp": 1528953358,
"aio": "Y2dgYLh*************xAAA=",
"app_displayname": "App Name",
"appid": "504ddb16-2899-48be-be57-**********",
"appidacr": "1",
"idp": "https://sts.windows.net/586145ec-0428-4da6-8061-fb114257ab70/",
"oid": "afcf166f-24c2-49f1-b285-b672d0413c50",
"roles": [
"Sites.Read.All",
"Sites.ReadWrite.All",
"Sites.Manage.All",
"Sites.FullControl.All",
],
"sub": "afcf166f-24c2-49f1-b285-b672d0413c50",
"tid": "586145ec-0428-4da6-8061-fb114257ab70",
"uti": "hwYd8FZCH0KruWGRFiIHAA",
"ver": "1.0"
}
I get other permissions also but these are site related in Microsoft Graph api
Cause:
The successful one is using ROPC flow and it can get delegated permissions onbehlaf of the user. But the failed one is using client_credentials flow which get application permissions and cannot onbehlf of the user.
Updated Answer
Solution:(Before you do this test, ensure you have SPO license in your tenant)
Try to add Sites.Read.All Application permission in your registrated AAD Application and do admin consent for it before you getting token.
If you're using AAD v1 endpoint, you can do admin consent by clicking Grant permissions button.If you're using v2 endpoint, please input this kind of URL in your internet browser to do admin grant:
https://login.microsoftonline.com/{yourtenant}/adminconsent?client_id={the applicationid of your client}&state=123&redirect_uri={the redirect uri of your app}
and sign in with Global admin account and accept this permission.
In my test lab, I used v2 endpoint.Here is the token I got via Postman:
Here is decoded token in https://jwt.ms , we can decoded the token to ensure it has the permissions we want.
Then I use this token in the head to call Microsoft Graph API and succeeded:
For more detials about Site permission for Microsoft Graph, please refer to this documentation.
Please let me know if this helps!

Azure Active Directory RBAC Not Returning Roles in Bearer Token

I'm using the Azure AD Basic tier with an ASP.NET Core API, I've followed the RBAC sample. I've set up an application with roles in my manifest like so:
appRoles": [
{
"allowedMemberTypes": [ "User" ],
"displayName": "Read Device",
"id": "b2e6f6c2-c3d5-4721-ad49-0eea255ccf45",
"isEnabled": true,
"description": "Can read a device.",
"value": "read_device"
},
...
]
I've setup my API to use the UseJwtBearerAuthentication middleware like so:
application.UseJwtBearerAuthentication(
new JwtBearerOptions()
{
AuthenticationScheme = "Azure Active Directory",
Authority = options.Authority,
Audience = options.ClientId,
TokenValidationParameters = new TokenValidationParameters()
{
RoleClaimType = "roles",
ValidateIssuer = false
}
})
I've given my user the above 'Read Device' role:
I'm using Swagger UI to make the call to get the auth token. It calls the following URL:
https://login.microsoftonline.com/[Tenant].onmicrosoft.com/oauth2/authorize?
response_type=token
&redirect_uri=http%3A%2F%2Flocalhost%3A5100%2Fswagger%2Fo2c.html
&realm=-
&client_id=[Client ID]
&scope=http%3A%2F%2Fschemas.microsoft.com%2Fws%2F2008%2F06%2Fidentity%2Fclaims%2Frole
&state=oauth2
&resource=[Client ID]
I suspected that I am not passing the correct values to the scope parameter, so I have tried asking for every scope I can think of:
&scope=openid
%20email
%20profile
%20offline_access
%20user_impersonation
%20roles
%20http%3A%2F%2Fschemas.microsoft.com%2Fws%2F2008%2F06%2Fidentity%2Fclaims%2Frole
%20read_device
If I set "groupMembershipClaims": "All" in my manifest I can see group claims but I want roles instead. I'm able to login to call my API, however I never get any roles back in my JWT token, so I'm unable check the users role. What am I doing wrong?
It turns out I needed to request an id_token instead of a token. An id_token contains extra claims/scopes/resources about the user. I also needed to provide a nonce parameter containing a new random GUID on every request. Thus, I ended up with the following URL:
https://login.microsoftonline.com/[Tenant].onmicrosoft.com/oauth2/authorize?
response_type=id_token
&client_id=[Client ID]
&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2F
&nonce=9ac5ad8d-df44-48e6-9bd6-e72743b3625c
If you are want to enable the role be assigned to users or groups(allowedMemberTypes=User) :
If you want to perform authorization using role claims , you could
follow the steps in this code sample , you could find the roles
claim is in the id_token .
If you want to make a client app to call your web api , when user
sign in ,app could check the access rules based on the role
claim,
you could use delegate flow(OAuth Authorization Code Grant,Implicit
Grant Flow..),roles claim is in the access_token ;
If you want to specify the role be assigned to client applications(allowedMemberTypes=Application), you could use OAuth Client Credential Flow ,appRoles of resource app/api that are assigned to the client app, and you will find the roles claim in the access_token ,check the detail steps from here.
Please click here for more details .
In my case I had mistakenly configured the App Registration to emit Security Groups as roles claims, thus overwriting the App Roles from the manifest. Removing the optional groups claim and logging back in correctly emitted the App Roles names in the roles claim of the id_token.

Delegating Azure Active Directory Roles When Calling API from SPA

I have a single page application (SPA) and an API. Both are secured using Azure Active Directory using role based access control (RBAC). I can login and viewview my SPA using ADAL. I can also login, call my API and see the role claims I have given myeself.
I want to call the API from the SPA. I have added the API delegated permissions to the SPA. I have also hit the 'Grant Permissions' button so I don't see a consent screen.
The problem is when the SPA calls the API, no role claims appear, so the API always returns a 403 Forbidden response. How can I solve this?
Update
This is the manifest for my API:
{
"appId": "[API Client ID]",
"appRoles": [
{
"allowedMemberTypes": [
"User"
],
"displayName": "Read Device",
"id": "b2e6f6c2-c3d5-4721-ad49-0eea255ccf45",
"isEnabled": true,
"description": "Can read a device.",
"value": "Device.Read.All"
}
],
...
}
In my SPA, I'm using ADAL and adal-angular like so:
var azureActiveDirectory = {
'instance': 'https://login.microsoftonline.com/',
'tenant': '[My Tenant ID]',
'clientId': '[SPA Client ID]',
'redirectUri': 'http://localhost:8080/',
'endpoints': {
'http://localhost:5000': '[API Client ID]'
}
adalAuthenticationServiceProvider.init(azureActiveDirectory, $httpProvider);
Apparently, roles in nested groups are not transitive i.e. If I am a member of Group 2, I do not have the Role granted to Group 1, even though Group 2 is a member of Group 2:
Group 1
Has a Role from Application 1
Has a Member called Group 2
This is absolutely unbelievable that such a feature has not been implemented. I've raised a suggestion on UserVoice. Please upvote the suggestion.
you should create the appRole in your API app, when your spa call API, it will get access token with the role in api app that the login user belongs to. so to make sure you create role and verify role in api app, not spa app.

Resources