Adding ADAL-JS and other globally referenced libraries to client-side applications

Sometimes external libraries use global variables, which don’t play nicely with System.js. This article talks you through how to export packages as globals to use throughout your application.

WARNING: This was produced with pre-release material and is subject to change!!

So you’ve added some external packages, you’ll followed the steps correctly here, but you’re getting errors? Frustrating I know, I feel your pain and felt it for several hours as I was working out what was going on!

There are some important things at play here, and in this article I’m going to show you how to properly add the Azure AD AngularJS library, but the theory works the same for other libraries (I also experienced this problem with moment.js).


Adding adal-angular

Follow the steps here, the name of the node.js package is ‘adal-angular’. All being well, you should have reference to the CDN.

Try to use adal-angular, ERRORS!

I’ve added import 'adal'; and import 'adal-angular';, they’re loading in dev tools. Now I want to actually use ADAL-JS. For those that are familar with ADAL, the boilerplate code below should be familiar

Loading ADAL-JS!

When you try to run it, you’ll find you get an error, as shown below.

Failed to instantiate module demoApp due to: ReferenceError: AuthenticationContext is not defined at init (http://localhost:4321/node_modules/adal-angular/lib/adal-angular.js:63:33) at eval (http://localhost:4321/dist/intranet-application.bundle.js:89:48) at Object.invoke (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:41:295) at d (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:39:234) at eval (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:39:358) at n (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:7:355) at g (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:39:135) at fb (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:43:164) at c (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:20:449) at Object.Ac (https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js:21:259

Cannot find AuthenticationContext?! Well, a bit of digging shows that AuthenticationContext is a global JavaScript variable in adal.js, but System.JS has done a great job of wrapping our library to prevent namespace clashes.

All well and good, but I really need AuthenticationContext!


Fixing the Issue

So, a crash source in System.js led me to the documentation. The great news is, there’s config in System.JS exactly for this scenario. It’s called the meta object, and is described more here. So, I made some changes to my .\config\bundle.json file, and it now looked like this…

{
  "entries": [
    {
      "entry": "./lib/intranetApplication/IntranetApplicationApplication.js",
      "outputPath": "dist/intranet-application.bundle.js",
      "configPath": "dist/intranet-application.config.js",
      "useWebpack": true,
      "exclude": [
        "@ms/sp-client-platform",
        "adal",
        "adal-angular",
        "angular",
        "react",
        "react-dom"
      ]
    }
  ],
  "config": {
    "meta": {
      "node_modules/angular/angular.js": { "format": "global", "exports": "angular" },
      "node_modules/adal-angular/lib/adal.js": {
        "format": "global",
        "exports": "AuthenticationContext"
      },
      "node_modules/adal-angular/lib/adal-angular.js": {
        "format": "global",
        "deps": [ "angular", "adal" ]
      }
    },
    "paths": {
      "adal": "node_modules/adal-angular/lib/adal.js",
      "adal-angular": "node_modules/adal-angular/lib/adal-angular.js",
      "angular": "https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js",
      "@ms/sp-client-platform": "dist/sp-client-platform.js",
      "react-dom": "dist/react-dom.js",
      "react": "dist/react.js"
    }
  },
  "baseUrl": "http://localhost:4321"
}

The important thing here, is the exporting of adal.js to be a global var called AuthenticationContext.


Still not working!

After adding the correct config into .\config\bundle.json, it still wasn’t playing ball - but there were greater forces at work here!

In short, and for the timebeing, a change needs to be made to one of the gulp tasks in .\node_modules\@ms\ms-core-build\lib\tasks\bundle.js. Look for a comment in the script which reads // Should we create a config.js?. Here, the guys at Microsoft are building the system.js config file, but at the moment - this only supports baseUrl and path objects.

Below, you’ll see my config, post change. I’ve added meta: options.config.meta

Adding Meta

Now, run your gulp command to build the bundle again, hey presto! ADAL-JS is now playing nicely….go forth and create awesome SPA.


Conclusion

In conclusion, the issues here were two-fold. Firstly, you need to know how System.js behaves - in that it will not, by default export any global variables.

Secondly, the @ms/sharepoint bundle gulp task, at time of writing doesn’t handle meta objects in the system.js builder. I have filed a bug with the product time, so hopefully they’ll fix it for when it’s released.