Tutorial: Anmelden von Benutzern und Abrufen eines Tokens für Microsoft Graph in einer Node.js & Express-Web-App

In diesem Tutorial erstellen Sie eine Web-App, die Benutzer anmeldet und Zugriffstoken für das Aufrufen von Microsoft Graph erwirbt. Die von Ihnen erstellte Desktop-App verwendet die Microsoft-Authentifizierungsbibliothek (Microsoft Authentication Library, MSAL) für Node.

Führen Sie die Schritte in diesem Tutorial für folgende Aktionen aus:

  • Registrieren der Anwendung im Azure-Portal
  • Erstellen eines Express-Web-App-Projekts
  • Installieren der Pakete für die Authentifizierungsbibliothek
  • Hinzufügen von App-Registrierungsdetails
  • Hinzufügen von Code für die Benutzeranmeldung
  • Testen der App

Weitere Informationen finden Sie im Beispielcode, der zeigt, wie Sie sich mit MSAL Node an- und abmelden und ein Zugriffstoken für eine geschützte Ressource wie Microsoft Graph beziehen.

Voraussetzungen

Registrieren der Anwendung

Führen Sie zunächst die Schritte unter Schnellstart: Registrieren einer Anwendung bei Microsoft Identity Platform aus, um Ihre App zu registrieren.

Verwenden Sie die folgenden Einstellungen für Ihre App-Registrierung:

  • Name: ExpressWebApp (Vorschlag)
  • Unterstützte Kontotypen: Nur Konten in diesem Organisationsverzeichnis
  • Plattformtyp: Web
  • Umleitungs-URI: http://localhost:3000/auth/redirect
  • Geheimer Clientschlüssel: ********* (Notieren Sie diesen Wert für die Verwendung in einem späteren Schritt. Er wird nur einmal angezeigt.)

Erstellen des Projekts

Verwenden Sie das Express-Anwendungsgeneratortool, um ein Anwendungsskelett zu erstellen.

  1. Installieren Sie zuerst das Express-Generator-Paket:
    npm install -g express-generator
  1. Erstellen Sie dann wie folgt ein Anwendungsskelett:
    express --view=hbs /ExpressWebApp && cd /ExpressWebApp
    npm install

Sie haben jetzt eine einfache Express-Webanwendung. Die Datei- und Ordnerstruktur Ihres Projekts muss in etwa wie folgt aussehen:

ExpressWebApp/
├── bin/
|    └── wwww
├── public/
|    ├── images/
|    ├── javascript/
|    └── stylesheets/
|        └── style.css
├── routes/
|    ├── index.js
|    └── users.js
├── views/
|    ├── error.hbs
|    ├── index.hbs
|    └── layout.hbs
├── app.js
└── package.json

Installieren der Authentifizierungsbibliothek

Suchen Sie den Stamm Ihres Projektverzeichnisses in einem Terminal, und installieren Sie das MSAL Node-Paket über npm.

    npm install --save @azure/msal-node

Installieren anderer Abhängigkeiten

Die Web-App-Stichprobe in diesem Lernprogramm verwendet das Expresssitzungspaket für die Sitzungsverwaltung, dotenv-Paket zum Lesen von Umgebungsparametern während der Entwicklung und axios zum Ausführen von Netzwerkaufrufen an die Microsoft Graph-API. Installieren Sie diese über npm:

    npm install --save express-session dotenv axios

Hinzufügen von App-Registrierungsdetails

  1. Erstellen Sie eine .env.dev-Datei im Stammverzeichnis Ihres Projektordners. Fügen Sie dann den folgenden Code hinzu:
CLOUD_INSTANCE="Enter_the_Cloud_Instance_Id_Here" # cloud instance string should end with a trailing slash
TENANT_ID="Enter_the_Tenant_Info_Here"
CLIENT_ID="Enter_the_Application_Id_Here"
CLIENT_SECRET="Enter_the_Client_Secret_Here"

REDIRECT_URI="http://localhost:3000/auth/redirect"
POST_LOGOUT_REDIRECT_URI="http://localhost:3000"

GRAPH_API_ENDPOINT="Enter_the_Graph_Endpoint_Here" # graph api endpoint string should end with a trailing slash

EXPRESS_SESSION_SECRET="Enter_the_Express_Session_Secret_Here"

