Adquirir tokens no MSAL Node

Como o MSAL Node suporta várias concessões de código de autorização, existe suporte para diferentes APIs públicas por concessão e pelo respetivo pedido. Este artigo irá guiá-lo pelas diferentes APIs públicas disponíveis para cada fluxo e pelo tipo de pedido correspondente. É fortemente recomendado que implemente o fluxo de código de autorização para a sua aplicação.

Fluxo de Código de Autorização

APIs públicas

  • getAuthCodeUrl(): Esta API é a primeira etapa do authorization code grant para o MSAL Node. O pedido é do tipo AuthorizationUrlRequest. A aplicação recebe um URL que pode ser usado para gerar um authorization code. Este URL pode ser aberto num navegador à escolha, onde o utilizador pode introduzir as suas credenciais, e será redirecionado de volta para o redirectUri (registado durante o registo da aplicação) com um authorization code. O authorization code pode agora ser trocado por um token, seguindo o passo abaixo. Note que, se o fluxo de código de autorização estiver a ser feito para uma aplicação cliente pública, recomenda-se o PKCE .

  • acquireTokenByCode(): Esta API é a segunda etapa do authorization code grant para o MSAL Node. O pedido aqui construído deve ser do tipo AuthorizationCodeRequest. A aplicação transmitiu o authorization code recebido no passo acima e troca-o por um token. Não que, se estiver a ser feito um fluxo de código de autorização para uma aplicação cliente pública, o PKCE seja recomendado.


    const authCodeUrlParameters = {
        scopes: ["sample_scope"],
        redirectUri: "your_redirect_uri",
    };

    // get url to sign user in and consent to scopes needed for application
    cca.getAuthCodeUrl(authCodeUrlParameters).then((response) => {
        console.log(response);
    }).catch((error) => console.log(JSON.stringify(error)));

    const tokenRequest = {
        code: "authorization_code",
        redirectUri: "your_redirect_uri",
        scopes: ["sample_scope"],
    };

    // acquire a token by exchanging the code
    cca.acquireTokenByCode(tokenRequest).then((response) => {
        console.log("\nResponse: \n:", response);
    }).catch((error) => {
        console.log(error);
    });

Fluxo de Código do Dispositivo

APIs públicas

  • acquireTokenByDeviceCode(): Esta API permite à aplicação adquirir um token com concessão de Código do Dispositivo. O pedido é do tipo DeviceCodeRequest. Esta API adquire um token da autoridade usando o fluxo de código do dispositivo OAuth2.0. Este fluxo foi concebido para dispositivos que não têm acesso a um navegador ou apresentam restrições de entrada. O servidor de autorização emite um objeto DeviceCode com um código de verificação, um código do utilizador final e o URI de verificação do utilizador final. O objeto DeviceCode é fornecido através de um callback, e o utilizador final deve ser instruído a usar outro dispositivo para navegar até ao URI de verificação e introduzir as credenciais. Como o cliente não pode receber pedidos recebidos, interroga repetidamente o servidor de autorização até que o utilizador final complete a introdução das credenciais.
const msalConfig = {
    auth: {
        clientId: "your_client_id_here",
        authority: "your_authority_here",
    }
};

const pca = new msal.PublicClientApplication(msalConfig);

const deviceCodeRequest = {
    deviceCodeCallback: (response) => (console.log(response.message)),
    scopes: ["user.read"],
};

pca.acquireTokenByDeviceCode(deviceCodeRequest).then((response) => {
    console.log(JSON.stringify(response));
}).catch((error) => {
    console.log(JSON.stringify(error));
});

Fluxo de token de atualização

APIs públicas

  • acquireTokenByRefreshToken: Esta API adquire um token trocando o token de atualização fornecido por um novo conjunto de tokens. O pedido é do tipo RefreshTokenRequest. Nunca refresh token é devolvido ao utilizador numa resposta, mas pode ser acedido a partir da cache do utilizador. Recomenda-se que uses acquireTokenSilent() para cenários não interativos. Ao utilizar o acquireTokenSilent(), o MSAL trata automaticamente da cache e da atualização dos tokens.
const config = {
    auth: {
        clientId: "your_client_id_here",
        authority: "your_authority_here",
    }
};

const pca = new msal.PublicClientApplication(config);

const refreshTokenRequest = {
    refreshToken: "",
    scopes: ["user.read"],
};

pca.acquireTokenByRefreshToken(refreshTokenRequest).then((response) => {
    console.log(JSON.stringify(response));
}).catch((error) => {
    console.log(JSON.stringify(error));
});

Fluxo Silencioso

APIs públicas

  • acquireTokenSilent: Esta API adquire um token silenciosamente, caso o utilizador forneça cache ou quando cache é criada ao preceder esta chamada com qualquer outro fluxo interativo (por exemplo: fluxo de código de autorização). O pedido é do tipo SilentFlowRequest. O token é adquirido silenciosamente quando um utilizador especifica a conta para a qual o token é solicitado.
/**
 * Cache Plugin configuration
 */
const cachePath = "path_to_your_cache_file/msal_cache.json"; // Replace this string with the path to your valid cache file.

const readFromStorage = () => {
    return fs.readFile(cachePath, "utf-8");
};

const writeToStorage = (getMergedState) => {
    return readFromStorage().then(oldFile =>{
        const mergedState = getMergedState(oldFile);
        return fs.writeFile(cachePath, mergedState);
    })
};

const cachePlugin = {
    readFromStorage,
    writeToStorage
};

/**
 * Public Client Application Configuration
 */
const publicClientConfig = {
    auth: {
        clientId: "your_client_id_here",
        authority: "your_authority_here",
        redirectUri: "your_redirectUri_here",
    },
    cache: {
        cachePlugin
    },
};

/** Request Configuration */

const scopes = ["your_scopes"];

const authCodeUrlParameters = {
    scopes: scopes,
    redirectUri: "your_redirectUri_here",
};

const pca = new msal.PublicClientApplication(publicClientConfig);
const msalCacheManager = pca.getCacheManager();
let accounts;

pca.getAuthCodeUrl(authCodeUrlParameters)
    .then((response) => {
        console.log(response);
    }).catch((error) => console.log(JSON.stringify(error)));

const tokenRequest = {
    code: req.query.code,
    redirectUri: "http://localhost:3000/redirect",
    scopes: scopes,
};

pca.acquireTokenByCode(tokenRequest).then((response) => {
    console.log("\nResponse: \n:", response);
    return msalCacheManager.writeToPersistence();
}).catch((error) => {
    console.log(error);
});

// get Accounts
accounts = msalCacheManager.getAllAccounts();

// Build silent request
const silentRequest = {
    account: accounts[0], // You would filter accounts to get the account you want to get tokens for
    scopes: scopes,
};

// Acquire Token Silently to be used in MS Graph call
pca.acquireTokenSilent(silentRequest).then((response) => {
    console.log("\nSuccessful silent token acquisition:\nResponse: \n:", response);
    return msalCacheManager.writeToPersistence();
}).catch((error) => {
        console.log(error);
});

Fluxo de Credenciais do Cliente

APIs públicas

  • acquireTokenByClientCredential: Esta API adquire um token usando as credenciais confidenciais da aplicação cliente para autenticar (em vez de se fazer passar por um utilizador) ao chamar outro serviço web. Neste cenário, o cliente é tipicamente um serviço web de nível intermédio, um serviço daemon ou uma aplicação web back-end. Para um nível mais alto de garantia, a plataforma de identidade da Microsoft também permite que o serviço de chamada use um certificado (em vez de um segredo compartilhado) como credencial. O pedido é do tipo ClientCredentialRequest.

Usar segredos de forma segura

Segredos nunca devem ser codificados fixamente. O pacote dotenv npm pode ser usado para armazenar segredos num ficheiro .env (localizado na diretoria raiz do projeto) que devem ser incluídos no .gitignore para evitar uploads acidentais dos segredos.

import "dotenv/config"; // process.env now has the values defined in a .env file

const config = {
    auth: {
        clientId: "your_client_id_here",
        authority: "your_authority_here",
        clientSecret: process.env.clientSecret
    }
};

// Create msal application object
const cca = new msal.ConfidentialClientApplication(config);

// With client credentials flows permissions need to be granted in the portal by a tenant administrator.
// The scope is always in the format "<resource>/.default"
const clientCredentialRequest = {
    scopes: ["https://graph.microsoft.com/.default"], // replace with your resource
};

cca.acquireTokenByClientCredential(clientCredentialRequest).then((response) => {
    console.log("Response: ", response);
}).catch((error) => {
    console.log(JSON.stringify(error));
});

Em nome da Flow

  • acquireTokenOnBehalfOf: Esta API implementa o On Behalf Of Flow, que é usado quando uma aplicação invoca uma API de serviço/web, que por sua vez precisa de chamar outra API de serviço/web que utilize qualquer outro fluxo de autenticação (código do dispositivo, nome de utilizador/palavra-passe, etc). O token de acesso é adquirido inicialmente pela API web (por qualquer um dos fluxos da API web), e a API web pode então trocar esse token por outro token via OBO. O pedido é do tipo OnBehalfOfRequest

Por favor, consulte o exemplo do fluxo On Behalf Of para obter instruções de utilização: