Uzyskiwanie tokenów w MSAL Node

Ponieważ biblioteka MSAL Node obsługuje różne przepływy kodu autoryzacyjnego, udostępnia różne publiczne interfejsy API dla każdego przepływu i odpowiadającego mu żądania. W tym artykule przedstawiono różne publiczne interfejsy API dostępne dla każdego przepływu i odpowiadający mu typ żądania. Zdecydowanie zaleca się zaimplementowanie przepływu kodu autoryzacji dla aplikacji.

Przepływ kodu autoryzacji

Publiczne interfejsy API

  • getAuthCodeUrl(): to API jest pierwszym etapem authorization code grant dla MSAL Node. Żądanie jest typu AuthorizationUrlRequest. Aplikacja jest wysyłana pod adres URL, którego można użyć do wygenerowania elementu authorization code. Ten adres URL można otworzyć w wybranej przeglądarce, gdzie użytkownik może wprowadzić swoje poświadczenia, po czym zostanie przekierowany z powrotem do redirectUri (zarejestrowanego podczas rejestracji aplikacji) z użyciem authorization code. Teraz można wymienić authorization code na token, wykonując następujący krok. Należy pamiętać, że jeśli przepływ kodu autoryzacji jest wykonywany dla publicznej aplikacji klienckiej, zaleca się PKCE .

  • acquireTokenByCode(): To API jest drugim etapem procesu authorization code grant w bibliotece MSAL Node. Żądanie skonstruowane w tym miejscu powinno mieć typ AuthorizationCodeRequest. Aplikacja przekazała authorization code otrzymany w ramach powyższego kroku i wymieniła go na token. Nie, jeśli przepływ kodu autoryzacji jest wykonywany dla publicznej aplikacji klienckiej, zaleca się 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);
    });

Przepływ kodu urządzenia

Publiczne interfejsy API

  • acquireTokenByDeviceCode(): ten interfejs API umożliwia aplikacji uzyskanie tokenu z udzielaniem kodu urządzenia. Żądanie jest typu DeviceCodeRequest. Ten interfejs API uzyskuje element token od serwera autoryzacji przy użyciu przepływu kodu urządzenia w OAuth 2.0. Ten przepływ jest przeznaczony dla urządzeń, które nie mają dostępu do przeglądarki lub mają ograniczenia wejściowe. Serwer autoryzacji wystawia obiekt DeviceCode z kodem weryfikacyjnym, kodem użytkownika końcowego i identyfikatorem URI weryfikacji użytkownika końcowego. Obiekt DeviceCode jest przekazywany w wywołaniu zwrotnym, a użytkownik końcowy powinien otrzymać instrukcję, aby użyć innego urządzenia do przejścia do URI weryfikacyjnego i wprowadzenia poświadczeń. Ponieważ klient nie może odbierać żądań przychodzących, wielokrotnie odpytuje serwer autoryzacji, dopóki użytkownik końcowy nie zakończy wprowadzania poświadczeń.
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));
});

Odświeżanie przepływu tokenu

Publiczne interfejsy API

  • acquireTokenByRefreshToken: ten interfejs API uzyskuje token przez wymianę tokenu odświeżania dostarczonego dla nowego zestawu tokenów. Żądanie jest typu RefreshTokenRequest. Element refresh token nigdy nie jest zwracany do użytkownika w odpowiedzi, ale można uzyskać do niego dostęp z pamięci podręcznej użytkownika. Zaleca się użycie acquireTokenSilent() w scenariuszach nieinteraktywnych. W przypadku korzystania z metody acquireTokenSilent()biblioteka MSAL będzie automatycznie obsługiwać buforowanie i odświeżanie tokenów.
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));
});

Cichy przepływ

Publiczne interfejsy API

  • acquireTokenSilent: ten interfejs API uzyskuje token dyskretnie, jeśli pamięć podręczna jest dostarczana przez użytkownika lub gdy pamięć podręczna jest tworzona przez poprzedzanie tego wywołania za pomocą dowolnego innego przepływu interaktywnego (np. przepływu kodu autoryzacji). Żądanie jest typu SilentFlowRequest. Element token jest uzyskiwany w trybie dyskretnym, gdy użytkownik określa konto, dla którego żądany jest 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);
});

Przepływ poświadczeń klienta

Publiczne interfejsy API

  • acquireTokenByClientCredential: To API pobiera token przy użyciu poświadczeń poufnej aplikacji klienckiej w celu uwierzytelnienia (zamiast podszywania się pod użytkownika) podczas wywoływania innej usługi internetowej. W tym scenariuszu klient jest zazwyczaj usługą internetową warstwy środkowej, usługą demona lub aplikacją internetową zaplecza. W celu zapewnienia wyższego poziomu bezpieczeństwa platforma tożsamości Microsoft umożliwia również usłudze wywołującej użycie certyfikatu (zamiast wspólnego sekretu) jako poświadczenia. Żądanie jest typu ClientCredentialRequest.

Bezpieczne korzystanie z sekretów

Wpisy tajne nigdy nie powinny być zakodowane na stałe. Pakiet npm dotenv może służyć do przechowywania wpisów tajnych w pliku env (znajdującym się w katalogu głównym projektu), który powinien zostać uwzględniony w pliku gitignore, aby zapobiec przypadkowemu przekazaniu wpisów tajnych.

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

W imieniu Flow

  • acquireTokenOnBehalfOf: ten interfejs API implementuje przepływ On Behalf Of Flow, który jest używany, gdy aplikacja wywołuje interfejs API usługi/sieci Web, który z kolei musi wywołać inny interfejs API usługi/sieci Web, który korzysta z dowolnego innego przepływu uwierzytelniania (kod urządzenia, nazwa użytkownika/hasło itp.). Token dostępu jest uzyskiwany przez internetowy interfejs API początkowo (przez dowolny przepływ internetowego interfejsu API), a internetowy interfejs API może następnie wymienić ten token na inny token za pośrednictwem OBO. Żądanie jest typu OnBehalfOfRequest

Aby uzyskać instrukcje użytkowania, zapoznaj się z przykładem przepływu On Behalf Of: