Esercitazione: Eseguire l’accesso degli utenti e acquisire un token per Microsoft Graph in un'app Web Node.js & Express

In questa esercitazione viene compilata un'app Web che esegue l’accesso degli utenti e acquisisce i token di accesso per chiamare Microsoft Graph. L'app Web compilata usa Microsoft Authentication Library (MSAL) per Node.

Seguire i passaggi descritti in questa esercitazione per:

  • Registrare l'applicazione nel portale di Azure
  • Creare un progetto di app Web Express
  • Installare i pacchetti della libreria di autenticazione
  • Aggiungere i dettagli di registrazione dell'app
  • Aggiungere il codice per l'accesso utente
  • Testare l'app

Per altre informazioni vedere il codice di esempio che mostra come usare il nodo MSAL per accedere, disconnettersi e acquisire un token di accesso per una risorsa protetta, ad esempio Microsoft Graph.

Prerequisiti

Registrare l'applicazione

Prima completare i passaggi descritti in Registrare un'applicazione con Microsoft Identity Platform per registrare l'app.

Usare le impostazioni seguenti per la registrazione dell'app:

  • Nome: ExpressWebApp (consigliato)
  • Tipi di account supportati: Account solo in questa directory organizzativa
  • Tipo di piattaforma: Web
  • URI di reindirizzamento: http://localhost:3000/auth/redirect
  • Segreto client: ********* (registrare questo valore da usare in un passaggio successivo: viene visualizzato una sola volta)

Creare il progetto

Usare lo strumento generatore di applicazioni Express per creare uno scheletro dell'applicazione.

  1. Installare prima il pacchettoexpress-generator:
    npm install -g express-generator
  1. Creare quindi uno scheletro dell'applicazione come indicato di seguito:
    express --view=hbs /ExpressWebApp && cd /ExpressWebApp
    npm install

Ora si dispone di una semplice app Web Express. La struttura di file e cartelle del progetto sarà simile alla struttura di cartelle seguente:

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

Installare la libreria di autenticazione

Individuare la radice della directory del progetto in un terminale e installare il pacchetto del nodo MSAL tramite npm.

    npm install --save @azure/msal-node

Installare altre dipendenze

L'esempio di app Web in questa esercitazione usa il pacchetto della sessione rapida per la gestione delle sessioni, il pacchetto dotenv per la lettura dei parametri di ambiente durante lo sviluppo e il pacchetto axios per effettuare chiamate di rete all'API Microsoft Graph. Installare questi pacchetti tramite npm:

    npm install --save express-session dotenv axios

Aggiungere i dettagli di registrazione dell'app

  1. Creare un file env.dev nella radice della cartella del progetto. Aggiungere quindi il codice seguente:
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"

Compilare questi dettagli con i valori ottenuti dal portale di registrazione delle app di Azure:

  • Enter_the_Cloud_Instance_Id_Here: Istanza cloud di Azure in cui è registrata l'applicazione.
    • Per il cloud di Azure principale (o globale), immettere https://login.microsoftonline.com/ (includere la barra finale avanti).
    • Peri cloud nazionali, ad esempio Cina, è possibile trovare i valori appropriati nella pagina Cloud nazionali.
  • Enter_the_Tenant_Info_here deve essere uno dei parametri seguenti:
    • Se l'applicazione supporta account in questa directory organizzativa, sostituire questo valore con l'ID tenant o il nome del tenant. Ad esempio: contoso.microsoft.com.
    • Se l'applicazione supporta account in qualsiasi directory organizzativa, sostituire questo valore con organizations.
    • Se l'applicazione supporta account in qualsiasi directory organizzativa e account Microsoft personali, sostituire questo valore con common.
    • Per limitare il supporto ai soli account Microsoft personali, sostituire questo valore con consumers.
  • L' Enter_the_Application_Id_HereID applicazione (client) dell'applicazione registrata.
  • Enter_the_Client_secret: sostituire questo valore con il segreto client creato in precedenza. Per generare una nuova chiave usare Certificati e segreti nelle impostazioni di registrazione dell'app nel portale di Azure.

Avviso

