Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ADAL.js - Obtaining Microsoft Graph Access Token with id_token

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.

API call with obtained "access_token"

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?

like image 938
JonnyKnottsvill Avatar asked Jun 28 '17 12:06

JonnyKnottsvill


People also ask

What is Adal token?

The Azure AD authentication Library (ADAL) enables client application developers to easily authenticate users to cloud or on-premises Active Directory (AD), and then obtain access tokens for securing API calls.

What is the difference between Msal and Adal?

ADAL.NET used AuthenticationContext as the representation of your connection to the Security Token Service (STS) or authorization server, through an Authority. MSAL.NET is designed around client applications.


2 Answers

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.

like image 59
JonnyKnottsvill Avatar answered Jan 01 '23 00:01

JonnyKnottsvill


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();
like image 33
NitinSingh Avatar answered Jan 01 '23 02:01

NitinSingh