Extending SharePoint with ADAL and the Microsoft Graph API – Part 2 (The Authorization)

This entry is part 2 of 3 in the series Extending SharePoint with ADAL and the Microsoft Graph API


In Part 1 of this series I covered all the setup needed to start your Microsoft Graph API (MSGraphAPI) client side widget. In Part 2, we’re going to dive into the many ways to use adal.js and its counterpart adal-angular.js. I’ve included the same resources I included in Part 1, under the section for ADAL you’ll find a lot of references to Cloud Identity blog by Vittorio Bertocci a Principal Program Manager at Microsoft who has blogged extensively on the library, explaining in depth the technical workings of it. I encourage you to read those posts I’ve included below to get a complete understanding of the library. Also, included in the references is a post about utilizing ADAL in the SharePoint Framework (SPFx). As is, ADAL was never meant to be used as part of a widget architecture as ADAL isn’t a singleton, so if you have multiple web parts on your page all referencing ADAL you’re going to have issues. The post “Call the MSGraphAPI using OAuth from your web part” gives you an extension that will help isolate ADAL so that you can utilize it as part of a more strongly developed widget pattern. Since my demo is just that, and since my solution will be the only one running on the page that uses the ADAL library I’m not going to address those modifications here. But, I encourage you do so if that is part of your use case.

The ADAL library for JavaScript

Finally, we get to the part where we talk about writing some code. ADAL stands for “Active Directory Authentication Library”. Based on the client you’re using and which authentication endpoint you’re using, there are a multitude of different examples and SDK’s available as you can see on the MSGraphAPI, Getting Started page. Because we’re going to write client side code (aka JavaScript, either transpiled from Typescript or native) and access via Implicit Flow to the MSGraphAPI, we’ll use the adal.js library. It comes in two parts, adal.js and adal-angular.js. If you’re going to use the AngularJS framework, you’ll want both pieces. If not, you can just include adal.js, but there will be more work to do to authenticate and get a token. You can find the source in the ADAL GitHub repo.

User Authentication

One of the things that bothered me was the idea that the user would have to “log in” manually every time the ADAL library would need to authenticate them. In my mind, I envisioned a pop-up that would prompt them for credentials. In the scenario where you’re running this code on your on-premises server in a hybrid scenario, and haven’t set up federated sign-in to your O365 tenant that would be valid, however, in the most likely scenarios I can envision the code would be running in your SharePoint site in your O365 tenant… therefore asking the user to log in again would be annoying at best. Well, sure enough that’s not what happens, the library uses a hidden iframe on the page to make the call to get the user authenticated, since they are technically already authenticated to O365 this is just a matter of “confirming” it for lack of a better term. So, the page does flicker but otherwise this is unnoticeable to the user.

*Note: Thanks to Wictor Wilen for bringing up the issue with using adal.js in IE with a trusted site. Please check out this issue, from the GitHub repo.

ADAL Config

A big part of utilizing the adal.js libraries is to get all the configuration settings correct. I want to highlight some of the configuration properties that I reviewed and what was useful. You’ll see how to put it together and pass it to adal.init() later. The definitions here come straight from the documentation in the adal.js file itself.

  • tenant: string – Your target tenant.
  • clientID: string – Client ID assigned to your app by Azure Active Directory.
  • endpoints: array – Collection of {Endpoint-ResourceId} used for automatically attaching tokens in webApi calls.
  • popUp: boolean – Set this to true to enable login in a popup window instead of a full redirect.Defaults to false.
  • cacheLocation: string – Sets browser storage to either ‘localStorage’ or sessionStorage’. Defaults to ‘sessionStorage’.
  • anonymousEndpoints: array – Array of keywords or URI’s. ADAL will not attach a token to outgoing requests that have these keywords or uri. Defaults to ‘null’.

Using ADAL.js with No Framework

The most tedious coding scenario with ADAL is utilizing it without the AngularJS add-on. I found this blog article on how to do it, but unfortunately for me although it worked initially, when it came time to renew the token the ADAL library was throwing errors. After quite a bit of time on it, reviewing the adal-angular.js file and various other blog posts, I managed to work out a scenario that seems to work reliably.