Füllen Sie diese Details mit den Werten aus, die Sie aus dem Azure-Portal für die App-Registrierung abrufen:

  • Enter_the_Cloud_Instance_Id_Here: Die Azure Cloud-Instanz, in der Ihre Anwendung registriert ist.
    • Geben Sie für die Azure-Haupt-Cloud (oder die globale) Azure-Cloud https://login.microsoftonline.com/ ein (schließen Sie den nachgestellten Schrägstrich ein).
    • Geeignete Werte für nationale Clouds (z. B. für China) finden Sie unter Nationale Clouds.
  • Enter_the_Tenant_Info_here muss einer der folgenden Parameter sein:
    • Wenn Ihre Anwendung Nur Konten in diesem Organisationsverzeichnis unterstützt, ersetzen Sie diesen Wert durch die Mandanten-ID oder den Mandantennamen. Beispiel: contoso.microsoft.com.
    • Falls Ihre Anwendung Konten in einem beliebigen Organisationsverzeichnis unterstützt, ersetzen Sie diesen Wert durch organizations.
    • Unterstützt Ihre Anwendung Konten in allen Organisationsverzeichnissen und persönliche Microsoft-Konten, ersetzen Sie diesen Wert durch common.
    • Wenn Sie die Unterstützung ausschließlich auf persönliche Microsoft-Konten beschränken möchten, ersetzen Sie diesen Wert durch consumers.
  • Enter_the_Application_Id_Here: Die Anwendungs-ID (Client) der von Ihnen registrierten Anwendung.
  • Enter_the_Client_secret: Ersetzen Sie diesen Wert durch den zuvor erstellten geheimen Clientschlüssel. Generieren Sie im Azure-Portal mithilfe von Zertifikate und Geheimnisse in den App-Registrierungseinstellungen einen neuen Schlüssel.

Warnung

Ein Klartextgeheimnis im Quellcode stellt ein höheres Sicherheitsrisiko dar. In diesem Artikel wird nur der Einfachheit halber ein geheimer Clientschlüssel in Klartext verwendet. Verwenden Sie in vertraulichen Clientanwendungen Zertifikatanmeldeinformationen anstelle von geheimen Clientschlüsseln. Dies gilt insbesondere bei Apps, die Sie in der Produktion bereitstellen möchten.

  • Enter_the_Graph_Endpoint_Here: Die Microsoft Graph-API-Cloudinstanz, die Ihre App aufruft. Geben Sie für den Microsoft Graph-API-Hauptdienst (global) https://graph.microsoft.com/ (einschließlich des nachstehenden Schrägstrichs) ein.
  • Enter_the_Express_Session_Secret_Here der geheime Schlüssel, der zum Signieren des Express-Sitzungscookies verwendet wird. Wählen Sie eine zufällige Zeichenfolge aus, mit der diese Zeichenfolge ersetzt werden soll, z. B. Ihren geheimen Clientschlüssel.
  1. Erstellen Sie als Nächstes eine Datei namens authConfig.js im Stamm Ihres Projekts zum Lesen in diesen Parametern. Fügen Sie nach der Erstellung den folgenden Code hinzu:
/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License.
 */

require('dotenv').config({ path: '.env.dev' });

/**
 * Configuration object to be passed to MSAL instance on creation.
 * For a full list of MSAL Node configuration parameters, visit:
 * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/configuration.md
 */
const msalConfig = {
    auth: {
        clientId: process.env.CLIENT_ID, // 'Application (client) ID' of app registration in Azure portal - this value is a GUID
        authority: process.env.CLOUD_INSTANCE + process.env.TENANT_ID, // Full directory URL, in the form of https://login.microsoftonline.com/<tenant>
        clientSecret: process.env.CLIENT_SECRET // Client secret generated from the app registration in Azure portal
    },
    system: {
        loggerOptions: {
            loggerCallback(loglevel, message, containsPii) {
                console.log(message);
            },
            piiLoggingEnabled: false,
            logLevel: 3,
        }
    }
}

const REDIRECT_URI = process.env.REDIRECT_URI;
const POST_LOGOUT_REDIRECT_URI = process.env.POST_LOGOUT_REDIRECT_URI;
const GRAPH_ME_ENDPOINT = process.env.GRAPH_API_ENDPOINT + "v1.0/me";

module.exports = {
    msalConfig,
    REDIRECT_URI,
    POST_LOGOUT_REDIRECT_URI,
    GRAPH_ME_ENDPOINT
};

Hinzufügen von Code für Benutzeranmeldung und Tokenbezug

  1. Erstellen Sie einen neuen Ordner mit dem Namen auth und fügen Sie darin eine neue Datei mit dem Namen AuthProvider.js hinzu. Diese enthält die AuthProvider-Klasse, die die erforderliche Authentifizierungslogik mithilfe von MSAL Node kapselt. Fügen Sie dort den folgenden Code hinzu:
