I have an Azure Function secured by the Azure Active Directory.
I can successfully call the application from the browser provided that I'm logged.
Now, what I want to do is to call that function from an application that doesn't use the username and password in order to authenticate but rather a trusted application client id and client secret.
I tried to use for that purpose the same application (say ApplicationA) that has been created for securing the function application. I went to the App Registrations, found the application created by configuring the Azure Active Directory authentication provider in the Function App Authentication/Authorization settings (ApplicationA) and I set a Client Secret for it.
Now I'm able to obtain a token using said application Client Id and the generated secret.
But when I'm trying to call the Function using that token I'm getting 401 error.
I tried the same operation with a newly created application in App Registration (say ApplicationB) but with the same result, I'm still getting 401.
I even tried to add a Reader Role for that application in Subscriptions but then again - 401 when calling Function with the token.
I know, there's something like API permissions in the application settings. So I tried to add the permission for ApplicationB to ApplicationA user_impersonation but it also doesn't work so that's not the way.
So how do I grant the permission for a registered Application for which I'm able to acquire a token so I can use this token to call the Function?
EDIT:
I'm using the following code for token acquisition:
using Microsoft.Identity.Client;
string ClientId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
string ClientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
string TenantId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
string Authority = $"https://login.microsoftonline.com/{TenantId}";
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(ClientId)
.WithClientSecret(ClientSecret)
.WithAuthority(new Uri(Authority))
.Build();
AuthenticationResult result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
string token = result.AccessToken;
You need to register at least one application permission (appRole with allowed member type Application) via the manifest into the functions app registration. Then you can assign the application permission to the client app.
You can see my article for more info on defining permissions: https://joonasw.net/view/defining-permissions-and-roles-in-aad
Example app permission in manifest:
"appRoles": [
{
"allowedMemberTypes": [
"Application"
],
"description": "Allow the application to read all things as itself.",
"displayName": "Read all things",
"id": "32028ccd-3212-4f39-3212-beabd6787d81",
"isEnabled": true,
"lang": null,
"origin": "Application",
"value": "Things.Read.All"
}
],
You need to define the id yourself, it just needs to be a GUID.
The value
is what is sent in the tokens in the roles
claim.
Description and display name are just for how the permissions shows up in the UI.
I added the app role and granted permission to it but then I'm still getting 401. Strange thing that when I decoded the token it doesn't contain scp ot roles claim.
Hmm, if the role is not there then the permission was not granted correctly or the token is being acquired wrong. Can you add your token acquiring code at least to the question?
I edited the question.
Ok, it was the scopes. I used
"https://myfunctionappname.azurewebsites.net/.default"
instead of"https://graph.microsoft.com/.default"
and now it works. Thanks.Ah, yeah it needs to match the ID URI defined in the app registration (or you can use
api-client-id-here/.default
)