Wrong audience for JWT using ADAL.js

570 Views Asked by At

I'm using the adal-angular library (but not with Angular) in my SPA to try to acquire an access token that I can use to call the SharePoint APIs (https://<my-tenant>.sharepoint.com/_api/).

I've registered an application in Azure AD and enabled the implicit flow in the manifest, and I'm now running my SPA locally, which is why there's a localhost redirect URI. The code below is being executed on startup:

const context = new AuthenticationContext({
    clientId: '<my-client-id>',
    redirectUri: 'http://localhost:3000/signin',
    popUp: true,
    loginResource: 'https://<my-tenant>.sharepoint.com',
    callback: () => window.location.reload()
});

const user = context.getCachedUser();
if (!user) {
    context.login();
} else {
    context.acquireToken('https://<my-tenant>.sharepoint.com', (error, token) => {
        console.log(error, token);
    });
}

I'm already logged into the SharePoint site, so with this config everything happens automatically and I see a JWT access token logged to the console. However, when I inspect the token, I see that the audience is <my-client-id>. When making a call to https://<my-tenant>.sharepoint.com/_api/v1.0/me using the access token, I then get a 401 response with the following error message:

{"error_description": "Exception of type 'Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException' was thrown."}

I'm pretty sure this all boils down to me not understanding the OAuth2 flow properly, but... how can I acquire a token that SharePoint can actually be used with SharePoint? Am I thinking about this the wrong way? It kinda defeats the purpose if the token retrieved by my app can only be used to authenticate against my own app.

1

There are 1 best solutions below

0
On

Getting an access token to SharePoint is well described here:

OneDrive for Business authentication and sign in

You should consider first getting a token to the Discovery Endpoint:

Using an access token received for resource https://api.office.com/discovery/ you can make a request to the discovery API to learn which services are available

If the call is successful, the response body contains JSON data with information about the services available for the user and your app.

{
  "@odata.context": "https:\/\/api.office.com\/discovery\/v1.0\/me\/$metadata#allServices",
  "value": [
    {
      "@odata.type": "#Microsoft.DiscoveryServices.ServiceInfo",
      "capability": "MyFiles",
      "serviceApiVersion": "v2.0",
      "serviceEndpointUri": "https:\/\/contoso-my.sharepoint.com\/_api\/v2.0",
      "serviceResourceId": "https:\/\/contoso-my.sharepoint.com\/"
    }
  ]
}

There you should get your valid Resource ID... but the issue here may just be that you did not include a forwardslash (/) at the end of the Resource URL in your sample code.