Adquisición de tokens en el nodo MSAL

Dado que MSAL Node admite varias concesiones de código de autorización, hay compatibilidad con distintas API públicas por concesión y la solicitud correspondiente. Este artículo le guiará a través de las distintas API públicas disponibles para cada flujo y el tipo de solicitud correspondiente. Se recomienda encarecidamente implementar el flujo de código de autorización para la aplicación.

Flujo de código de autorización

API públicas

  • getAuthCodeUrl(): Esta API es el primer paso del authorization code grant para MSAL Node. La solicitud es del tipo AuthorizationUrlRequest. Se envía a la aplicación una dirección URL que se puede usar para generar un authorization code. Esta dirección URL se puede abrir en un explorador que prefiera, donde el usuario puede escribir sus credenciales y se redirigirá de nuevo a redirectUri (registrado durante el registro de la aplicación) con un authorization code. El authorization code ahora se puede canjear por un token siguiendo el siguiente paso. Tenga en cuenta que si se realiza el flujo de código de autorización para una aplicación cliente pública, se recomienda PKCE .

  • acquireTokenByCode(): Esta API es la segunda fase de authorization code grant para MSAL Node. La solicitud construida aquí debe ser del tipo AuthorizationCodeRequest. La aplicación transmitió el authorization code recibido como parte del paso anterior y lo intercambia por un token. Tenga en cuenta que, si el flujo de código de autorización se realiza para una aplicación cliente pública, se recomienda PKCE.


    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);
    });

Flujo de código de dispositivo

API públicas

  • acquireTokenByDeviceCode(): esta API permite a la aplicación adquirir un token con la concesión de código de dispositivo. La solicitud es del tipo DeviceCodeRequest. Esta API obtiene un token de la autoridad mediante el flujo de código de dispositivo de OAuth 2.0. Este flujo está diseñado para dispositivos que no tienen acceso a un explorador o tienen restricciones de entrada. El servidor de autorización emite un objeto DeviceCode con un código de verificación, un código de usuario final y el URI de verificación del usuario final. El objeto DeviceCode se proporciona a través de una función de devolución de llamada, y se le debe indicar al usuario final que use otro dispositivo para acceder al URI de verificación e introducir sus credenciales. Dado que el cliente no puede recibir solicitudes entrantes, sondea el servidor de autorización repetidamente hasta que el usuario final completa la entrada de las credenciales.
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));
});

Actualizar flujo de tokens

API públicas

  • acquireTokenByRefreshToken: esta API adquiere un token intercambiando el token de actualización proporcionado para un nuevo conjunto de tokens. La solicitud es del tipo RefreshTokenRequest. Nunca se devuelve refresh token al usuario en una respuesta, pero puede obtenerse de la caché del usuario. Se recomienda usar acquireTokenSilent() para escenarios no interactivos. Al usar acquireTokenSilent(), MSAL controlará automáticamente el almacenamiento en caché y la actualización de 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));
});

Flujo silencioso

API públicas

  • acquireTokenSilent: esta API adquiere un token de forma silenciosa, en caso de que el usuario proporcione la memoria caché o cuando la memoria caché se cree antes de esta llamada con cualquier otro flujo interactivo (por ejemplo, flujo de código de autorización). La solicitud es del tipo SilentFlowRequest. El token se obtiene de forma silenciosa cuando un usuario especifica la cuenta para la que se solicita el token.
/**
 * 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);
});

Flujo de credenciales de cliente

API públicas

  • acquireTokenByClientCredential: esta API adquiere un token mediante las credenciales de la aplicación cliente confidencial para autenticarse (en lugar de suplantar a un usuario) al llamar a otro servicio web. En este escenario, el cliente suele ser un servicio web de nivel intermedio, un servicio en segundo plano o una aplicación web del servidor. Para conseguir un mayor nivel de control, la plataforma de identidad de Microsoft también permite que el servicio que realiza la llamada use un certificado (en lugar de un secreto compartido) como credencial. La solicitud es del tipo ClientCredentialRequest.

Uso de secretos de forma segura

Los secretos nunca se deben codificar de forma dura. El paquete npm de dotenv se puede usar para almacenar secretos en un archivo .env (ubicado en el directorio raíz del proyecto) que se debe incluir en .gitignore para evitar cargas accidentales de los secretos.

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));
});

En nombre de Flow

  • acquireTokenOnBehalfOf: esta API implementa el flujo On Behalf Of, que se usa cuando una aplicación invoca un servicio o una API web, que a su vez necesita llamar a otro servicio o API web que utilice cualquier otro flujo de autenticación (código de dispositivo, nombre de usuario y contraseña, etc.). La API web adquiere inicialmente el token de acceso (por cualquiera de los flujos de API web) y la API web puede intercambiar este token para otro token a través de OBO. La solicitud es del tipo OnBehalfOfRequest

Consulte el ejemplo del flujo On Behalf Of para ver las instrucciones de uso: