Migrating from ADAL to MSAL

Photo by Tadas Sar on Unsplash

UPD: Oct, 13th. Version 1.1.3 fixed a lot of issues, most important one is that now tokens’ cache is working properly and requesting token from MSAL is no longer leads to redundant calls.

Recently on my project we’ve started migration from ADAL JS to MSAL JS. If you are not aware, MSAL JS team released a first stable version in May, so it was a good time to try migration.

Unfortunately, despite the fact that MSAL is officially released it still lacks good documentations and contains several important bugs. In this article I’ll try to cover some important bugs we’ve faced at the time of writing and give some guidance how to properly use new library.

Let’s start from the configuration of the MSAL:

let config = {
auth: {
clientId: '{{application ID, GUID}}',
authority: 'https://login.microsoftonline.com/{{tenant ID}}.onmicrosoft.com',
redirectUri: '{{registed return URL}}',
navigateToLoginRequestUrl: false
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: true
system: {
loadFrameTimeout: {{time in milliseconds}}
let context = new Msal.UserAgentApplication(config);
view raw msal-config.js hosted with ❤ by GitHub
MSAL Configuration

Here I want to mention only three parameters, because all other parameters are well-described in official documentation:

  • redirectUri – you’ll need to fulfill this parameter in case you need to return to page which is different from the page you are currently on. In general this is often the case, because it’s unlikely that you want to register all pages where you’re using access tokens. As a result you’ll have one page in your application which is used as a return URL and all pages will return to it and from this page will return to original page, for example by storing original URL in localStorage/sessionStorage;
  • navigateToLoginRequestUrl – if you are developing an SPA application using some framework (Angular, Vue.js or React with extensions) it’s very likely you already have a custom routing system with internal navigation. Disabling this option will tell MSAL that you don’t need help in navigating back to proper page and you’ll implement it yourself. And you probably should do it, because navigation using location.href assignment will cause a full page reload and it’s unlikely the desired behavior;
  • loadFrameTimeout – this is also a quite important parameter, because if users have slow internet connection or your servers could in some cases experience a high load your users will suffer from issues with silent token acquisition process. This parameter will help you to fix this issue.

Now let’s take a look a the code snippet where we will try to acquire token silently if user already authenticated and authenticate if he’s not:

return new Promise((resolve) => {
let scopes = {
// To acquire Sharepoint token
scopes: ['https://{{tenant ID}}.sharepoint.com/.default', 'openid', 'profile'],
// To acquire Graph API token
scopes: ['.default', 'openid', 'profile'],
loginHint: null
context.handleRedirectCallback((error, response) => {
if (error) {
// TODO: e.g. track into analytics
} else if (window.parent === window) {
if (response.tokenType === 'access_token' && response.accessToken) {
if (!context.isCallback(window.location.hash)) {
if (context.getAccount()) {
context.acquireTokenSilent(scopes).then((response) => {
if (response.accessToken) {
}).catch((_error) => {
} else {
view raw msal-login.js hosted with ❤ by GitHub
Token acquisition

Here I want to discuss several important things:

  • By default, you are receiving access tokens which can be used only with Graph API, but if you need to call, for example, Sharepoint API you can easily achieve this by requesting domain scope: ‘ https://{{tenant ID}}.sharepoint.com/.default ‘;
  • I personally suggest to add ‘openid’ and ‘profile’ to the list of scopes, because in the version I’m currently using (MSAL v.1.0.2) two iframes will be created otherwise. One iframe#msalRenewFrame.default openid profile and one iframe#msalRenewFrame.default. I believe this is a bug and probably will be fixed in the future releases.

Basically that’s all I wanted share regarding MSAL basic configuration and usage. However I’d recommend to enable logging which is available out of the box in MSAL. You can read here how to do it.

At the end I’ll list couple of bugs (information updated for the MSAL v1.1.3 ):

  • Several concurrent calls of acquireTokenSilent can lead to flooding of local storage, because it looks like there is a bug in checking “In Progress” status;
  • FIXED: Currently acquireTokenSilent always updates the iframe and tries to retrieve a new token ignoring the fact that previous token is still fresh.

As a result of these bugs you probably need to implement your own wrapper which validates the last received token and based on this information calls the acquireTokenSilent or return the previous token directly.

If you still have any questions feel free to contact me in the comments below.

Also if you find this material useful don’t forget to subscribe and share it with your colleagues! Thanks!

3 thoughts on “Migrating from ADAL to MSAL

  1. Thanks for sharing your feedback! I work on the msal js team and am sharing this with the team so we can continue to improve the library. Please reach out on github with any more feedback you may have. We are committed to shipping incremental improvement often.

    Liked by 2 people

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s