Получение токенов в MSAL Node

Поскольку MSAL Node поддерживает различные варианты предоставления кода авторизации, для каждого такого варианта и соответствующего запроса доступны разные публичные API. В этой статье описаны различные общедоступные API, доступные для каждого потока и соответствующего типа запроса. Настоятельно рекомендуется реализовать поток кода авторизации для приложения.

Поток кода авторизации

Общедоступные API

  • getAuthCodeUrl(): Этот API является первым этапом authorization code grant для MSAL Node. Запрос имеет тип AuthorizationUrlRequest. Приложение отправляет URL-адрес, который можно использовать для создания authorization code. Этот URL-адрес можно открыть в предпочитаемом браузере, где пользователь может ввести свои учетные данные, после чего он будет перенаправлен обратно в redirectUri (зарегистрированный при регистрации приложения) с authorization code. Теперь authorization code можно обменять на token, выполнив следующий шаг. Обратите внимание, что если поток кода авторизации выполняется для общедоступного клиентского приложения, рекомендуется использовать PKCE .

  • acquireTokenByCode(): этот API является вторым этапом authorization code grant для MSAL Node. Созданный здесь запрос должен иметь тип AuthorizationCodeRequest. Приложение передало authorization code, полученный на предыдущем шаге, и обменяло его на token. Обратите внимание, что, если поток кода авторизации используется для общедоступного клиентского приложения, рекомендуется использовать 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);
    });

Поток кода устройства

Общедоступные API

  • acquireTokenByDeviceCode(): этот API позволяет приложению получить маркер с предоставлением кода устройства. Запрос имеет тип DeviceCodeRequest. Этот API получает token от центра авторизации с использованием потока кода устройства OAuth 2.0. Этот поток предназначен для устройств, которые не имеют доступа к браузеру или имеют ограничения ввода. Сервер авторизации выдает объект DeviceCode с кодом проверки, кодом конечного пользователя и универсальным кодом проверки пользователя. Объект DeviceCode предоставляется с помощью обратного вызова, а конечный пользователь должен использовать другое устройство для перехода к URI проверки для ввода учетных данных. Так как клиент не может получать входящие запросы, он повторно опрашивает сервер авторизации до тех пор, пока конечный пользователь не завершит ввод учетных данных.
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));
});

Поток маркеров обновления

Общедоступные API

  • acquireTokenByRefreshToken: Этот API получает токен, обменивая предоставленный токен обновления на новый набор токенов. Запрос имеет тип RefreshTokenRequest. refresh token никогда не возвращается пользователю в ответе, но доступ к нему можно получить из пользовательского кэша. Рекомендуется использовать acquireTokenSilent() для неинтерактивных сценариев. При использовании acquireTokenSilent() MSAL будет автоматически управлять кэшированием и обновлением токенов.
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));
});

Тихий поток

Общедоступные API

  • acquireTokenSilent: этот API получает токен без взаимодействия с пользователем, если кэш предоставлен пользователем или был создан до этого вызова с помощью любого другого интерактивного потока (например, потока авторизационного кода). Запрос имеет тип SilentFlowRequest. 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);
});

Поток учетных данных клиента

Общедоступные API

  • acquireTokenByClientCredential: этот API получает маркер, используя учетные данные конфиденциального клиентского приложения для проверки подлинности (вместо олицетворения пользователя) при вызове другой веб-службы. В этом сценарии клиент обычно является веб-службой среднего уровня, управляющей службой или серверным веб-приложением. Для большей надежности платформа удостоверений Майкрософт также позволяет вызывающей службе использовать в качестве учетных данных сертификат (вместо общего секрета). Запрос имеет тип ClientCredentialRequest.

Безопасное использование секретов

Секреты никогда не должны быть жестко закодированы. Пакет dotenv npm можно использовать для хранения секретов в env-файле (расположенном в корневом каталоге проекта), который должен быть включен в gitignore, чтобы предотвратить случайные отправки секретов.

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

От имени Flow

  • acquireTokenOnBehalfOf: этот API реализует поток On-Behalf-Of, который используется, когда приложение вызывает службу или веб-API, а та, в свою очередь, должна вызвать другую службу или веб-API, использующие любой другой поток аутентификации (код устройства, имя пользователя/пароль и т. д.). Маркер доступа изначально приобретается веб-API (любым из потоков веб-API), а затем веб-API может обмениваться этим маркером на другой маркер через OBO. Запрос имеет тип OnBehalfOfRequest

Ознакомьтесь с примером потока On Behalf Of и инструкциями по его использованию: