Quickstart: Secure a Web API with Azure Active Directory

Applies to:
  • Azure AD v1.0 endpoint

In this quickstart, you'll learn how to secure a Restify API endpoint with Passport using the passport-azure-ad module to handle communication with Azure Active Directory (Azure AD).

The scope of this quickstart covers the concerns regarding securing API endpoints. The concerns of signing in and retaining authentication tokens are not implemented here and are the responsibility of a client application. For details surrounding a client implementation, review Node.js web app sign-in and sign-out with Azure AD.

The full code sample associated with this article is available on GitHub.


To get started, complete these prerequisites.

Create the sample project

The server application requires a few package dependencies to support Restify and Passport as well as account information that is passed to Azure AD.

To begin, add the following code into a file named package.json:

  "name": "active-directory-webapi-nodejs",
  "version": "0.0.1",
  "scripts": {
    "start": "node app.js"
  "dependencies": {
    "passport": "0.4.0",
    "passport-azure-ad": "4.0.0",
    "restify": "7.7.0"

Once package.json is created, run npm install in your command prompt to install the package dependencies.

Configure the project to use Active Directory

To get started configuring the application, there are a few account-specific values you can obtain from the Azure CLI. The easiest way to get started with the CLI is to use the Azure Cloud Shell.

Open Azure Cloud Shell

Azure Cloud Shell is an interactive shell environment hosted in Azure and used through your browser. Azure Cloud Shell allows you to use either bash or PowerShell shells to run a variety of tools to work with Azure services. Azure Cloud Shell comes pre-installed with the commands to allow you to run the content of this article without having to install anything on your local environment.

To run any code contained in this article on Azure Cloud Shell, open a Cloud Shell session, use the Copy button on a code block to copy the code, and paste it into the Cloud Shell session with Ctrl+Shift+V on Windows and Linux, or Cmd+Shift+V on macOS. Pasted text is not automatically executed, so press Enter to run code.

You can launch Azure Cloud Shell with:

Option Example/Link
Select Try It in the upper-right corner of a code block. This doesn't automatically copy text to Cloud Shell. Example of Try It for Azure Cloud Shell
Open Azure Cloud Shell in your browser.
Select the Cloud Shell button on the menu in the upper-right corner of the Azure portal. Cloud Shell button in the Azure portal

Enter the following command in the cloud shell:

az ad app create --display-name node-aad-demo --homepage http://localhost --identifier-uris http://node-aad-demo

The arguments for the create command include:

Argument Description
display-name Friendly name of the registration
homepage Url where users can sign in and use your application
identifier-uris Space separated unique URIs that Azure AD can use for this application

Before you can connect to Azure Active Directory, you need the following information:

Name Description Variable Name in Config File
Tenant Name Tenant name you want to use for authentication tenantName
Client ID Client ID is the OAuth term used for the AAD Application ID. clientID

From the registration response in the Azure Cloud Shell, copy the appId value and create a new file named config.js. Next, add in the following code and replace your values with the bracketed tokens:

const tenantName    = //<YOUR_TENANT_NAME>;
const clientID      = //<YOUR_APP_ID_FROM_CLOUD_SHELL>;
const serverPort    = 3000;

module.exports.serverPort = serverPort;

module.exports.credentials = {
  identityMetadata: `https://login.microsoftonline.com/${tenantName}.onmicrosoft.com/.well-known/openid-configuration`, 
  clientID: clientID

For more information regarding the individual configuration settings, review the passport-azure-ad module documentation.

Implement the server

The passport-azure-ad module features two authentication strategies: OIDC and Bearer strategies. The server implemented in this article uses the Bearer strategy to secure the API endpoint.

Step 1: Import dependencies

Create a new file named app.js and paste in the following text:

      restify = require('restify')
    , restifyPlugins = require ('restify').plugins
    , passport = require('passport')
    , BearerStrategy = require('passport-azure-ad').BearerStrategy
    , config = require('./config')
    , authenticatedUserTokens = []
    , serverPort = process.env.PORT || config.serverPort

In this section of code:

  • The restify and plugins modules are referenced in order to set up a Restify server.
  • The passport and passport-azure-ad modules are responsible for communicating with Azure AD.
  • The config variable is initialized with values from the config.js file created in the previous step.
  • An array is created for authenticatedUserTokens to store user tokens as they are passed into secured endpoints.
  • The serverPort is either defined from the process environment's port or from the configuration file.

Step 2: Instantiate an authentication strategy

As you secure an endpoint, you must provide a strategy responsible for determining whether or not the current request originates from an authenticated user. Here the authenticatonStrategy variable is an instance of the passport-azure-ad BearerStrategy class. Add the following code after the require statements.

const authenticationStrategy = new BearerStrategy(config.credentials, (token, done) => {
    let currentUser = null;

    let userToken = authenticatedUserTokens.find((user) => {
        currentUser = user;
        user.sub === token.sub;

    if(!userToken) {

    return done(null, currentUser, token);

This implementation uses auto-registration by adding authentication tokens into the authenticatedUserTokens array if they do not already exist.

Once a new instance of the strategy is created, you must pass it into Passport via the use method. Add the following code to app.js to use the strategy in Passport.


Step 3: Server configuration

With the authentication strategy defined, you can now set up the Restify server with some basic settings and set to use Passport for security.

const server = restify.createServer({ name: 'Azure Active Directory with Node.js Demo' });

This server is initialized and configured to parse authorization headers and then set to use Passport.

Step 4: Define routes

You can now define routes and decide which to secure with Azure AD. This project includes two routes where the root level is open and the /api route is set to require authentication.

In app.js add the following code for the root level route:

server.get('/', (req, res, next) => {
    res.send(200, 'Try: curl -isS -X GET');

The root route allows all requests through the route and returns a message that includes a command to test the /api route. By contrast, the /api route is locked down using passport.authenticate. Add the following code after the root route.

server.get('/api', passport.authenticate('oauth-bearer', { session: false }), (req, res, next) => {
    res.json({ message: 'response from API endpoint' });
    return next();

This configuration only allows authenticated requests that include a bearer token access to /api. The option of session: false is used to disable sessions to require that a token is passed with each request to the API.

Finally, the server is set to listen on the configured port by calling the listen method.


Run the sample

Now that the server is implemented, you can start the server by opening up a command prompt and enter:

npm start

With the server running, you can submit a request to the server to test the results. To demonstrate the response from the root route, open a bash shell and enter the following code:

curl -isS -X GET

If you have configured your server correctly, the response should look similar to:

HTTP/1.1 200 OK
Server: Azure Active Directory with Node.js Demo
Content-Type: application/json
Content-Length: 49
Date: Tue, 10 Oct 2017 18:35:13 GMT
Connection: keep-alive

Try: curl -isS -X GET

Next, you can test the route that requires authentication by entering the following command into your bash shell:

curl -isS -X GET

If you have configured the server correctly, then the server should respond with a status of Unauthorized.

HTTP/1.1 401 Unauthorized
Server: Azure Active Directory with Node.js Demo
WWW-Authenticate: token is not found
Date: Tue, 10 Oct 2017 16:22:03 GMT
Connection: keep-alive
Content-Length: 12


Now that you have created a secure API, you can implement a client that is able to pass authentication tokens to the API.

Next steps