1
votes

I am using the Implicit Grant workflow in Angular with the microsoft-adal-angular6 library authenticate the user in my app and then obtain a token for access to the Microsoft Graph.

The authentication portion is working.

And I can obtain a token from AAD via the library. However, when I attempt to query graph via the client (and via http) I receive an invalid audience error message (the http query is slightly less helpful with just a 401).

statusCode: 401 
   code: "InvalidAuthenticationToken" 
   message: "Access token validation failure. Invalid audience." 
   requestId: "157c3867-3ac6-41e7-aa79-fbd6cc466c4f" 
   date: Tue Mar 03 2020 23:18:44 GMT-0700 (Mountain Standard Time) {} 
   body: "{"code":"InvalidAuthenticationToken","message":"Access token validation failure. Invalid audience.","innerError":{"request-id":"157c3867-3ac6-41e7-aa79-fbd6cc466c4f","date":"2020-03-03T23:18:44"}}"
    __proto__: Object`

Here I setup my ADAL service:

`adalConfig = {
  tenant: AppConfig.settings.aad.tenant,
  clientId: AppConfig.settings.aad.clientId,
  redirectUri: AppConfig.settings.aad.redirectUri,
  endpoints: AppConfig.settings.aad.apiEndpoint,
  navigateToLoginRequestUrl: false,
  cacheLocation: AppConfig.settings.aad.cacheLocation
};`

json:

"aad": {
    "requireAuth": true,
    "apiEndpoint": {
        "https://localhost:44371": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
        "https://graph.microsoft.com/v1.0/": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"  
    },
    "clientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "tenant": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "resource": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "redirectUri": "http://localhost:4200/frameredirect/",
    "cacheLocation": "sessionStorage",
    "vospEndpoint": "https://localhost:44371",
    "graphEndpoint": "https://graph.microsoft.com/v1.0/",
    "vospAADGroup": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "clientSecret": "",
    "scopes": [
        "GroupMember.Read.All"
    ]
}}`

My call to get my token for the graph endpoint:

private async getAccessToken(): Promise<string> {
const resource =  this.adalService.GetResourceForEndpoint(AppConfig.settings.aad.graphEndpoint);
let result = await this.adalService.acquireToken(resource).toPromise().then((token:string) => {return token;}).catch(error => {return error;});

if(result) console.log(result);
return result;

And here is my code to call init the graph client and call the api:

let graphClient = await Client.init({
  authProvider: async(done) => {
    let token = await this.getAccessToken()
    .catch((reason) => {
      done(reason,null);
    });

    if(token) {
      done(null, token);
    } else {
      done("Could not get an access token", null);
    }
  }
});

let aadGroupId = AppConfig.settings.aad.vospAADGroup;
let loggedInUser = this.adalService.LoggedInUserEmail;

let graphUser2 = await graphClient.api("/users/" + loggedInUser + "/memberOf?").filter("id eq '" + aadGroupId + "'").get().catch(error => {return error});

The slot on Azure has been configure to grant the following Graph API scopes:

Microsoft Graph (8) 
    Directory.AccessAsUser.all      Delegated       Access directory as the signed in user
    Directory.Read.all              Application     Read directory data
    Group.Read.All                  Delegated       Read all groups
    Group.Read.all                  Application     Read all groups
    User.Read                       Delegated       Sign in and read user profile
    User.Read.All                   Delegated       Read all users' full profiles
    User.Read.All                   Application     Read all users' full profiles
    User.ReadBasic.All              Delegated       Read all users' basic profiles

My calls to the graph being denied due token audience. How do I specify the correct audience and scope for the token using the microsoft-adal-angular6 wrapper for ADAL.js?

2
The graphEndpoint is not correct. It should be https://graph.microsoft.com.Tony Ju
Thanks. I had started with that URL and then added the "/v1.0/" later to see if that made a difference. It didn't. I tried again with just "graph.microsoft.com", again the token is rejected by graph.ben.kansas
@TonyJu, thanks. see my comment above.ben.kansas
You can use jwt.ms to decode your token, what is the value of aud? docs.microsoft.com/en-us/azure/active-directory/develop/…Tony Ju
What is the value of const resource = this.adalService.GetResourceForEndpoint(AppConfig.settings.aad.graphEndpoint); lTony Ju

2 Answers

0
votes

Access token validation failure. Invalid audience

This error usually occurs due to the wrong audience. We can use https://jwt.ms/ to check the audience in the token. If you want to call Microsoft Graph API, the resource should be https://graph.microsoft.com.

Reference:

https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens#payload-claims

1
votes

Using https://jwt.ms (thanks @TonyJu) I found that the token audience was referencing my app's clientId. So in my JSON I changed my Endpoint node reference to "https://graph.microsoft.com": "https://graph.microsoft.com"

This allowed my http interceptor to get the "resource" for the endpoint from the session storage and acquire a token for the correct audience.

This seems like it could have used some clarification in the microsoft-adal-angular6 documentation. But maybe it is just common-sense.

@NgModule({
imports: [
    MsAdalAngular6Module.forRoot({
      tenant: '<YOUR TENANT>',<-------------------------------- ADD
      clientId: '<YOUR CLIENT / APP ID>',<--------------------- ADD
      redirectUri: window.location.origin,
      endpoints: { <------------------------------------------- ADD
        "https://localhost/Api/": "xxx-bae6-4760-b434-xxx",
        ---
        ---
      },
      navigateToLoginRequestUrl: false,
      cacheLocation: '<localStorage / sessionStorage>', <------ ADD
    }),
    ---
    ---
  ],
  ---
  ---
})