Qualsiasi segreto in testo non crittografato del codice sorgente aumenta il rischio di sicurezza. Questo articolo usa un segreto client in testo non crittografato solo per semplicità. Si consiglia di usare le credenziali del certificato, anziché i segreti client nelle applicazioni client riservate, in particolare quelle che si intende distribuire nell'ambiente di produzione.

  • Enter_the_Graph_Endpoint_Here: l'istanza cloud dell'API Microsoft Graph che verrà chiamata dall'app. Per il servizio API Microsoft Graph principale (globale), immettere https://graph.microsoft.com/ (includere la barra finale).
  • Enter_the_Express_Session_Secret_Here il segreto utilizzato per firmare il cookie di sessione Express. Scegliere una stringa casuale di caratteri con cui sostituire questa stringa, ad esempio il segreto client.
  1. Poi creare un file denominato authConfig.js nella radice del progetto per la lettura in questi parametri. Una volta creato, aggiungere qui il codice seguente:
/*
 * 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
};

Aggiungere il codice per l'accesso utente e l'acquisizione di token

  1. Creare una nuova cartella denominata authe qui aggiungere un nuovo file denominato AuthProvider.js. Questo conterrà la classe AuthProvider, che incapsula la logica di autenticazione necessaria tramite il nodo MSAL. Aggiungere qui il codice seguente:
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. Creare quindi un nuovo file denominato auth.js nella cartella routes e qui aggiungere il codice seguente:
/*
 * 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. Aggiornare la route index.js sostituendo il codice esistente con il frammento di codice seguente:
/*
 * 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. Aggiornare infine la route users.js sostituendo il codice esistente con il frammento di codice seguente:
/*
 * 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;

Aggiungere il codice per chiamare l'API Microsoft Graph

Creare un file denominato fetch.js nella radice del progetto e aggiungere il codice seguente:

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

Aggiungere viste per la visualizzazione dei dati

  1. Nella cartella viste aggiornare il file index.hbs sostituendo il codice esistente con il codice seguente:
<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. Sempre nella stessa cartella creare un altro file denominato id.hbs per visualizzare il contenuto del token ID dell'utente:
<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. Creare infine un altro file denominato profile.hbs per visualizzare il risultato della chiamata effettuata a 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>

Registrare i router e aggiungere la gestione dello stato

Nel file app.js nella radice della cartella del progetto registrare le route create in precedenza e aggiungere il supporto della sessione per tenere traccia dello stato di autenticazione usando il pacchetto della sessione rapida. Sostituire il codice esistente con il frammento di codice seguente:

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

Testare l'accesso e chiamare Microsoft Graph

La creazione dell'applicazione è stata completata ed ora è possibile testare le funzionalità dell'app.

  1. Avviare l'app console Node.js eseguendo il comando seguente dalla radice della cartella del progetto:
   npm start
  1. Aprire una finestra del browser e passare a http://localhost:3000. Verrà visualizzata una pagina iniziale:

Visualizzazione della pagina iniziale dell'app Web

  1. Selezionare il collegamento Accedi. Verrà visualizzata la schermata di accesso a Microsoft Entra:

Visualizzazione della schermata di accesso a Microsoft Entra

  1. Dopo aver immesso le credenziali, verrà visualizzata una schermata di consenso che chiede di approvare le autorizzazioni per l'app.

Visualizzazione della schermata di consenso di Microsoft Entra

  1. Dopo aver fornito il consenso, si verrà reindirizzati alla home page dell'applicazione.

Visualizzazione della pagina iniziale dell'app Web dopo l'accesso

  1. Selezionare il collegamento Visualizza token ID per visualizzare il contenuto del token ID dell'utente connesso.

Visualizzazione della schermata del token ID utente

  1. Tornare alla home page e selezionare il collegamento Acquisire un token di accesso e chiamare l’API Microsoft Graph. Dopo aver eseguito questa operazione, verrà visualizzata la risposta dell'endpoint di Microsoft Graph /me per l'utente connesso.

Visualizzazione della schermata delle chiamate a Graph

  1. Tornare alla home page e selezionare il collegamento Disconnetti. Verrà visualizzata la schermata di disconnessione da Microsoft Entra.

Visualizzazione della schermata di disconnessione di Microsoft Entra

Funzionamento dell'applicazione

In questa esercitazione è stata avviata un'istanza di un oggetto MSAL Node ConfidentialClientApplication trasmettendolo a un oggetto di configurazione (msalConfig) che contiene i parametri ottenuti dalla registrazione dell'app Microsoft Entra nel portale di Azure. L'app Web creata usa il protocollo OpenID Connect per eseguire l’accesso degli utenti e il Flusso del codice di autorizzazione OAuth 2.0 per ottenere i token di accesso.

Passaggi successivi

Per approfondire lo sviluppo di applicazioni Web Node.js & Express su Microsoft Identity Platform, vedere la serie di scenari in più parti: