How to authorize Azure AD access_token generated with client secret in a .net API?

67 views Asked by At

I created an application in Azure to control authentication for an application I am developing. I developed a small program to generate the access_token using the client secret and I would like to validate this token in my api using [Authorize] in the controllers. The problem is that when I send the token the application is returning a 401 Unauthorized code. I added the application information (clientId and TenantID) in appsettings and added authentication in the file in program.cs.

Some time ago I made this same implementation, but in this case I called the API via the Angular frontend. At the time I used the MSAL library in Angular to login and retrieve the idToken and send it in requests. This application with the frontend works perfectly, but in this case generating the token with the client secret and sending the access_token does not work.

Method used to generate the access_token:

public static async Task LoginWithSecret()
{
    var authority = $"https://login.microsoftonline.com/{ tenantId }";
    var scope = "https://graph.microsoft.com/.default"

    var app = ConfidentialClientApplicationBuilder
               .Create(clientId)
               .WithClientSecret(clientSecret)
               .WithAuthority(new Uri(authority))
               .Build();

    var result = await app.AcquireTokenForClient(new[] { scope }).ExecuteAsync();

    var accessToken = result.AccessToken;
    Console.WriteLine($"{ accessToken }");

}

API appsettings file:

  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "*********************************",
    "ClientId": "*********************************"
  },

program.cs class:

IConfiguration configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddMicrosoftIdentityWebApi(configuration);
(...)

Controller:

[HttpPost]
[Authorize]
public async Task<ActionResult<bool>> MyMethod(ViewModel model) {
 (...)
}

I've tried several examples, but none of them worked. As I said, I have already implemented something similar using an API and a frontend in Angular, but in this case I used the idToken that is returned by the MSAL library when the user login to the frontend. In this example I'm trying, I don't have a login screen and that's why I'm using clientsecret to obtain this token.

Please, could anyone tell me if I need to do any more configuration in the API?

Thanks

1

There are 1 answers

0
Hugo Barona On

When you use the scope https://graph.microsoft.com/.default, you are requesting a token to use while making requests to Graph API.

If that's what you want, then you need to ensure to configure the API permissions on the app registration in Entra ID.

So, edit your app registration and configure the application permissions to set the permissions you need to use Graph API.

If you need your AppX to call other AppY/ApiY you have, and authorize the request, then the best way would be to have an app registration (security principal) for your AppY, and then on AppX, when you are requesting the token, you need to specify in the scope the client id of AppY, so in this case you are requesting a token to access the AppY exclusively, and you are limiting the scope of your token.

Given that you are using a daemon app to call your API, follows the link describing the scenario:

https://learn.microsoft.com/en-us/entra/identity-platform/scenario-daemon-overview

More info on app registration permissions on the link below:

https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-configure-app-access-web-apis?source=recommendations#add-permissions-to-access-your-web-api