const msal = require('@azure/msal-node');
const axios = require('axios');

const { msalConfig } = require('../authConfig');

class AuthProvider {
    msalConfig;
    cryptoProvider;

    constructor(msalConfig) {
        this.msalConfig = msalConfig
        this.cryptoProvider = new msal.CryptoProvider();
    };

    login(options = {}) {
        return async (req, res, next) => {

            /**
             * MSAL Node library allows you to pass your custom state as state parameter in the Request object.
             * The state parameter can also be used to encode information of the app's state before redirect.
             * You can pass the user's state in the app, such as the page or view they were on, as input to this parameter.
             */
            const state = this.cryptoProvider.base64Encode(
                JSON.stringify({
                    successRedirect: options.successRedirect || '/',
                })
            );

            const authCodeUrlRequestParams = {
                state: state,

                /**
                 * By default, MSAL Node will add OIDC scopes to the auth code url request. For more information, visit:
                 * https://docs.microsoft.com/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes
                 */
                scopes: options.scopes || [],
                redirectUri: options.redirectUri,
            };

            const authCodeRequestParams = {
                state: state,

                /**
                 * By default, MSAL Node will add OIDC scopes to the auth code request. For more information, visit:
                 * https://docs.microsoft.com/azure/active-directory/develop/v2-permissions-and-consent#openid-connect-scopes
                 */
                scopes: options.scopes || [],
                redirectUri: options.redirectUri,
            };

            /**
             * If the current msal configuration does not have cloudDiscoveryMetadata or authorityMetadata, we will 
             * make a request to the relevant endpoints to retrieve the metadata. This allows MSAL to avoid making 
             * metadata discovery calls, thereby improving performance of token acquisition process. For more, see:
             * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/performance.md
             */
            if (!this.msalConfig.auth.cloudDiscoveryMetadata || !this.msalConfig.auth.authorityMetadata) {

                const [cloudDiscoveryMetadata, authorityMetadata] = await Promise.all([
                    this.getCloudDiscoveryMetadata(this.msalConfig.auth.authority),
                    this.getAuthorityMetadata(this.msalConfig.auth.authority)
                ]);

                this.msalConfig.auth.cloudDiscoveryMetadata = JSON.stringify(cloudDiscoveryMetadata);
                this.msalConfig.auth.authorityMetadata = JSON.stringify(authorityMetadata);
            }

            const msalInstance = this.getMsalInstance(this.msalConfig);

            // trigger the first leg of auth code flow
            return this.redirectToAuthCodeUrl(
                authCodeUrlRequestParams,
                authCodeRequestParams,
                msalInstance
            )(req, res, next);
        };
    }

    acquireToken(options = {}) {
        return async (req, res, next) => {
            try {
                const msalInstance = this.getMsalInstance(this.msalConfig);

                /**
                 * If a token cache exists in the session, deserialize it and set it as the 
                 * cache for the new MSAL CCA instance. For more, see: 
                 * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/caching.md
                 */
                if (req.session.tokenCache) {
                    msalInstance.getTokenCache().deserialize(req.session.tokenCache);
                }

                const tokenResponse = await msalInstance.acquireTokenSilent({
                    account: req.session.account,
                    scopes: options.scopes || [],
                });

                /**
                 * On successful token acquisition, write the updated token 
                 * cache back to the session. For more, see: 
                 * https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-node/docs/caching.md
                 */
                req.session.tokenCache = msalInstance.getTokenCache().serialize();
                req.session.accessToken = tokenResponse.accessToken;
                req.session.idToken = tokenResponse.idToken;
                req.session.account = tokenResponse.account;

                res.redirect(options.successRedirect);
            } catch (error) {
                if (error instanceof msal.InteractionRequiredAuthError) {
                    return this.login({
                        scopes: options.scopes || [],
                        redirectUri: options.redirectUri,
                        successRedirect: options.successRedirect || '/',
                    })(req, res, next);
                }

                next(error);
            }
        };
    }

    handleRedirect(options = {}) {
        return async (req, res, next) => {
            if (!req.body || !req.body.state) {
                return next(new Error('Error: response not found'));
            }

            const authCodeRequest = {
                ...req.session.authCodeRequest,
                code: req.body.code,
                codeVerifier: req.session.pkceCodes.verifier,
            };

            try {
                const msalInstance = this.getMsalInstance(this.msalConfig);

                if (req.session.tokenCache) {
                    msalInstance.getTokenCache().deserialize(req.session.tokenCache);
                }

                const tokenResponse = await msalInstance.acquireTokenByCode(authCodeRequest, req.body);

                req.session.tokenCache = msalInstance.getTokenCache().serialize();
                req.session.idToken = tokenResponse.idToken;
                req.session.account = tokenResponse.account;
                req.session.isAuthenticated = true;

                const state = JSON.parse(this.cryptoProvider.base64Decode(req.body.state));
                res.redirect(state.successRedirect);
            } catch (error) {
                next(error);
            }
        }
    }

    logout(options = {}) {
        return (req, res, next) => {

            /**
             * Construct a logout URI and redirect the user to end the
             * session with Azure AD. For more information, visit:
             * https://docs.microsoft.com/azure/active-directory/develop/v2-protocols-oidc#send-a-sign-out-request
             */
            let logoutUri = `${this.msalConfig.auth.authority}/oauth2/v2.0/`;

            if (options.postLogoutRedirectUri) {
                logoutUri += `logout?post_logout_redirect_uri=${options.postLogoutRedirectUri}`;
            }

            req.session.destroy(() => {
                res.redirect(logoutUri);
            });
        }
    }

    /**
     * Instantiates a new MSAL ConfidentialClientApplication object
     * @param msalConfig: MSAL Node Configuration object 
     * @returns 
     */
    getMsalInstance(msalConfig) {
        return new msal.ConfidentialClientApplication(msalConfig);
    }


    /**
     * Prepares the auth code request parameters and initiates the first leg of auth code flow
     * @param req: Express request object
     * @param res: Express response object
     * @param next: Express next function
     * @param authCodeUrlRequestParams: parameters for requesting an auth code url
     * @param authCodeRequestParams: parameters for requesting tokens using auth code
     */
    redirectToAuthCodeUrl(authCodeUrlRequestParams, authCodeRequestParams, msalInstance) {
        return async (req, res, next) => {
            // Generate PKCE Codes before starting the authorization flow
            const { verifier, challenge } = await this.cryptoProvider.generatePkceCodes();

            // Set generated PKCE codes and method as session vars
            req.session.pkceCodes = {
                challengeMethod: 'S256',
                verifier: verifier,
                challenge: challenge,
            };

            /**
             * By manipulating the request objects below before each request, we can obtain
             * auth artifacts with desired claims. For more information, visit:
             * https://azuread.github.io/microsoft-authentication-library-for-js/ref/modules/_azure_msal_node.html#authorizationurlrequest
             * https://azuread.github.io/microsoft-authentication-library-for-js/ref/modules/_azure_msal_node.html#authorizationcoderequest
             **/
            req.session.authCodeUrlRequest = {
                ...authCodeUrlRequestParams,
                responseMode: msal.ResponseMode.FORM_POST, // recommended for confidential clients
                codeChallenge: req.session.pkceCodes.challenge,
                codeChallengeMethod: req.session.pkceCodes.challengeMethod,
            };

            req.session.authCodeRequest = {
                ...authCodeRequestParams,
                code: '',
            };

            try {
                const authCodeUrlResponse = await msalInstance.getAuthCodeUrl(req.session.authCodeUrlRequest);
                res.redirect(authCodeUrlResponse);
            } catch (error) {
                next(error);
            }
        };
    }

    /**
     * Retrieves cloud discovery metadata from the /discovery/instance endpoint
     * @returns 
     */
    async getCloudDiscoveryMetadata(authority) {
        const endpoint = 'https://login.microsoftonline.com/common/discovery/instance';

        try {
            const response = await axios.get(endpoint, {
                params: {
                    'api-version': '1.1',
                    'authorization_endpoint': `${authority}/oauth2/v2.0/authorize`
                }
            });

            return await response.data;
        } catch (error) {
            throw error;
        }
    }

    /**
     * Retrieves oidc metadata from the openid endpoint
     * @returns
     */
    async getAuthorityMetadata(authority) {
        const endpoint = `${authority}/v2.0/.well-known/openid-configuration`;

        try {
            const response = await axios.get(endpoint);
            return await response.data;
        } catch (error) {
            console.log(error);
        }
    }
}

const authProvider = new AuthProvider(msalConfig);

module.exports = authProvider;
  1. Erstellen Sie eine neue Datei namens auth.js im Ordner router und fügen Sie den folgenden Code ein:
/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License.
 */

var express = require('express');

const authProvider = require('../auth/AuthProvider');
const { REDIRECT_URI, POST_LOGOUT_REDIRECT_URI } = require('../authConfig');

const router = express.Router();

router.get('/signin', authProvider.login({
    scopes: [],
    redirectUri: REDIRECT_URI,
    successRedirect: '/'
}));

router.get('/acquireToken', authProvider.acquireToken({
    scopes: ['User.Read'],
    redirectUri: REDIRECT_URI,
    successRedirect: '/users/profile'
}));

router.post('/redirect', authProvider.handleRedirect());

router.get('/signout', authProvider.logout({
    postLogoutRedirectUri: POST_LOGOUT_REDIRECT_URI
}));

module.exports = router;
  1. Aktualisieren Sie als Nächstes die Route in index.js, indem Sie den vorhandenen Code durch den folgenden Codeschnipsel ersetzen:
/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License.
 */

var express = require('express');
var router = express.Router();

router.get('/', function (req, res, next) {
    res.render('index', {
        title: 'MSAL Node & Express Web App',
        isAuthenticated: req.session.isAuthenticated,
        username: req.session.account?.username,
    });
});

module.exports = router;
  1. Aktualisieren Sie abschließend die Route in index.js, indem Sie den vorhandenen Code durch den folgenden Codeschnipsel ersetzen:
/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License.
 */

var express = require('express');
var router = express.Router();

var fetch = require('../fetch');

var { GRAPH_ME_ENDPOINT } = require('../authConfig');

// custom middleware to check auth state
function isAuthenticated(req, res, next) {
    if (!req.session.isAuthenticated) {
        return res.redirect('/auth/signin'); // redirect to sign-in route
    }

    next();
};

router.get('/id',
    isAuthenticated, // check if user is authenticated
    async function (req, res, next) {
        res.render('id', { idTokenClaims: req.session.account.idTokenClaims });
    }
);

router.get('/profile',
    isAuthenticated, // check if user is authenticated
    async function (req, res, next) {
        try {
            const graphResponse = await fetch(GRAPH_ME_ENDPOINT, req.session.accessToken);
            res.render('profile', { profile: graphResponse });
        } catch (error) {
            next(error);
        }
    }
);

module.exports = router;

Hinzufügen von Code zum Aufrufen der Microsoft Graph-API

Erstellen Sie im Stamm Ihres Projekts eine Datei namens fetch.js und fügen Sie den folgenden Code ein:

/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License.
 */

var axios = require('axios');

/**
 * Attaches a given access token to a MS Graph API call
 * @param endpoint: REST API endpoint to call
 * @param accessToken: raw access token string
 */
async function fetch(endpoint, accessToken) {
    const options = {
        headers: {
            Authorization: `Bearer ${accessToken}`
        }
    };

    console.log(`request made to ${endpoint} at: ` + new Date().toString());

    try {
        const response = await axios.get(endpoint, options);
        return await response.data;
    } catch (error) {
        throw new Error(error);
    }
}

module.exports = fetch;

Hinzufügen von Ansichten zum Anzeigen von Daten

  1. Aktualisieren Sie im Ordner Ansichten die Datei index.hbs, indem Sie den vorhandenen Code durch Folgendes ersetzen:
<h1>{{title}}</h1>
{{#if isAuthenticated }}
<p>Hi {{username}}!</p>
<a href="/users/id">View ID token claims</a>
<br>
<a href="/auth/acquireToken">Acquire a token to call the Microsoft Graph API</a>
<br>
<a href="/auth/signout">Sign out</a>
{{else}}
<p>Welcome to {{title}}</p>
<a href="/auth/signin">Sign in</a>
{{/if}}
  1. Erstellen Sie weiterhin im gleichen Ordner eine andere Datei namens id.hbs, um den Inhalt des ID-Tokens des Benutzers anzuzeigen:
<h1>Azure AD</h1>
<h3>ID Token</h3>
<table>
    <tbody>
        {{#each idTokenClaims}}
        <tr>
            <td>{{@key}}</td>
            <td>{{this}}</td>
        </tr>
        {{/each}}
    </tbody>
</table>
<br>
<a href="https://aka.ms/id-tokens" target="_blank">Learn about claims in this ID token</a>
<br>
<a href="/">Go back</a>
  1. Erstellen Sie schließlich eine andere Datei namens profile.hbs zum Anzeigen des Ergebnisses des Aufrufs an Microsoft Graph:
<h1>Microsoft Graph API</h1>
<h3>/me endpoint response</h3>
<table>
    <tbody>
        {{#each profile}}
        <tr>
            <td>{{@key}}</td>
            <td>{{this}}</td>
        </tr>
        {{/each}}
    </tbody>
</table>
<br>
<a href="/">Go back</a>

Registrieren von Routern und Hinzufügen der Zustandsverwaltung

Registrieren Sie in der Datei app.js im Stamm des Projektordners die Routen, die Sie zuvor erstellt haben, und fügen Sie Sitzungsunterstützung für die Nachverfolgung des Authentifizierungsstatus mithilfe des Pakets express-session hinzu. Ersetzen Sie den vorhandenen Code durch den folgenden Codeschnipsel:

/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License.
 */

require('dotenv').config();

var path = require('path');
var express = require('express');
var session = require('express-session');
var createError = require('http-errors');
var cookieParser = require('cookie-parser');
var logger = require('morgan');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var authRouter = require('./routes/auth');

// initialize express
var app = express();

/**
 * Using express-session middleware for persistent user session. Be sure to
 * familiarize yourself with available options. Visit: https://www.npmjs.com/package/express-session
 */
 app.use(session({
    secret: process.env.EXPRESS_SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    cookie: {
        httpOnly: true,
        secure: false, // set this to true on production
    }
}));

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');

app.use(logger('dev'));
app.use(express.json());
app.use(cookieParser());
app.use(express.urlencoded({ extended: false }));
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/auth', authRouter);

// catch 404 and forward to error handler
app.use(function (req, res, next) {
    next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {
    // set locals, only providing error in development
    res.locals.message = err.message;
    res.locals.error = req.app.get('env') === 'development' ? err : {};

    // render the error page
    res.status(err.status || 500);
    res.render('error');
});

module.exports = app;

Testen der Anmeldung und Aufrufen von Microsoft Graph

Sie haben die Erstellung der Anwendung abgeschlossen und sind nun bereit, die Funktionalität der App zu testen.

  1. Starten Sie die Node.js-Konsolen-App, indem Sie den folgenden Befehl im Stammverzeichnis Ihres Projektordners ausführen:
   npm start
  1. Öffnen Sie ein Browserfenster, und navigieren Sie zu http://localhost:3000. Es sollte eine Willkommensseite angezeigt werden:

Web app welcome page displaying

  1. Wählen Sie den Link Anmelden aus. Sie sollten nun den Anmeldebildschirm von Microsoft Entra sehen:

Microsoft Entra sign-in screen displaying

  1. Nachdem Sie Ihre Anmelde Informationen eingegeben haben, wird ein Zustimmungsbildschirm angezeigt, auf dem Sie zur Genehmigung der Berechtigungen für die App aufgefordert werden.

Microsoft Entra consent screen displaying

  1. Sobald Sie zugestimmt haben, sollten Sie wieder zur Startseite der Anwendung umgeleitet werden.

Web app welcome page after sign-in displaying

  1. Wählen Sie den Link ID-Token anzeigen aus, um den Inhalt des ID-Tokens des angemeldeten Benutzers anzuzeigen.

User ID token screen displaying

  1. Gehen Sie zurück auf die Willkommensseite, und wählen Sie den Link Zugriffstoken abrufen und die Microsoft Graph-API aufrufen. Anschließend sollten Sie die Antwort von Microsoft Graph /me-Endpunkt für den angemeldeten Benutzer sehen.

Graph call screen displaying

  1. Gehen Sie zurück zur Willkommensseite und wählen Sie den Link Abmelden aus. Sie sollten nun den Abmeldebildschirm von Microsoft Entra sehen.

Microsoft Entra sign-out screen displaying

Funktionsweise der Anwendung

In diesem Tutorial haben Sie ein MSAL Node-Objekt vom Typ ConfidentialClientApplication instanziiert, indem Sie ein Konfigurationsobjekt (msalConfig) übergeben haben, das aus der Microsoft Entra-App-Registrierung im Azure-Portal abgerufene Parameter enthält. Die von Ihnen erstellte Webanwendung verwendet das Protokoll OpenID Connect, um Benutzer anzumelden, und den OAuth 2.0-Autorisierungscodeflow, um Zugriffstoken zu beziehen.

Nächste Schritte

Wenn Sie sich ausführlicher mit der Entwicklung von Node.js- und Express-Webanwendungen auf Microsoft Identity Platform beschäftigen möchten, können Sie sich die mehrteilige Szenarioreihe ansehen: