I have an App Registration in Entra with permissions granted to call another App Registration from same Entra. When I use client secret to get a bearer token via http for grant_type=client_credentials
- the token works fine.
Now I want to use DefaultAzureCredential inside an Azure App Service to get the same token without client secret. When I use DefaultAzureCredential.GetTokenAsync
- I get a token with no Roles and oid
set to the system-assigned identity of my App Service. I tried Passing DefaultAzureCredentialOptions.ManagedIdentityClientId
set to Client Id of my App Registration, but then I get code 400, indicating that my App Service does not have permissions to use the identity from App Registration.
Am I missing some configuration to link my App Service to my App Registration?
Update I've recreated the setup, here is what it looks like:
App Registrations:
Http call gets me the token with roles:
POST https://login.microsoftonline.com/62765715-2081-4050-bdc7-8c2e178d7424/oauth2/v2.0/token HTTP/2.0
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=1009eb01-33c0-4bf9-ad54-726d50fb18b5
&client_secret=zlr8*************************************
&scope=api:%2F%2F442b3378-34c6-421f-8912-d3f18a004d1c%2F.default
{
"aud": "api://442b3378-34c6-421f-8912-d3f18a004d1c",
"iss": "https://sts.windows.net/62765715-2081-4050-bdc7-8c2e178d7424/",
"iat": 1735085790,
"nbf": 1735085790,
"exp": 1735089690,
"aio": "k2BgYDh97Ul1oVFTEfumuQ1zVuQdBQA=",
"appid": "1009eb01-33c0-4bf9-ad54-726d50fb18b5",
"appidacr": "1",
"idp": "https://sts.windows.net/62765715-2081-4050-bdc7-8c2e178d7424/",
"oid": "d5760fed-eaf1-4e6e-aed2-a2b65ac0a030",
"rh": "1.AREAFVd2YoEgUEC9x4wuF410JHgzK0TGNB9CiRLT8YoATRwXAQARAA.",
"roles": [
"Vehicles.Read",
"Vehicles.Write"
],
"sub": "d5760fed-eaf1-4e6e-aed2-a2b65ac0a030",
"tid": "62765715-2081-4050-bdc7-8c2e178d7424",
"uti": "4gbiMCOLlk2bJqHrffsaAA",
"ver": "1.0"
}
Is there any way in Azure to give it access to the above token (or similar, as long as the audience and roles are there) without using client secret? Preferably via DefaultAzureCredential?
Update2:
I have tried the following
New-AzureADServiceAppRoleAssignment `
-ObjectId e67aa4a7-e487-47b9-8d27-78cf30888f61 `
-PrincipalId e67aa4a7-e487-47b9-8d27-78cf30888f61 `
-Id f39a570e-6309-496f-b81a-0de5a9e07e2e `
-ResourceId 3d73b9d4-b4b6-4741-b1f6-22a7fa6453d2
Output:
New-AzureADServiceAppRoleAssignment: Error occurred while executing NewServicePrincipalAppRoleAssignment
Code: Request_BadRequest
Message: Permission being assigned was not found on application
RequestId: 8cf83ecf-c707-4621-adfe-52397837d690
DateTimeStamp: Fri, 27 Dec 2024 21:10:58 GMT
Details: PropertyName - None, PropertyErrorCode - InvalidUpdate
HttpStatusCode: BadRequest
HttpStatusDescription: Bad Request
HttpResponseStatus: Completed
Update3:
Update 4
I assigned backend-api permissions back to itself, reran above New-AzureADServiceAppRoleAssignment
command, still the same result.
Update 5: Success! The command worked with following ids:
Following code returns token with roles
AccessToken token1 =
await new DefaultAzureCredential()
.GetTokenAsync(new TokenRequestContext(
["api://442b3378-34c6-421f-8912-d3f18a004d1c/"]));
"roles": [
"Vehicles.Read"
],
Note that: To call another Microsoft Entra Application and generate access token using system managed identity you need to assign the permissions to the managed identity.
Assuming you want to generate token using managed identity in web app service and include roles in it.
I created a Microsoft Entra ID application and created app role:
Assign this app role to system managed identity:
Connect-AzureAD
New-AzureADServiceAppRoleAssignment -ObjectId MIObjectID -Id AppRoleID -PrincipalId MIObjectID -ResourceId MicrosoftEntraServicrPrincipalObjID
You can also make use of latest Microsoft Graph PowerShell module.
When you check the managed identity in the Enterprise application blade, app role is assigned:
Now I used the below code to generate access token using Azure web app system identity:
using Azure.Core;
using Azure.Identity;
namespace WebApplication1.Models
{
public class TokenService
{
public async Task<string> GetAccessTokenAsync()
{
string resource = "api://ClientIDOfEntra/";
var credential = new DefaultAzureCredential();
var tokenRequestContext = new TokenRequestContext(new[] { resource });
AccessToken token = await credential.GetTokenAsync(tokenRequestContext);
Console.WriteLine($"Access Token: {token.Token}");
return token.Token;
}
}
}
When published to App service access token generated successfully:
Decode the token app roles are displayed:
The appid claim includes the Application ID of system managed identity.
By using the above token, you can call the other application successfully and make sure to use the same scope you are using of client credential flow.