Search code examples
oauth-2.0azure-active-directoryazure-functionsaccess-tokenazure-managed-identity

Azure AD Access token of Client Application does not contain Roles Claims


I have 2 Azure AD applications say Client-App and Server-App in Azure AD App registrations.

Server AD Application:

  • Registered a new App in Azure AD.
  • Set up App Roles with name "Search.Address" which is custom role.

Client AD Application:

  • Registered a new App in Azure AD.
  • API Permissions: Added the role "Search.Address" created in server-app registration is exposed as an Application Permissions in client app.
  • Granted Admin access successfully.

I have client Function App created with .NET stack and enabled system managed identity which is associated with Client-App. Client function app runs code to get an access token using ManagedIdentityCredential.

Token is successfully created but role "Search.Address" is missing.

I tried Client-App exposing as an API. But in no vain.

Does Managed identity have any permission to talk to server? How I can assign that using approleassignment ?

 public static class Function1
    {
        [FunctionName("Function1")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;
            string responseMessage = string.Empty;
            try
            {

               var credential = new ManagedIdentityCredential();
               var accessToken = await credential.GetTokenAsync(new TokenRequestContext(scopes: new string[] { "SERVERAPP_ClientID/.default" }) { });
               
                responseMessage = string.IsNullOrEmpty(name)
                    ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
                    : $"Hello, {name}. Your Token: {accessToken.Token}";
            }
            catch (Exception ex)
            {

                log.LogError(ex.Message+ex.InnerException.Message);
            }           

            return new OkObjectResult(responseMessage);
        }
    }

Reference:

https://anoopt.medium.com/few-ways-of-obtaining-access-token-in-azure-application-to-application-authentication-40a9473a2dde


Solution

  • You need to assign the application permission/app role to the Managed Identity service principal. You can't do this through the Portal at the moment, you'll need PowerShell to do that:

    Connect-AzureAD
    New-AzureADServiceAppRoleAssignment -ObjectId 1606ffaf-7293-4c5b-b971-41ae9122bcfb -Id 32028ccd-3212-4f39-3212-beabd6787d81 -PrincipalId 1606ffaf-7293-4c5b-b971-41ae9122bcfb -ResourceId c3ccaf5a-47d6-4f11-9925-45ec0d833dec
    

    Note that this is for the older AzureAD module. There is also a similar cmdlet for the newer Microsoft.Graph module.

    For the AzureAD cmdlet, the ids you need are:

    • ObjectId and PrincipalId: Managed Identity Service Principal object ID
    • Id: id of the app role/app permission
    • ResourceId: object ID of the API Service Principal

    Running this command is the same thing as the admin consent for application permissions.

    Article I wrote on this: https://joonasw.net/view/calling-your-apis-with-aad-msi-using-app-permissions