Compartilhar via


Habilitar a autenticação em seu próprio aplicativo Web node usando o Azure Active Directory B2C

Importante

A partir de 1º de maio de 2025, o Azure AD B2C não estará mais disponível para compra para novos clientes. Saiba mais em nossas perguntas frequentes.

Neste artigo, você aprenderá a adicionar a autenticação do Azure AD B2C (Azure Active Directory B2C) em seu próprio aplicativo Web Node.js. Você permitirá que os usuários entrem, saiam, atualizem o perfil e redefinam a senha usando fluxos de usuário do Azure AD B2C. Este artigo usa a MSAL (biblioteca de autenticação da Microsoft) para o nó para simplificar a adição de autenticação ao seu aplicativo Web do nó.

O objetivo deste artigo é substituir o aplicativo de exemplo usado em Configurar a autenticação em um aplicativo Web Node.js de exemplo usando o Azure AD B2C por seu próprio aplicativo Web Node.js.

Este artigo usa Node.js e Express para criar um aplicativo Web Node.js básico. As exibições do aplicativo usam Handlebars.

Pré-requisitos

Etapa 1: Criar um projeto Node

Crie uma pasta para hospedar seu aplicativo do Node, como active-directory-b2c-msal-node-sign-in-sign-out-webapp.

  1. No terminal, altere o diretório para a pasta do aplicativo Node, como cd active-directory-b2c-msal-node-sign-in-sign-out-webappe execute npm init -y. Esse comando cria um arquivo package.json padrão para seu projeto Node.js.

  2. Execute npm install express no seu terminal. Esse comando instala a estrutura do Express.

  3. Crie mais arquivos e pastas para obter a seguinte estrutura de projeto:

    active-directory-b2c-msal-node-sign-in-sign-out-webapp/
    ├── index.js
    └── package.json
    └── .env
    └── views/
        └── layouts/
            └── main.hbs
        └── signin.hbs
    

A views pasta contém arquivos handlebars para a interface do usuário do aplicativo.

Etapa 2: Instalar dependências do aplicativo

No terminal, instale os pacotes dotenv, express-handlebars, express-session e @azure/msal-node executando os seguintes comandos:

npm install dotenv
npm install express-handlebars
npm install express-session
npm install @azure/msal-node

Etapa 3: Criar componentes da interface do usuário do aplicativo

main.hbs No ficheiro, adicione o seguinte código:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
    <title>Tutorial | Authenticate users with MSAL for B2C</title>

    <!-- adding Bootstrap 4 for UI components  -->
    <!-- CSS only -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    <link rel="SHORTCUT ICON" href="https://c.s-microsoft.com/favicon.ico?v2" type="image/x-icon">
  </head>
  <body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
      <a class="navbar-brand" href="/">Microsoft Identity Platform</a>
        {{#if showSignInButton}}
            <div class="ml-auto">
                <a type="button" id="SignIn" class="btn btn-secondary" href="/signin" aria-haspopup="true" aria-expanded="false">
                    Sign in
                </a>
            </div>
        {{else}}
              <div class="ml-auto">
                  <a type="button" id="EditProfile" class="btn btn-warning" href="/profile" aria-haspopup="true" aria-expanded="false">
                      Edit profile
                  </a>
                  <a type="button" id="PasswordReset" class="btn btn-warning" href="/password" aria-haspopup="true" aria-expanded="false">
                      Reset password
                  </a>
              </div>

                <p class="navbar-brand d-flex ms-auto">Hi {{givenName}}</p>

                <a class="navbar-brand d-flex ms-auto" href="/signout">Sign out</a>
        {{/if}}
    </nav>
    <br>
    <h5 class="card-header text-center">MSAL Node Confidential Client application with Auth Code Flow</h5>
    <br>
    <div class="row" style="margin:auto" >
      {{{body}}}
    </div>
    <br>
    <br>
  </body>
</html>

O arquivo main.hbs está na pasta layout. Ele deve conter qualquer código HTML necessário em todo o aplicativo. Qualquer interface que muda de uma exibição para outra, como em signin.hbs, é colocada no marcador de posição mostrado como {{{body}}}.

O main.hbs arquivo implementa a interface do usuário criada com a estrutura do CSS do Bootstrap 5. Você verá os componentes Editar senha, Redefinir senha e Sair da interface do usuário (botões) quando conectado. Você verá Entrar quando estiver desconectado. Esse comportamento é controlado pela variável Booleana showSignInButton, que o servidor de aplicativos envia.

signin.hbs No ficheiro, adicione o seguinte código:

<div class="col-md-3" style="margin:auto">
  <div class="card text-center">
    <div class="card-body">
      {{#if showSignInButton}}
          <h5 class="card-title">Please sign-in to acquire an ID token</h5>
      {{else}}
           <h5 class="card-title">You have signed in</h5>
      {{/if}}
    </div>

    <div class="card-body">
      {{#if message}}
          <h5 class="card-title text-danger">{{message}}</h5>
      {{/if}}
    </div>
  </div>
</div>

Etapa 4: Configurar o servidor Web e o cliente MSAL

  1. .env No arquivo, adicione o código a seguir e atualize-o conforme explicado em Configurar o aplicativo Web de exemplo.

    #HTTP port
    SERVER_PORT=3000
    #web apps client ID
    APP_CLIENT_ID=<You app client ID here>
    #session secret
    SESSION_SECRET=sessionSecretHere
    #web app client secret
    APP_CLIENT_SECRET=<Your app client secret here>
    #B2C sign up and sign in user flow/policy authority
    SIGN_UP_SIGN_IN_POLICY_AUTHORITY=https://<your-tenant-name>.b2clogin.com/<your-tenant-name>.onmicrosoft.com/<sign-in-sign-up-user-flow-name>
    #B2C password reset user flow/policy authority
    RESET_PASSWORD_POLICY_AUTHORITY=https://<your-tenant-name>.b2clogin.com/<your-tenant-name>.onmicrosoft.com/<reset-password-user-flow-name>
    #B2C edit profile user flow/policy authority
    EDIT_PROFILE_POLICY_AUTHORITY=https://<your-tenant-name>.b2clogin.com/<your-tenant-name>.onmicrosoft.com/<profile-edit-user-flow-name>
    #B2C authority domain
    AUTHORITY_DOMAIN=https://<your-tenant-name>.b2clogin.com
    #client redirect url
    APP_REDIRECT_URI=http://localhost:3000/redirect
    #Logout endpoint 
    LOGOUT_ENDPOINT=https://<your-tenant-name>.b2clogin.com/<your-tenant-name>.onmicrosoft.com/<sign-in-sign-up-user-flow-name>/oauth2/v2.0/logout?post_logout_redirect_uri=http://localhost:3000
    
  2. No seu arquivo index.js, adicione o seguinte código para usar as dependências do seu aplicativo.

    require('dotenv').config();
    const express = require('express');
    const session = require('express-session');
    const {engine}  = require('express-handlebars');
    const msal = require('@azure/msal-node');
    
  3. index.js No arquivo, adicione o seguinte código para configurar a biblioteca de autenticação:

    /**
     * Confidential Client Application Configuration
     */
     const confidentialClientConfig = {
        auth: {
            clientId: process.env.APP_CLIENT_ID, 
            authority: process.env.SIGN_UP_SIGN_IN_POLICY_AUTHORITY, 
            clientSecret: process.env.APP_CLIENT_SECRET,
            knownAuthorities: [process.env.AUTHORITY_DOMAIN], //This must be an array
            redirectUri: process.env.APP_REDIRECT_URI,
            validateAuthority: false
        },
        system: {
            loggerOptions: {
                loggerCallback(loglevel, message, containsPii) {
                    console.log(message);
                },
                piiLoggingEnabled: false,
                logLevel: msal.LogLevel.Verbose,
            }
        }
    };
    
    // Initialize MSAL Node
    const confidentialClientApplication = new msal.ConfidentialClientApplication(confidentialClientConfig);
    

    confidentialClientConfig é o objeto de configuração MSAL usado para se conectar aos pontos de extremidade de autenticação do locatário do Azure AD B2C.

  4. Para adicionar mais variáveis globais ao index.js arquivo, adicione o seguinte código:

    /**
     * The MSAL.js library allows you to pass your custom state as state parameter in the Request object
     * By default, MSAL.js passes a randomly generated unique state parameter value in the authentication requests.
     * 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.
     * For more information, visit: https://docs.microsoft.com/azure/active-directory/develop/msal-js-pass-custom-state-authentication-request
     * In this scenario, the states also serve to show the action that was requested of B2C since only one redirect URL is possible. 
     */
    
    const APP_STATES = {
        LOGIN: 'login',
        LOGOUT: 'logout',
        PASSWORD_RESET: 'password_reset',
        EDIT_PROFILE : 'update_profile'
    }
    
    
    /** 
     * Request Configuration
     * We manipulate these two request objects below 
     * to acquire a token with the appropriate claims.
     */
     const authCodeRequest = {
        redirectUri: confidentialClientConfig.auth.redirectUri,
    };
    
    const tokenRequest = {
        redirectUri: confidentialClientConfig.auth.redirectUri,
    };
    
    /**
     * Using express-session middleware. Be sure to familiarize yourself with available options
     * and set them as desired. Visit: https://www.npmjs.com/package/express-session
     */
     const sessionConfig = {
        secret: process.env.SESSION_SECRET,
        resave: false,
        saveUninitialized: false,
        cookie: {
            secure: false, // set this to true on production
        }
    }
    
    1. APP_STATES: usado para diferenciar as respostas recebidas do Azure AD B2C marcando solicitações. Há apenas um URI de redirecionamento para qualquer número de solicitações enviadas ao Azure AD B2C.
    2. authCodeRequest: o objeto de configuração usado para recuperar o código de autorização.
    3. tokenRequest: o objeto de configuração usado para adquirir um token por código de autorização.
    4. sessionConfig: o objeto de configuração da sessão Express.
  5. Para definir o mecanismo de modelo de exibição e a configuração de sessão do Express, adicione o seguinte código no arquivo index.js.

     
    //Create an express instance
    const app = express();
    
    //Set handlebars as your view engine
    app.engine('.hbs', engine({extname: '.hbs'}));
    app.set('view engine', '.hbs');
    app.set("views", "./views");
    
    //usse session configuration 
    app.use(session(sessionConfig));
    

Etapa 5: Adicionar rotas expressas

Antes de adicionar a rota do aplicativo, adicione a lógica que recupera a URL do código de autorização, que é a primeira etapa do fluxo de concessão de código de autorização. index.js No ficheiro, adicione o seguinte código:


/**
 * This method is used to generate an auth code request
 * @param {string} authority: the authority to request the auth code from 
 * @param {array} scopes: scopes to request the auth code for 
 * @param {string} state: state of the application
 * @param {Object} res: express middleware response object
 */
 const getAuthCode = (authority, scopes, state, res) => {

    // prepare the request
    console.log("Fetching Authorization code")
    authCodeRequest.authority = authority;
    authCodeRequest.scopes = scopes;
    authCodeRequest.state = state;

    //Each time you fetch Authorization code, update the relevant authority in the tokenRequest configuration
    tokenRequest.authority = authority;

    // request an authorization code to exchange for a token
    return confidentialClientApplication.getAuthCodeUrl(authCodeRequest)
        .then((response) => {
            console.log("\nAuthCodeURL: \n" + response);
            //redirect to the auth code URL/send code to 
            res.redirect(response);
        })
        .catch((error) => {
            res.status(500).send(error);
        });
}

O authCodeRequest objeto tem as propriedades redirectUri, authoritye scopesstate. O objeto é passado para o getAuthCodeUrl método como um parâmetro.

index.js No ficheiro, adicione o seguinte código:

 app.get('/', (req, res) => {
    res.render('signin', { showSignInButton: true });
});

app.get('/signin',(req, res)=>{
        //Initiate a Auth Code Flow >> for sign in
        //no scopes passed. openid, profile and offline_access will be used by default.
        getAuthCode(process.env.SIGN_UP_SIGN_IN_POLICY_AUTHORITY, [], APP_STATES.LOGIN, res);
});

/**
 * Change password end point
*/
app.get('/password',(req, res)=>{
    getAuthCode(process.env.RESET_PASSWORD_POLICY_AUTHORITY, [], APP_STATES.PASSWORD_RESET, res); 
});

/**
 * Edit profile end point
*/
app.get('/profile',(req, res)=>{
    getAuthCode(process.env.EDIT_PROFILE_POLICY_AUTHORITY, [], APP_STATES.EDIT_PROFILE, res); 
});

/**
 * Sign out end point
*/
app.get('/signout',async (req, res)=>{    
    logoutUri = process.env.LOGOUT_ENDPOINT;
    req.session.destroy(() => {
        //When session destruction succeeds, notify B2C service using the logout uri.
        res.redirect(logoutUri);
    });
});

app.get('/redirect',(req, res)=>{
    
    //determine the reason why the request was sent by checking the state
    if (req.query.state === APP_STATES.LOGIN) {
        //prepare the request for authentication        
        tokenRequest.code = req.query.code;
        confidentialClientApplication.acquireTokenByCode(tokenRequest).then((response)=>{
        
        req.session.sessionParams = {user: response.account, idToken: response.idToken};
        console.log("\nAuthToken: \n" + JSON.stringify(response));
        res.render('signin',{showSignInButton: false, givenName: response.account.idTokenClaims.given_name});
        }).catch((error)=>{
            console.log("\nErrorAtLogin: \n" + error);
        });
    }else if (req.query.state === APP_STATES.PASSWORD_RESET) {
        //If the query string has a error param
        if (req.query.error) {
            //and if the error_description contains AADB2C90091 error code
            //Means user selected the Cancel button on the password reset experience 
            if (JSON.stringify(req.query.error_description).includes('AADB2C90091')) {
                //Send the user home with some message
                //But always check if your session still exists
                res.render('signin', {showSignInButton: false, givenName: req.session.sessionParams.user.idTokenClaims.given_name, message: 'User has cancelled the operation'});
            }
        }else{
            
            res.render('signin', {showSignInButton: false, givenName: req.session.sessionParams.user.idTokenClaims.given_name});
        }        
        
    }else if (req.query.state === APP_STATES.EDIT_PROFILE){
    
        tokenRequest.scopes = [];
        tokenRequest.code = req.query.code;
        
        //Request token with claims, including the name that was updated.
        confidentialClientApplication.acquireTokenByCode(tokenRequest).then((response)=>{
            req.session.sessionParams = {user: response.account, idToken: response.idToken};
            console.log("\AuthToken: \n" + JSON.stringify(response));
            res.render('signin',{showSignInButton: false, givenName: response.account.idTokenClaims.given_name});
        }).catch((error)=>{
            //Handle error
        });
    }else{
        res.status(500).send('We do not recognize this response!');
    }

});

As rotas expressas são:

  • /:
    • É usado para acessar o aplicativo web.
    • Renderiza a página signin.
  • /signin:
    • Ele é usado quando você faz login.
    • Ele chama o método getAuthCode() e passa authority para a política/fluxo de usuário de Entrar e inscrever-se, APP_STATES.LOGIN, e uma matriz scopes vazia para ele.
    • Se necessário, ele causa um desafio para você inserir suas credenciais. Se você não tiver uma conta, ela solicitará que você se inscreva.
    • A resposta final resultante dessa rota inclui um código de autorização do Azure AD B2C, que é enviado de volta para a rota /redirect.
  • /password:
    • Ele é usado quando você redefine uma senha.
    • Ele chama o método getAuthCode() e passa authority para a política/fluxo de usuário de Redefinição de senha, APP_STATES.PASSWORD_RESET, e uma matriz scopes vazia para ele.
    • Ele permite que você altere sua senha usando a experiência de redefinição de senha ou pode cancelar a operação.
    • A resposta final resultante dessa rota inclui um código de autorização do Azure AD B2C, que é enviado de volta para a rota /redirect. Se você cancelar a operação, um erro será postado de volta.
  • /profile:
    • Ele é usado quando você atualiza seu perfil.
    • Ele chama o método getAuthCode() e passa authority para a política/fluxo de usuário de Edição de perfil, APP_STATES.EDIT_PROFILE, e uma matriz scopes vazia para ele.
    • Ele permite que você atualize seu perfil e use a experiência de edição de perfil.
    • A resposta final resultante dessa rota inclui um código de autorização do Azure AD B2C, que é enviado de volta para a rota /redirect.
  • /signout:
    • Ele é usado quando você sair do serviço.
    • O aplicativo web limpa a sessão e faz uma chamada HTTP para o endpoint de logout do Azure AD B2C.
  • /redirect:
    • É a rota definida como URI de Redirecionamento para o aplicativo web no portal do Azure.
    • Ele usa o state parâmetro de consulta na solicitação do Azure AD B2C para diferenciar as solicitações feitas do aplicativo Web. Ele lida com todos os redirecionamentos Azure AD B2C, exceto a saída.
    • Se o estado do aplicativo for APP_STATES.LOGIN, o código de autorização adquirido será usado para recuperar um token por meio do acquireTokenByCode() método. Esse token inclui idToken e idTokenClaims, que são usados para identificação do usuário.
    • Se o estado do aplicativo estiver APP_STATES.PASSWORD_RESET, ele manipulará qualquer erro, como user cancelled the operation. OAADB2C90091 código de erro identifica esse erro. Caso contrário, ele decidirá a próxima experiência do usuário.
    • Se o estado do aplicativo estiver APP_STATES.EDIT_PROFILE, ele usará o código de autorização para adquirir um token. O token contém idTokenClaims, que inclui as novas alterações.

Etapa 6: Iniciar o servidor Node

Para iniciar o servidor Node, adicione o seguinte código no arquivo index.js:

app.listen(process.env.SERVER_PORT, () => {
    console.log(`Msal Node Auth Code Sample app listening on port !` + process.env.SERVER_PORT);
});

Depois de fazer todas as alterações necessárias no index.js arquivo, ela deverá ser semelhante ao seguinte arquivo:

/*
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License.
 */
 //<ms_docref_use_app_dependencies>
require('dotenv').config();
const express = require('express');
const session = require('express-session');
const {engine}  = require('express-handlebars');
const msal = require('@azure/msal-node');
//</ms_docref_use_app_dependencies>

//<ms_docref_configure_msal>
/**
 * Confidential Client Application Configuration
 */
 const confidentialClientConfig = {
    auth: {
        clientId: process.env.APP_CLIENT_ID, 
        authority: process.env.SIGN_UP_SIGN_IN_POLICY_AUTHORITY, 
        clientSecret: process.env.APP_CLIENT_SECRET,
        knownAuthorities: [process.env.AUTHORITY_DOMAIN], //This must be an array
        redirectUri: process.env.APP_REDIRECT_URI,
        validateAuthority: false
    },
    system: {
        loggerOptions: {
            loggerCallback(loglevel, message, containsPii) {
                console.log(message);
            },
            piiLoggingEnabled: false,
            logLevel: msal.LogLevel.Verbose,
        }
    }
};

// Initialize MSAL Node
const confidentialClientApplication = new msal.ConfidentialClientApplication(confidentialClientConfig);
//</ms_docref_configure_msal>

//<ms_docref_global_variable>
/**
 * The MSAL.js library allows you to pass your custom state as state parameter in the Request object
 * By default, MSAL.js passes a randomly generated unique state parameter value in the authentication requests.
 * 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.
 * For more information, visit: https://docs.microsoft.com/azure/active-directory/develop/msal-js-pass-custom-state-authentication-request
 * In this scenario, the states also serve to show the action that was requested of B2C since only one redirect URL is possible. 
 */

const APP_STATES = {
    LOGIN: 'login',
    LOGOUT: 'logout',
    PASSWORD_RESET: 'password_reset',
    EDIT_PROFILE : 'update_profile'
}


/** 
 * Request Configuration
 * We manipulate these two request objects below 
 * to acquire a token with the appropriate claims.
 */
 const authCodeRequest = {
    redirectUri: confidentialClientConfig.auth.redirectUri,
};

const tokenRequest = {
    redirectUri: confidentialClientConfig.auth.redirectUri,
};

/**
 * Using express-session middleware. Be sure to familiarize yourself with available options
 * and set them as desired. Visit: https://www.npmjs.com/package/express-session
 */
 const sessionConfig = {
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    cookie: {
        secure: false, // set this to true on production
    }
}

//</ms_docref_global_variable>

//<ms_docref_view_tepmplate_engine>
 
//Create an express instance
const app = express();

//Set handlebars as your view engine
app.engine('.hbs', engine({extname: '.hbs'}));
app.set('view engine', '.hbs');
app.set("views", "./views");

//usse session configuration 
app.use(session(sessionConfig));

//</ms_docref_view_tepmplate_engine>

//<ms_docref_authorization_code_url>

/**
 * This method is used to generate an auth code request
 * @param {string} authority: the authority to request the auth code from 
 * @param {array} scopes: scopes to request the auth code for 
 * @param {string} state: state of the application
 * @param {Object} res: express middleware response object
 */
 const getAuthCode = (authority, scopes, state, res) => {

    // prepare the request
    console.log("Fetching Authorization code")
    authCodeRequest.authority = authority;
    authCodeRequest.scopes = scopes;
    authCodeRequest.state = state;

    //Each time you fetch Authorization code, update the relevant authority in the tokenRequest configuration
    tokenRequest.authority = authority;

    // request an authorization code to exchange for a token
    return confidentialClientApplication.getAuthCodeUrl(authCodeRequest)
        .then((response) => {
            console.log("\nAuthCodeURL: \n" + response);
            //redirect to the auth code URL/send code to 
            res.redirect(response);
        })
        .catch((error) => {
            res.status(500).send(error);
        });
}
 
 //</ms_docref_authorization_code_url>

 
 //<ms_docref_app_endpoints>
 app.get('/', (req, res) => {
    res.render('signin', { showSignInButton: true });
});

app.get('/signin',(req, res)=>{
        //Initiate a Auth Code Flow >> for sign in
        //no scopes passed. openid, profile and offline_access will be used by default.
        getAuthCode(process.env.SIGN_UP_SIGN_IN_POLICY_AUTHORITY, [], APP_STATES.LOGIN, res);
});

/**
 * Change password end point
*/
app.get('/password',(req, res)=>{
    getAuthCode(process.env.RESET_PASSWORD_POLICY_AUTHORITY, [], APP_STATES.PASSWORD_RESET, res); 
});

/**
 * Edit profile end point
*/
app.get('/profile',(req, res)=>{
    getAuthCode(process.env.EDIT_PROFILE_POLICY_AUTHORITY, [], APP_STATES.EDIT_PROFILE, res); 
});

/**
 * Sign out end point
*/
app.get('/signout',async (req, res)=>{    
    logoutUri = process.env.LOGOUT_ENDPOINT;
    req.session.destroy(() => {
        //When session destruction succeeds, notify B2C service using the logout uri.
        res.redirect(logoutUri);
    });
});

app.get('/redirect',(req, res)=>{
    
    //determine the reason why the request was sent by checking the state
    if (req.query.state === APP_STATES.LOGIN) {
        //prepare the request for authentication        
        tokenRequest.code = req.query.code;
        confidentialClientApplication.acquireTokenByCode(tokenRequest).then((response)=>{
        
        req.session.sessionParams = {user: response.account, idToken: response.idToken};
        console.log("\nAuthToken: \n" + JSON.stringify(response));
        res.render('signin',{showSignInButton: false, givenName: response.account.idTokenClaims.given_name});
        }).catch((error)=>{
            console.log("\nErrorAtLogin: \n" + error);
        });
    }else if (req.query.state === APP_STATES.PASSWORD_RESET) {
        //If the query string has a error param
        if (req.query.error) {
            //and if the error_description contains AADB2C90091 error code
            //Means user selected the Cancel button on the password reset experience 
            if (JSON.stringify(req.query.error_description).includes('AADB2C90091')) {
                //Send the user home with some message
                //But always check if your session still exists
                res.render('signin', {showSignInButton: false, givenName: req.session.sessionParams.user.idTokenClaims.given_name, message: 'User has cancelled the operation'});
            }
        }else{
            
            res.render('signin', {showSignInButton: false, givenName: req.session.sessionParams.user.idTokenClaims.given_name});
        }        
        
    }else if (req.query.state === APP_STATES.EDIT_PROFILE){
    
        tokenRequest.scopes = [];
        tokenRequest.code = req.query.code;
        
        //Request token with claims, including the name that was updated.
        confidentialClientApplication.acquireTokenByCode(tokenRequest).then((response)=>{
            req.session.sessionParams = {user: response.account, idToken: response.idToken};
            console.log("\AuthToken: \n" + JSON.stringify(response));
            res.render('signin',{showSignInButton: false, givenName: response.account.idTokenClaims.given_name});
        }).catch((error)=>{
            //Handle error
        });
    }else{
        res.status(500).send('We do not recognize this response!');
    }

});

 //</ms_docref_app_endpoints>
//start app server to listen on set port
 //<ms_docref_start_node_server>
app.listen(process.env.SERVER_PORT, () => {
    console.log(`Msal Node Auth Code Sample app listening on port !` + process.env.SERVER_PORT);
});
//</ms_docref_start_node_server>

Etapa 7: Executar seu aplicativo Web

Siga as etapas em Executar seu aplicativo Web para testar seu aplicativo Web Node.js.

Próximas etapas