Skip to content

Latest commit

 

History

History
194 lines (143 loc) · 9.01 KB

File metadata and controls

194 lines (143 loc) · 9.01 KB
languages page_type description products
javascript
powershell
html
sample
Learn how to sign-in users to your web app, call Azure storage, and call Microsoft Graph.
nodejs
express
ms-graph
azure
azure-storage
azure-active-directory

Tutorial: Enable authentication in App Service and call Microsoft Graph (as the signed-in user)

About this sample

Overview

This sample demonstrates a Node.js & Express web app that uses authentication to limit access to users in your organization​ and then calls Microsoft Graph as the signed-in user. The web app authenticates a user and displays some of the user's profile information. This sample is a companion to the Access Microsoft Graph from a secured app as the user tutorial on docs.microsoft.com.

Scenario

You want to limit access to your web app running on Azure App Service to people in your organization. App Service provides built-in authentication and authorization support, so you can sign in users and access data by writing minimal or no code in your web app.

You also want to add access to Microsoft Graph from your web app and perform some action as the signed-in user. This section describes how to grant delegated permissions to the web app and get the signed-in user's profile information from Azure Active Directory (Azure AD).

How to run this sample

To run this sample, you'll need:

Step 1: Clone or download this repository

Clone or download this repository. From your shell or command line:

git clone https://github.com/Azure-Samples/ms-identity-easyauth-nodejs-storage-graphapi.git
cd ms-identity-easyauth-nodejs-storage-graphapi
cd 2-WebApp-graphapi-on-behalf

Step 2: Deploy the web app and configure App Service authentication

This project has one WebApp project. To deploy it to Azure App Service, you'll need to:

  • configure a deployment user
  • create an Azure App Service plan
  • create a web app
  • publish the web app to Azure

For information on how to do this from VS Code using the App Service Extension, see the tutorial.

After you've deployed the web app to Azure, configure the Azure App Service authentication/authorization module. Also verify that only users in your organization can access the web site.

Step 3: Grant web app access to call Microsoft Graph

Now that you've enabled authentication and authorization on your web app, the web app is registered with the Microsoft identity platform and is backed by an Azure AD application. In this step, you give the web app permissions to access Microsoft Graph for the user. For more information, read Grant web app access in the tutorial on docs.microsoft.com.

Step 4: Configure App Service to return a usable access token

The web app now has the required permissions to access Microsoft Graph as the signed-in user. In this step, you configure App Service authentication and authorization to give you a usable access token for accessing Microsoft Graph. For more information, read Configure App Service to return a usable access token in the tutorial on docs.microsoft.com.

Step 5: Visit the web app

Open a browser and navigate to the deployed web app (replace web-app-name with the name of your web app): https://web-app-name.azurewebsites.net. Once authenticated, select the Profile button at the center of the page. This will take you to the page that displays your profile data from Microsoft Graph.

About the code

This sample is built using the @azure-samples/microsoft-identity-express package for authentication and authorization, and the @microsoft/microsoft-graph-client package for querying Microsoft Graph.

Add authentication to your web app

The signIn middleware in routes/mainRoutes.js receives the App Service authentication headers from the incoming request, and then initializes a session variable with the user account, which indicates that the user has successfully signed-in.

    router.get('/login', msid.signIn({
        postLoginRedirect: '/home',
    }));

The isAuthenticated middleware checks the user's session variable to make sure the user is still signed in during route transitions:

router.get('/id', msid.isAuthenticated(), mainController.getIdPage);

When the user selects the sign-out button on the navigation bar, the signOut middleware wipes clean the user's session variable, and redirects the app to home page:

    router.get('/logout', msid.signOut({
        postLogoutRedirect: '/home',
    }));

Display name of the signed-in user

When you access the web app running on Azure, you see sign-in/sign-out and ID buttons at the top of the page. The ID page displays the contents of the singed-in user's ID token. To do so, we access the user's account via the session variable, which is populated when the user signs-in. The code for this is found in the controllers/mainController.js file:

exports.getIdPage = (req, res, next) => {
    const claims = {
        name: req.session.account.idTokenClaims.name,
        preferred_username: req.session.account.idTokenClaims.preferred_username,
        oid: req.session.account.idTokenClaims.oid,
        sub: req.session.account.idTokenClaims.sub
    };

    res.render('id', { isAuthenticated: req.session.isAuthenticated, appServiceName: appServiceName, claims: claims });
}

The claims object is then displayed on the views/id.ejs file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" status="width=device-width, initial-scale=1.0">
    <title>ID</title>
</head>
<body>
    <%- include('includes/navbar', {isAuthenticated: isAuthenticated, appServiceName: appServiceName}); %>
        <div class="table-area-div">
            <table class="table" style="table-layout: fixed">
                <thead class="thead-dark">
                    <tr>
                        <th scope="col">Claim</th>
                        <th scope="col">Value</th>
                    </tr>
                </thead>
                <tbody>
                    <% for (const [key, value] of Object.entries(claims)) { %>
                        <tr>
                            <td><%= key %></td>
                            <td><%= value %></td>
                        </tr>
                    <% } %>
                </tbody>
            </table>
        </div>
</body>
</html>

Call Microsoft Graph on behalf of the signed-in user

The sample app gets the user's access token from the incoming requests header, which is then passed down to Microsoft Graph client to make an authenticated request to the /me endpoint:

const graphHelper = require('../utils/graphHelper');

exports.getProfilePage = async(req, res, next) => {

    try {
        const graphClient = graphHelper.getAuthenticatedClient(req.session.protectedResources["graphAPI"].accessToken);

        const profile = await graphClient
            .api('/me')
            .get();

        res.render('profile', { isAuthenticated: req.session.isAuthenticated, profile: profile, appServiceName: appServiceName });   
    } catch (error) {
        next(error);
    }
}

To query Microsoft Graph, the sample uses the Microsoft Graph JavaScript SDK. The code for this is located in utils/graphHelper.js:

getAuthenticatedClient = (accessToken) => {
    // Initialize Graph client
    const client = graph.Client.init({
        // Use the provided access token to authenticate requests
        authProvider: (done) => {
            done(null, accessToken);
        }
    });

    return client;
}

Resources

Read the Access Microsoft Graph from a secured app as the user tutorial.