1

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?

ben.kansas
  • 71
  • 7
  • The graphEndpoint is not correct. It should be `https://graph.microsoft.com`. – Tony Ju Mar 04 '20 at 02:51
  • 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 "https://graph.microsoft.com", again the token is rejected by graph. – ben.kansas Mar 04 '20 at 14:16
  • @TonyJu, thanks. see my comment above. – ben.kansas Mar 04 '20 at 14:23
  • You can use https://jwt.ms/ to decode your token, what is the value of `aud`? https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens#payload-claims – Tony Ju Mar 06 '20 at 02:00
  • What is the value of `const resource = this.adalService.GetResourceForEndpoint(AppConfig.settings.aad.graphEndpoint); l` – Tony Ju Mar 06 '20 at 02:01
  • Any update for this issue? – Tony Ju Mar 10 '20 at 01:18
  • @TonyJu, see my answer below. If you want to write up another I'll mark your's as the answer. I wouldn't have made it there without the suggestion to use http://jwt.ms. – ben.kansas Mar 11 '20 at 22:40

2 Answers2

1

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
    }),
    ---
    ---
  ],
  ---
  ---
})
ben.kansas
  • 71
  • 7
0

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://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens#payload-claims

Tony Ju
  • 14,891
  • 3
  • 17
  • 31