This post shows how to create a Node.js application using Node.js, Bash for Windows, Visual Studio Code, and Azure Active Directory. The final solution is available at https://github.com/kaevans/node-aad.
I went to an article, Node.js web app sign-in and sign-out with Azure AD, followed the steps, and it didn’t work. I went to GitHub and cloned a repository, https://github.com/AzureAD/passport-azure-ad, and it didn’t work. After wasting a really long time trying to figure it out, I discovered that those two resources (as of today’s date) use Node.js version 4.x, which is the current Long Term Support (LTS) version of Node. Following the instructions below, I ended up with Node version 7.4.0. The versions are not backwards-compatible between major releases, which explains why I couldn’t get things to work.
You could get things to work by using a Node version manager. A popular one is “n” which lets you interactively select which version of Node you are using. The rest of this post assumes Node version 7.4.0.
This post is going to look scary long. It’s actually not that bad, I am just verbose. The completed solution is available at https://github.com/kaevans/node-aad.
I am not using a Linux desktop, just using it as a server. I used vi in Linux enough to realize I prefer the productivity of menus and a mouse, so I have a Windows 10 desktop running Visual Studio Code. However, I fell in love with Bash, so I enabled the Bash for Windows feature. This lets me use the Bash shell for things like Node.js (including npm) and Express web server. Once I code and test locally, I deploy the code to a Linux VM running in Azure. If you are using a Mac, you can use the Bash shell natively and you can still install Visual Studio Code.
Create an Azure AD Application
Go to the Azure portal, under Azure Active Directory / App Registrations and add a new registration. Create it as a Web app / API with a sign-on URL of https://localhost.
Once created, go to the properties of your new app registration. The App ID URI will have a GUID, you may wish to change that GUID to the name of your app (completely an optional step, but one that I prefer).
In this screen shot, item #1 is the application ID, also known as the client ID. The App ID URI is also known as the Audience URI. We’ll use those values in our configuration at the end of the post.
If your application will access other APIs, you will need a key. To do that, go to the Keys setting of your app registration and add a new key.
Copy this value (you won’t be able to retrieve it later). This key is also known as the client secret.
Install Node.js and Express Generator
I am going to assume that you already have Bash on Windows enabled (more details here), and you have Visual Studio Code installed. Open a command line and just type “bash” to start the Bash shell. This enables you to install Node.js using a package manager in Bash. Since Bash on Windows uses Ubuntu, you need to choose the Ubuntu directions for installing Node.js.
curl -sL https://deb.nodesource.com/setup_7.x | sudo -E bash - sudo apt-get install -y nodejs sudo apt-get install -y build-essential
Now that we have Node.js, we can use the Node Package Manager (NPM) to install dependencies similar to how we’ve used NuGet for packages in Visual Studio. Let’s install the Express Generator that lets us quickly scaffold Node.js applications that use Express. We use the “-g” switch to make this a global dependency.
npm install express-generator -g
So, where to keep our project? Bash for Windows creates a mounted file system to access your Windows files, so wherever we keep them in Windows is accessible via Bash as well. As an example, I created a directory “Source” under my user profile.
Just for completeness sake, I am showing the same directory using the old CMD shell in Windows to prove you can easily access those files in Windows.
Now close the CMD shell, we will only use the Bash shell during this post!
Create the Application
Now that we have a folder to keep our new application, we need to install some libraries. Change directory to the Source directory and then use the Express Generator to scaffold the application. In the Bash shell:
Open Visual Studio Code and then open the node-aad folder that was just created.
If you go to the debug menu in VS Code and hit Start, the application will fail with an error “Exception occured Error: Cannot find module ‘express’”. Yes, “occurred” is misspelled, but the more important thing to note is that the packages.json file contains a list of dependencies that haven’t been downloaded yet, kind of like NuGet package refresh. This allows you to check your project into source control without all the dependency binaries. To download the binaries, we go back to the Bash shell and change directory to our project’s folder.
The output shows all the binaries that were downloaded.
To test the application, in the Bash shell try to following:
Now switch to a browser and go to http://localhost:3000. You will see your application.
Watch the Bash shell window to see the requests.
Hit Ctrl+C to stop the server. We now have a working Node.js web application. Let’s secure it with Azure AD.
Update Your Application to Use Azure AD with Passport
No, I don’t mean Passport as in the precursor to Microsoft Accounts (formerly Live accounts, formerly Hotmail accounts, formerly Passport accounts), I mean Passport the authentication middleware for Node.js. Passport makes it easy to use different strategies for authenticating to services such as Facebook, Twitter, and more. We will use the passport-azure-ad package that provides an OpenId Connect strategy for authenticating to Azure AD. Go to the Bash shell and run the following. This will install the packages method-override, express-session, passport, and passport-azure-ad, and the “—save” switch will update the package.js file to include the references.
npm install --save method-override express-session passport passport-azure-ad
Go check package.js and you will see that it has been updated.
We are using OAuth, which means we are passing a bearer token in an HTTP header, which means using HTTPS is mandatory. In fact, this is one of the things that didn’t work when I tried the directions for Node.js 4.x using Node.js 7.4.0… the sample I linked to in the opening paragraph allowed you to use HTTP but that doesn’t work with Node 7.4.0. Creating an HTTPS server using Express is really simple. Go to the Bash shell and create the signing key, certificate request, and certificate, then delete the request file.
openssl genrsa -out key.pem openssl req -new -key key.pem -out csr.pem openssl x509 -req -days 9999 -in csr.pem -signkey key.pem -out cert.pem rm csr.pem
Now update app.js. At the top of the file, add the require statements for https and fs.
At the bottom of the file, just before the last line of code, add the following:
To test, go to the Bash shell and use “npm start” to start the application, then open a browser to “https://localhost” to see your application now listens to port 443 instead of 3000. You may get an unhandled error:
If that is the case, then try running it using the sudo command:
sudo npm start app.js
Note: this is using a self-signed certificate and is not secure for production use.
Using Passport for Authentication
In Visual Studio Code, add a new file called config.js.
Notice that we do not put hard-coded values for variable items in this file, and we certainly never ever never ever put secrets (like client ID and client secret) into code.
Add the following to the list of “require” statements in app.js.
Beneath the require statements, add the following:
Next, we create the app object and tell it what middleware to inject.
Finally we add our routes.
Making It Readable
We now turn to making it readable so someone can actually use our application. Let’s update the controller for the Index view to pass both the user and the title to the view.
Now let’s update the view.
Notice the Jade file starts with “extends layout”. We can use this like a master page in ASP.NET (or a layout in ASP.NET MVC). Update the layout.jade file.
In our app.js file, there’s a route for /account. We need a view for that as well. Add a new “account.jade” file in the views folder.
The last thing we need to do it to add a little styling so the navigation is easier to read. Update style.css in the public/stylesheets folder to include padding.
Check It In
We want to commit the code to git, but we don’t need to commit all those dependencies. In the root of the project, create a file “.gitignore” and add the following:
This will prevent checking in any files in the node_modules folder, the .vscode folder (will be created in the next step), the certificates for the HTTPS server, or any log files.
In VS Code, you can now go to the Git tool and initialize the repository and check your changes in.
Test It Out
Our config.js file uses a lot of environment variables. We need a way to pass those into our program when debugging locally. One way is to use the Bash command:
sudo CLIENT_ID=YOUR CLIENT_ID CLIENT_SECRET=YOUR_APP_SECRET_KEY REDIRECT_URL=https://localhost/auth/openid/return node app.js
Replace the placeholders for client ID and app secret with the values from your Azure AD app.
Another way to do this is to set the environment information within VS Code. Go to the debugging tab, then click Settings.
That will create a .vscode/launch.json file that makes it easy for you to configure the environment variables necessary for debugging your application without creating a script or actually setting those variables for your environment. Replace with the values for your Azure AD application.
In VS Code, you can now click the Debug button to start debugging, giving you access to breakpoints, step-through, watch locals, etc.
Now open a browser in InPrivate (Internet Explorer) or Incognito (Chrome) to ignore existing cookies. Navigate to https://localhost and you will see your new application!
Click Log In and see that you are prompted to log into Azure AD.
Once you log in, the UI changes to indicate you are logged in.
Click Account to see details about the claims in your token.
Git the Source
If you weren’t able to follow along or just want to download the source, the completed solution is available at https://github.com/kaevans/node-aad. At a command line:
git clone https://github.com/kaevans/node-aad.git
To run the application, you will need to complete a few steps:
- The node modules are not checked into source, but are referenced in the package.json file. Just change directory to the project root and use the command “npm install” to download all of the dependencies so that you can debug locally. Checking these into source would bloat your repository needlessly.
- The certificates are not checked into source (these are secrets). Follow the directions above for using openssl to generate the certificates. Do not check these into source!
- The .vscode/launch.json is not checked into source (it has secrets in it). Follow the directions above for creating/modifying the .vscode/launch.json file. Do not check this into source!
For More Information
https://github.com/kaevans/node-aad – Completed source code
Node.js web app sign-in and sign-out with Azure AD – instructions to build a Node.js 4.x application, some changes required for a 7.x application.
https://github.com/AzureAD/passport-azure-ad – Completed sample for a Node.js 4.x application, some changes required for a 7.x application.