For simplicity’s sake, I’m showing an entire html file including the JavaScript in one code snippet. I commented the code extensively but in a nutshell, we’ll do the following:

  • 1. For simplicity code is executed on page load using jQuery’s document.ready function. The goal of that bit of code is to determine if AAD is doing a callback and if so, let the adal.js library handle it.
    • a. If not a callback, check if the user is authenticated, if not, call the ADAL login function
    • b. If not a callback, and user is authenticated, then execute any initialization code we want to run.
  • 2. When a call needs to be made against the MSGraphAPI, e.g., the sympraxis.getGraphData function, first get the token by calling the sympraxis.getAuthToken function (which returns a promise since it may need to make an asynchronous call to AAD, and if so we need to wait until that completes.
    • a. If the token is in the cache, return it by resolving he promise.
    • b. If the token is not in the cache, acquire a new one and then resolve the promise with the new token.
  • 3. Make the REST call to the MSGraphAPI and include the token in the header.

Using Angular 1.x framework with ngRoute

If you’re a fan of the AngularJS framework, then the adal-angular.js library does all the heavy lifting for you. It extends both AngularJS’s $http provider and the ngRoute directive. It adds the bearer token that was retrieved using the adal.js library to the $httpProvider in your REST calls for you. In addition, it accepts an additional configuration setting on each of your routes which determines whether AD login should be required or not. If set to true, when you navigate to the particular route, the adal-angular.js library makes sure the user is logged in, and then also makes sure the $httpProvider appends the token. If it’s not set – or set to false – then the token will not be appended to the $http calls. Also, note here that I’ve utilized html5Mode on the $locationProvider. I did that because of a recommendation in the documentation that indicated that having it on fixes issues with endless callbacks. I too found this to be an issue, but only when bypassing ngRoute. For safety, I put it in both examples, but I’ll leave it to you to test whether it’s necessary in your solution or not.

So, at this point I’m sure you can see that this scenario is significantly simplified from our “No Framework” version above. Other than the changes to the .config, no other changes are necessary. You just go about your business making $http calls and the adal-angular.js library does the rest .

Angular 1.5+ using Components

Angular version 1.5 introduced a new concept called “Components” which was viewed widely as a superior architectural strategy for building Angular applications. So much so a very similar schema was adopted for Angular 2. With components, you generally do not use ngRoute. Further, with many widget solutions, routing is overkill. So, we need to consider another strategy for managing when the $http provider should include the token and, because ngRoute was making sure the user is authenticated for us (as I noted in the previous section), we’re going to need to handle that as well.

For authentication, we’ll reuse the concepts we discussed in the “No Framework” section by making sure on page load we trap the callback and allow the ADAL.js library to handle it. Because this is a component there is the handy $onInit() function. That will work perfectly for our needs.

Now to handle server calls that are not meant to have the token amended… enter, anonymousEndpoints. In this scenario, our configuration would not include the $routeProvider. Instead we would include relative URLs we want to ignore when making $http calls. In this case I included two anonymous endpoints, one for the location of my component templates, and the other is the SharePoint REST APIs.

I specified relative URLs in the anonymousEndpoints array we want to ignore because if you review the code that decides if the $http call should append the bearer token to it, you can see that if the URL includes http or https it will try to find a matching endpoint. If it does not find one, it will utilize the token that was used for the login resource. For example, if you try to make a call against the SharePoint REST API and the URL you use includes https://mytenant.sharepoint.com it’s going to append the bearer token and subsequently fail. Also, note that I only included the root of the URLs I want ADAL to ignore. That is because the test for anonymous endpoint uses a “contains” check.

The controller for the component we create would then define an $onInit() function that would handle login for those components that need it. There are certainly other ways architecturally to handle this, but I wanted to keep things simple so I wouldn’t lose the point in the elegance of the architecture. At a baseline this is what it would look like. We’re going to expand on this, and explain the SP_EP url in the _CONFIG in Part 3.


Now we’ve completed Part 2, you should have everything you need to go off and start making calls to the MSGraphAPI. But, if you’re interested, Part 3 will bring all of this together and show you how to create an Excel spreadsheet from scratch, add it to a SharePoint document library, and then manipulate it with the Excel API’s. Please stay tuned…


OAuth Flows

Andrew Connell – Looking at the Different OAuth2 Flows Supported in AzureAD for Office 365 APIs
Microsoft – Integrating applications with Azure Active Directory
Matt Velloso – Troubleshooting common Azure Active Directory Errors
Microsoft – Should I use the v2.0 endpoint?


GitHub – Azure Active Directory Library for JS
Cloud Identity – Introducing ADAL JS v1
Cloud Identity – ADAL JavaScript and AngularJS – Deep Dive
Cloud Identity – Getting Acquainted with AuthenticationResult
Cloud Identity – Getting Acquainted with ADAL’s Token Cache
Microsoft – Call the Microsoft Graph API using OAuth from your web part

Microsoft Graph API

Microsoft – Microsoft Graph permission scopes
Microsoft – App authentication with Microsoft Graph

Series Navigation<< Extending SharePoint with ADAL and the Microsoft Graph API – Part 1 (The Setup)Extending SharePoint with ADAL and the Microsoft Graph API – Part 3 (The Execution) >>

Published by

Julie Turner, MVP

Julie has been building software on primarily the Microsoft platform for over 20 years. With a degree in Electrical Engineering specializing in microprocessor system design from Worcester Polytechnic Institute she came at software initially from a very low level but quickly realized a love and aptitude for developing rich user experiences and solutions. She worked her way up through internal IT ranks reaching a Director of IT position before realizing more impact could be made in consulting and really focused in on the SharePoint platform in 2007. Since then her focus has been on the SharePoint platform, Office 365, Azure, and client side development. She's the co-author of the Widget Wrangler JavaScript library and continues to try and help innovate SharePoint and Office 365 solutions for her clients. She is a 2017 recipient of the Microsoft MVP award for Office Servers and Services.

16 thoughts on “Extending SharePoint with ADAL and the Microsoft Graph API – Part 2 (The Authorization)”

  1. One thing to bear in mind is that ADAL.js does not work properly with Internet Explorer and SharePoint Online, if SharePoint Online is in your trusted zone – which you normally have for SSO to work.

    1. After going back and forth with Wictor on a private Slack I think I finally get the Internet Explorer zones issue. Basically, every site that uses ADAL,js has to be in the same zone as login.microsoftonline.com. This is a problem for SharePoint users because tenantname.sharepoint.com and tenantname-my.sharepoint.com are often in the Local Intranet or Trusted Sites zone. So, if you want to access the Graph API from a SharePoint web part you need to put login.microsoftonline.com in the same zone as the sharepoint.com URLs. Now, what if you also use abc.azurewebsites.net and xyz.azurewebsites.net which both use ADAL.js? You’re going to have to put those sites in the same zone as login.microsoftonline.com too or they won’t work properly. As time goes on and more and more sites use ADAL.js you end up having a huge list of sites in whatever zone login.microsoftonline.com is in.

  2. Hi Julie,

    Thanks a lot for your post. Sadly It doesn’t work out the way I want it to.
    I’ve created an complete empty aspx page with your code from “Using ADAL.js with No Framework” in it. I’ve added the html, header and body tag so that it is a ‘real’ page; and obviously I’ve changed

    sympraxis.clientId = ”;
    sympraxis.tenant = ”;

    This page is uploaded to the Library SitePages in my Site Collection. Sadly when go to the page the first time; I see some kind of token beïng obtained when I look in the address-bar of Chrome; but other nothing happens.

    When I hit F5 I get the valid data and I see the displayname and message (and other data) beïng returned.

    Any idea why I always need to hit F5, when the application doesn’t have a correct token yet? Obviously I’m signed in into SharePoint online and I want this solution to work “single-sign-on”…

    Best Regards,


    1. Hi Paul, Without seeing your code this is fairly hard to answer. However, based on your description is sounds like you’re not handling the callback. The code I have in the section you mention includes a jQuery “document.ready” function that performs that action. Given you’re seeing the URL change to include the token then I’d say it must be working in general but somehow you’re not getting ADAL to handle the callback… did you include that section and have you tried debugging to see what’s happening?

      1. Julie… Thanks for your answer…

        Yep – I copied your complete code; so the jQyery document.ready is included as well.

        First time I get on the page isCallback is obviously false;
        No user can be retreived from cache thus sympraxis.authContext.login(); runs

        After the callback isCallback is true; and !getLoginError() is true, so it comes into

        window.location.hash has a value of something like….


        after the function sympraxis.authContext.handleWindowCallback(window.location.hash) runs the original url of the page (without the token and with the “#”-sign remains)

        After that – the debugger stops……….. and nothing happens. – no information is displayed in the message div as wel……

        When hitting F5 the user can be retreived from cache and thus it runs the getGraphData function correctly…….

        Hope this helps you.. Would be great to receive some feedback…..

        P.S. I’m using Chrome – but other browsers have similar results….

  3. The section where you say “the original url of the page (without the token and with the “#”-sign remains” implies that the page has again reloaded (at least that’s what it does for me) so you should have entered the document ready function again… I assume you have a breakpoint on what is line 87 in my example and it’s not getting back there after handleWindowCallback is called?

  4. Julie – Thanks sooo much for helping this far…

    I have a breakpoint on line 87 and it IS getting back there… (So it enters the document.Ready twice in total)….

    The first time it isn’t a callback and therefore goes into the else satement (line 91); hasn’t got a user from cache and tries to login the user (line 95)…

    It then returns on the page is indeed a callback and therefor goes to the handleWindowCallback (line 90) – After that function it stops and doesn’t enter line 92 anymore…

    However when I hit F5 – it tries the same thing but has a user from cache and it enters the else statement on (line 96)…

    Hopes that makes sense….

    I just think the handleWindowCallback doesn’t work the way it should, but I’m really not sure what’s wrong here……

    1. The handleWindowCallback should refresh the page a third time… so a total of 3 screen refreshs… first to get the token, second to handle token, third to execute your function (at least until it’s cached). That’s why I asked you if you have a breakpoint on that line to see if the handleWindowCallback was indeed refreshing the page a third time, in that case it should fall through the code to the point of calling your init function. If it is not in fact refreshing a third time then yes, I am stumped because I have always seen that behave properly. What version of ADAL.js are you using?

      1. Julie – Thanks!

        I’ve switched to version 1.0.13 (was using the newest 1.0.14) and now I see three pageloads and could build my solution further… It works the way I want it to work now!

        Thanks for your help; without you I guess I wouldn’t have solved it anytime soon….


  5. Hello Julie,

    I am trying to use Adal.js for authentication in a mobile app (cordova)
    But I receive the following return after authentication:

    Do you have a solution?

    Sign In
    Sorry, but we’re having trouble signing you in.
    We received a bad request.

    Additional technical information:
    Correlation ID: e414ef65-16fe-4702-bbfd-686f0b26dda3
    Timestamp: 2017-07-10 09:51:27Z
    AADSTS50011: Reply address ‘file:///var/mobile/Containers/Data/Application/55CDBFD1-8F17-470E-A8D1-263C400F6B4F/Library/Caches/launch/1499680266/57bac3b37e2193c2198b2691/www/index.html’ specified by the request is not a valid URL. Allowed schemes: ‘http,https’

    Kind regards,

    1. Hi Mario, First I should say I don’t do any kind of native mobile programming so this is not my area of expertise but my opinion would be that you’re using the wrong ADAL library, there is a version of ADAL specifically for Cordova https://github.com/AzureAD/azure-activedirectory-library-for-cordova which I think will get you a lot farther. The ADAL.js library is meant specifically for building web based solutions, specifically SPAs. Hope that helps.

      1. Hello Julie,

        I have already investigated the “https://github.com/AzureAD/azure-activedirectory-library-for-cordova” but cannot get it to work.
        If you know anyone in your network who can help me I would be very much interested.

        Thanks and Kind regards,

Leave a Reply