ADAL.js - Obtaining Microsoft Graph Access Token w

2019-02-27 11:38发布

问题:

I am attempting to integrate Azure AD login and Graph API into my angular2 website.

I have successfully implemented an ADAL login and redirect, built around a useful blog post here

From this I retrieved an id_token parameter that my adalservice can access. Currently this is acheived through a simple context.login() and catching the token in the redirect.

When I use this token to try and access Microsoft Graph, I receive an InvalidAuthenticationToken response stating Access Token validation failure.

I'm new to this stuff, so it could be that my call is intrinsically wrong, or that I lack certain permissions in AD, or my app reg lacks permissions. I've seen that I potentially need to request an access token with sufficient scope, yet I can find any examples of this.

Has anyone used this adalService library to obtain tokens for use with Graph API?

回答1:

I found a solution to my problem.

I was using the wrong token. I had to acquire a token specifically for Graph API. This meant I would have to first log in and then call this.context.acquireToken() like below:

this.context.acquireToken("https://graph.microsoft.com", function (error, id_token) {

    if (error || !id_token) {
        console.log('ADAL error occurred: ' + error);
    } 
    else {
            this.graphAccessToken = id_token;
            //Call graph API
    }
    }.bind(this)
);

It seems like it's essential that this process have 2 calls. Maybe someone can shed some light on whether I can immediately obtain a token with scope for the Graph API on login. Perhaps by setting required permissions for the app in Azure AD.



回答2:

Just to have a clarity for all, updating the end to end solution here again.

In case you do not have the base starter code, refer to this link Adal-JS Tutorial. This post only concerns with the customization involved.

Step 1: Configure the AdalService

(only new code is shown, other methods remain as it is)

export class AdalService {

    public get graphAccessToken() {
        return  sessionStorage[new AppConstants().User_Graph_Token];
    }

    public retrieveTokenForGraphAPI() {
        this.context.acquireToken('https://graph.microsoft.com', function (error, graph_token) {

            if (error || !graph_token) {
                console.log('ADAL error occurred: ' + error);
            } else {
                // Store token in sessionStorage
                sessionStorage[new AppConstants().User_Graph_Token] = graph_token;
                return;
            }
        }.bind(this)
        );
    }
 }

The code should have existing handlers for id_token callback and corresponding configuration in the routing. If not, please refer to link above for the initial code.

Now the requirement is retrieve the access_token once the id_token is retrieved. The access_token has additional field for "puid" which describes identifier for claims. This will be the step 2.

Step 2: Update LoginComponent

ngOnInit() {
    if (!this.adalService.isAuthenticated) {
      console.log('LoginComponent::Attempting login via adalService');
      this.adalService.login();
    } else {
      if (this.adalService.accessTokenForGraph == null) {
        console.log('LoginComponent::Login valid, attempting graph token retrieval');
        this.adalService.retrieveTokenForGraphAPI();
      }
   }

Now the token is retrieved and stored for later use.

Step 3: Update Routing for 'access_token' callback

Similar to the 'id_token' callback, we need to add additional callback route for the access_token. The callback components will remain same. Their code is as described in the main link. Note that *access_token" endpoint is MS provided, hence be careful not to change the name.

  { path: 'access_token', component:  OAuthCallbackComponent, canActivate: [OAuthCallbackHandler] },
  { path: 'id_token', component: OAuthCallbackComponent, canActivate: [OAuthCallbackHandler] }

Step 4: Use the token wherever required

const bearer = this.adalService.graphAccessToken();