I haven’t touch Node.js much lately, however, back while I have been working with it, I was always curious, how to leverage both Passport.js with Azure AD and using ADAL for Node.js together in order to have ADAL handle the tokens, refreshes, cache etc. In the end, I have come up with a solution which I am going to share below.
Notice, that we save the refreshToken into the user’s profile property as initialRefreshToken. This is quite important, because next, we are going to use it with ADAL for Node.js in order to exchange it for an actual access token. So next step is to initialize ADAL for Node.js:
Note that we are initializing it with a MemoryCache so that our credentials persist. The biggest issue with ADAL is that it doesn’t cache tokens retreived by refresh token by default (maybe an idea for a pull request?), so we have to do a little workaround to force it into the cache.
So how does this piece of code work? First, we have to include the token-request.js in order to be able to access the token cache easily. Then, we take a look if this is our initial sign in – we have to exchange the refresh token for an access token and cache it or not. In case of having to create the entry in the cache, we have to create a TokenRequest object, initialize it and then call which does all the heavylifting. In the sample, I also slightly modify the initial token response to identify the user by their objectId within the Azure AD rather than using their userPrincipalName (note that if you are making a multi-tenant application and sharing the token cache, using objectIds or userPrincipalName + tenantId as an identifier is required for the cache to work properly). Once stored, every next request for the token goes through the cache (notice passing in the user.oid as user identifier – see explanation above).
The major difference between this approach and using ADAL with OpenID Connect Middleware in ASP.NET Core is that in case of Node.js the authorization code is redeemed for access and refresh tokens directly by the Passport.js (equivalent of OIDC middleware in ASP.NET Core) and then the refresh token is used to initialize ADAL where in ASP.NET Core, the authorization code redemption is already handled by ADAL. Either way, this is quite an obscure solution (yeah, accessing properties meant to be private is never good but it makes it work fine).