Sdílet prostřednictvím


Kurz: Přihlášení uživatelů a získání tokenu pro Microsoft Graph ve webové aplikaci Node.js & Express

V tomto kurzu vytvoříte webovou aplikaci, která přihlásí uživatele a získá přístupové tokeny pro volání Microsoft Graphu. Webová aplikace, kterou sestavíte, používá Knihovnu MSAL (Microsoft Authentication Library) proNode .

Postupujte podle kroků v tomto kurzu:

  • Registrace aplikace na webu Azure Portal
  • Vytvoření projektu webové aplikace Express
  • Instalace balíčků ověřovací knihovny
  • Přidání podrobností o registraci aplikace
  • Přidání kódu pro přihlášení uživatele
  • Otestování aplikace

Další informace najdete v ukázkovém kódu , který ukazuje, jak se pomocí uzlu MSAL přihlásit, odhlásit se a získat přístupový token pro chráněný prostředek, jako je Microsoft Graph.

Požadavky

Registrace aplikace

Nejprve dokončete kroky v Registrace aplikace pomocí platformy Microsoft Identity k registraci vaší aplikace.

Pro registraci aplikace použijte následující nastavení:

  • Název: ExpressWebApp (navrhované)
  • Podporované typy účtů: Pouze účty v tomto organizačním adresáři
  • Typ platformy: Webové
  • Identifikátor URI přesměrování: http://localhost:3000/auth/redirect
  • Tajný klíč klienta: ********* (poznamenejte si tuto hodnotu pro použití v pozdějším kroku – zobrazí se jenom jednou).

Vytvoření projektu

Pomocí nástroje generátoru aplikací Express vytvořte kostru aplikace.

  1. Nejprve nainstalujte balíček generátoru express-generator:
    npm install -g express-generator
  1. Pak vytvořte kostru aplikace následujícím způsobem:
    express --view=hbs /ExpressWebApp && cd /ExpressWebApp
    npm install

Teď máte jednoduchou webovou aplikaci Express. Struktura souborů a složek projektu by měla vypadat podobně jako následující struktura složek:

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

Nainstalujte autentizační knihovnu

Vyhledejte kořen adresáře projektu v terminálu a nainstalujte balíček MSAL Node přes npm.

    npm install --save @azure/msal-node

Instalujte další závislosti

Ukázka webové aplikace v tomto kurzu používá balíček express-session pro správu relací, dotenv balíček pro čtení parametrů prostředí během vývoje a axios pro volání sítě do rozhraní Microsoft Graph API. Nainstalujte je prostřednictvím npm:

    npm install --save express-session dotenv axios

Přidání podrobností o registraci aplikace

  1. V kořenové složce projektu vytvořte soubor .env.dev. Pak přidejte následující kód:
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"

Vyplňte tyto podrobnosti hodnotami, které získáte z portálu pro registraci aplikací Azure:

  • Enter_the_Cloud_Instance_Id_Here: Cloudová instance Azure, ve které je vaše aplikace zaregistrovaná.
    • V případě hlavního cloudu Azure (nebo globální) zadejte https://login.microsoftonline.com/ (včetně koncového lomítka).
    • Pro národní cloudy (například Čína) najdete odpovídající hodnoty v národních cloudech.
  • Enter_the_Tenant_Info_here by měl být jedním z následujících parametrů:
    • Pokud vaše aplikace podporuje účty v tomto organizačním adresáři, nahraďte tuto hodnotu ID tenanta nebo název tenanta. Například contoso.microsoft.com.
    • Pokud vaše aplikace podporuje účty v libovolném organizačním adresáři, nahraďte tuto hodnotu organizations.
    • Pokud vaše aplikace podporuje účty v libovolném organizačním adresáři a osobní účty Microsoft, nahraďte tuto hodnotu common.
    • Chcete-li omezit podporu na osobní účty Microsoft pouze, nahraďte tuto hodnotu consumers.
  • Enter_the_Application_Id_Here: ID aplikace (klient) aplikace, kterou jste zaregistrovali.
  • Enter_the_Client_secret: Tuto hodnotu nahraďte tajným kódem klienta, který jste vytvořili dříve. Pokud chcete vygenerovat nový klíč, použijte Certifikáty & tajemství v nastavení registrace aplikace v Azure Portal.

Varování

Jakýkoli tajný kód prostého textu ve zdrojovém kódu představuje zvýšené bezpečnostní riziko. Tento článek používá pouze tajný kód klienta ve formátu prostého textu. V důvěrných klientských aplikacích používejte přihlašovací údaje certifikátu místo tajných klíčů klienta, zejména těch aplikací, které chcete nasadit do produkčního prostředí.

  • Enter_the_Graph_Endpoint_Here: Cloudová instance rozhraní Microsoft Graph API, kterou bude vaše aplikace volat. Pro hlavní (globální) službu Microsoft Graph API zadejte https://graph.microsoft.com/ (včetně koncového lomítka).
  • Enter_the_Express_Session_Secret_Here tajný kód použitý k podepisování session cookie Expressu. Zvolte náhodný řetězec znaků, kterým chcete tento řetězec nahradit, například tajným kódem klienta.
  1. Dále vytvořte soubor s názvem authConfig.js v kořenovém adresáři projektu pro čtení v těchto parametrech. Po vytvoření přidejte do ní následující kód:
/*
 * 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
};

Přidání kódu pro získání přihlášení uživatele a tokenu

  1. Vytvořte novou složku s názvem ověřovánía přidejte do ní nový soubor s názvem AuthProvider.js. Bude obsahovat třídu AuthProvider, která zapouzdřuje potřebnou logiku ověřování pomocí uzlu MSAL. Přidejte do ní následující kód:
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. Dále vytvořte nový soubor s názvem auth.js ve složce trasy a přidejte do ní následující kód:
/*
 * 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. Aktualizujte trasu index.js nahrazením existujícího kódu následujícím fragmentem kódu:
/*
 * 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. Nakonec aktualizujte trasu users.js nahrazením existujícího kódu následujícím fragmentem kódu:
/*
 * 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;

Přidání kódu pro volání rozhraní Microsoft Graph API

V kořenovém adresáři projektu vytvořte soubor s názvem fetch.js a přidejte následující kód:

/*
 * 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;

Přidat pohledy pro zobrazení dat

  1. Ve složce zobrazení aktualizujte soubor index.hbs tím, že nahradíte stávající kód následujícím:
<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. Ve stejné složce vytvořte další soubor s názvem id.hbs pro zobrazení obsahu tokenu ID uživatele:
<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. Nakonec vytvořte další soubor s názvem profile.hbs pro zobrazení výsledku volání microsoft Graphu:
<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>

Registrace směrovačů a přidání správy stavu

V souboru app.js v kořenové složce projektu zaregistrujte trasy, které jste vytvořili dříve, a přidejte podporu relace pro sledování stavu ověřování pomocí balíčku express-session. Existující kód tam nahraďte následujícím fragmentem kódu:

/*
 * 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;

Testování přihlášení a volání Microsoft Graphu

Dokončili jste vytváření aplikace a teď jste připraveni otestovat funkčnost aplikace.

  1. Spusťte konzolovou aplikaci Node.js spuštěním následujícího příkazu v kořenové složce projektu:
   npm start
  1. Otevřete okno prohlížeče a přejděte na http://localhost:3000. Měla by se zobrazit úvodní stránka:

úvodní stránka webové aplikace zobrazující

  1. Vyberte odkaz Přihlásit se. Měla by se zobrazit přihlašovací obrazovka Microsoft Entra:

na přihlašovací obrazovce Microsoft Entra zobrazující

  1. Po zadání přihlašovacích údajů by se měla zobrazit obrazovka pro vyjádření souhlasu s žádostí o schválení oprávnění pro aplikaci.

Microsoft Entra obrazovka souhlasu zobrazující

  1. Jakmile souhlasíte, měli byste být přesměrováni zpět na domovskou stránku aplikace.

úvodní stránka webové aplikace po přihlášení zobrazující

  1. Vyberte odkaz Zobrazit token ID pro zobrazení obsahu tokenu ID přihlášeného uživatele.

obrazovka s tokenem ID uživatele zobrazující

  1. Vraťte se na domovskou stránku a vyberte Získat přístupový token a volejte odkaz rozhraní Microsoft Graph API. Jakmile to uděláte, měla by se zobrazit odpověď koncového bodu Microsoft Graph /me pro přihlášeného uživatele.

obrazovka pro volání Graph zobrazující

  1. Vraťte se na domovskou stránku a vyberte odkaz Odhlásit se. Měla by se zobrazit přihlašovací obrazovka Microsoft Entra.

odhlašovací obrazovka Microsoft Entra zobrazující

Jak aplikace funguje

V tomto kurzu jste vytvořili instanci objektu MSAL Node ConfidentialClientApplication tím, že jste předali konfigurační objekt (msalConfig), který obsahuje parametry získané z registrace vaší aplikace Microsoft Entra na portálu Azure. Vytvořená webová aplikace používá protokol OpenID Connect pro přihlášení a tok autorizačního kódu OAuth 2.0 k získání přístupových tokenů.

Další kroky

Pokud se chcete podrobněji podívat na vývoj webových aplikací Node.js & Express na platformě Microsoft Identity Platform, podívejte se na naši sérii scénářů s více částmi: