fireholster
fireholster

Reputation: 640

Azure AD Authentication : Multiple Scopes Issue

I am likely expecting or doing something that is not correct. Need some help in getting back to the right path.

Simple Usecase - How to configure a client so it can request a token with all the right scopes? currently I am running it via postman but actual client is going to be a react app using msal.

Setup:

    {
      "AzureAd": {
        "Instance": "https://login.microsoftonline.com/",
        "Audience":"api//someguid"
        "ClientId": "my-client-id",
        "TenantId": "my-tenant-id"     
      },
      "Graph": {
        "BaseUrl": "https://graph.microsoft.com/v1.0",
        "Scopes": "user.read,email"
      }
    }
    builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApi(Configuration, Configuration.GetSection("AzureAd"))
        .EnableTokenAcquisitionToCallDownstreamApi()
        .AddMicrosoftGraph(Configuration.GetSection("Graph"))
        .AddInMemoryTokenCaches();
 [Authorize]
 public class AbcController: Controller
 {
     private readonly GraphServiceClient _graphClient;     

     public AbcController(GraphServiceClient graphClient)
     {
         _graphClient = graphClient;
     }

     [HttpGet("get-me")]
     public async Task<ActionResult> GetSomeDetails()
     {
         var user = await _graphClient.Me.Request().GetAsync();
         return null;
     }

I run this via postman with Auth Code flow with PKCE, Here are the issues

  1. When I set the Scope as : api//someguid/testscope

    • Call gets authenticated and the Token is acquired correctly in postman
    • The API get-me get authorized correctly
    • But the call _graphClient.Me.Request().GetAsync() throws throws a 500 error
    • Also, a direct call to https://graph.microsoft.com/v1.0/me in postman using the token gives insufficient privilege error
  2. When I set the scope as : api//someguid/testscope https://graph.microsoft.com/email

    • Call gets authenticated But the acquire token fails with incorrect scope
  3. When I set the scope as : https://graph.microsoft.com/email https://graph.microsoft.com/user.read

    • Call gets authenticated and the acquire token is acquired
    • Direct call to https://graph.microsoft.com/v1.0/me works as expected
    • But now my API does not get Authorized and gives 401

Can someone suggest what am i missing in my setup or if i am doing something crazy wrong?

All i am looking to do is get my API authorized, and get the email address pulled from graph in the API, without explicitly re-acquiring the token or specifying my client secret in the API to build the graph client.

This was taken as an input to try and build my poc https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-web-api-call-api-call-api?tabs=aspnetcore

Upvotes: 2

Views: 4645

Answers (1)

Sridevi
Sridevi

Reputation: 22452

Note that, one token can only be issued to one audience. You cannot acquire access token for multiple audience (Ex: custom API and MS Graph) in single call.

In your scenario, you need to make two separate requests for acquiring access tokens i.e., one for your API and other for Microsoft Graph.

I tried to reproduce the same in my environment via Postman and got below results

I registered one Azure AD application and added same API permissions as below:

enter image description here

Now I exposed one API named testscope same as you like below:

enter image description here

Make sure to select Single-page application while adding Redirect URIs to your application like below:

enter image description here

I acquired token successfully using Auth code flow with PKCE from Postman like below:

POST  https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token
client_id:<appID>
grant_type:authorization_code
scope: api://someguid/testscope
code:code
redirect_uri: https://jwt.ms
code_verifier:S256

enter image description here

The above token won't work for calling Microsoft Graph /me endpoint and works only to authorize API based on its audience.

To check the audience of above token, decode it in jwt.ms like below:

enter image description here

To call /me endpoint for mail, you need to acquire token again with Microsoft graph scope without configuring client secret like below:

POST  https://login.microsoftonline.com/<tenantID>/oauth2/v2.0/token
client_id:<appID>
grant_type:authorization_code
scope: https://graph.microsoft.com/.default
code:code
redirect_uri: https://jwt.ms
code_verifier:S256

enter image description here

The above token won't work for authorizing API whereas you can call Microsoft Graph based on its audience.

To check the audience of above token, decode it in jwt.ms like below:

enter image description here

When I call /me endpoint using above token, I got the results successfully with mail like below:

enter image description here

References:

Azure AD Oauth2 implicit grant multiple scopes by juunas

reactjs - azure msal-brower with nextJs: passing only one scope to the API

Upvotes: 3

Related Questions