1
votes

This page describes how to add Application app roles to an application in Azure Active Directory using the manifest.

Code sample from the page:

"appId": "8763f1c4-f988-489c-a51e-158e9ef97d6a",
"appRoles": [
    {
      "allowedMemberTypes": [
        "Application"
      ],
      "displayName": "ConsumerApps",
      "id": "47fbb575-859a-4941-89c9-0f7a6c30beac",
      "isEnabled": true,
      "description": "Consumer apps have access to the consumer data.",
      "value": "Consumer"
    }
  ],
"availableToOtherTenants": false,

When calling an an Azure Function from an application authenticated using the client_credentials grant type, how do you enforce it to belong to the application role?

I've Googled but been unable to find clear documentation that explains how this authorization is done for Azure Functions.


My Test Function App

I've created a simple "hello <name>" Azure Function from within the Azure Portal which I call from Postman.

#r "Microsoft.Azure.WebJobs.Extensions.Http"
#r "Newtonsoft.Json"

using System.Net;
using System.Security.Claims;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;


public static IActionResult Run(HttpRequest req,  ILogger log, ClaimsPrincipal claimsPrincipal)
{
    var name = req.Query["name"];
    log.LogInformation($"C# HTTP trigger function processed a request: {name}");

    var cp = new {
        Identity = new {
            claimsPrincipal.Identity.AuthenticationType,
            claimsPrincipal.Identity.IsAuthenticated,
            claimsPrincipal.Identity.Name
        },
        Claims = claimsPrincipal.Claims.Select(claim => new
        {
            claim.Type,
            claim.Value
        })
    };
    log.LogInformation($"ClaimsPrincipal ({claimsPrincipal.GetType().FullName}): {JsonConvert.SerializeObject(cp, Formatting.Indented)}");

    return (IActionResult)new OkObjectResult($"Hello, {name}");
}

Firstly I authenticate using https://login.microsoftonline.com/<Tenant ID>/oauth2/v2.0/token and capture the access_token.

Request Body Example:

grant_type:client_credentials
client_id:<Application ID>
client_secret:<Client Secret>
scope:https://<Function-app-name>.azurewebsites.net/.default

Example Result:

{
    "token_type": "Bearer",
    "expires_in": 3599,
    "ext_expires_in": 3599,
    "access_token": "eyJ0eXAi......"
}

Then I call my Azure Function using https://<function-app-name>.azurewebsites.net/api/hello?name=World and a header containing Authorization: Bearer eyJ0eXAi.......

Authentication works fine, as does calling the Azure Function. However, I can add a new Application via App registrations in the Azure Portal, authenticate and then call the Azure Function freely. I don't know how to restrict access the the Azure Function to only Applications that have a specific application role.

1
Please show how did you call the function.Joy Wang
@JoyWang I've added it into the question.John Mills

1 Answers

2
votes

I don't know how to restrict access the Azure Function to only Applications that have a specific application role.

If you just want the App who has the ConsumerApps permission access your function, follow the steps below.

1.Navigate to the AD App of your function in the Azure Active Directory in the portal -> click the Managed application in local directory -> Properties -> set the User assignment required to Yes.

enter image description here

enter image description here

2.Then you could try to get the token with your AD App again, you will find the app could not get the token successfully, you will get the error like below, because your client app does not have the ConsumerApps permission.

enter image description here

3.To access the function successfully, we just need to add the Application permission for the Client AD App you used.

Navigate to the client AD App in the portal -> API permissions -> Add a permission -> click APIs my organization uses -> search for your function AD App name -> click the app -> Application permissions -> add the Consumer permission -> click the Grant admin consent for xxx button.

enter image description here

enter image description here

enter image description here

Wait for a while, then try to get the token again, it works fine.

enter image description here

Use the token to call function, also works.

enter image description here