Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Przed rozpoczęciem tutaj upewnij się, że rozumiesz, jak zainicjować obiekt aplikacji.
Interfejsy API logowania w bibliotece MSAL pobierają authorization code, które można wymienić na token ID dla zalogowanego użytkownika, przy jednoczesnym wyrażeniu zgody na zakresy dodatkowego zasobu, oraz na token dostępu zawierający zakresy, na które użytkownik wyraził zgodę, aby umożliwić aplikacji bezpieczne wywoływanie interfejsu API.
Wybieranie typu interakcji
Zobacz tutaj , jeśli nie masz pewności co do różnic między loginRedirect i loginPopup.
Logowanie użytkownika
Musisz przekazać obiekt żądania do interfejsów API logowania. Ten obiekt umożliwia używanie różnych parametrów w żądaniu. Zobacz tutaj , aby uzyskać więcej informacji na temat parametrów obiektu żądania.
W przypadku żądań logowania wszystkie parametry są opcjonalne, więc wystarczy wysłać pusty obiekt.
- Popup
try {
const loginResponse = await msalInstance.loginPopup({});
} catch (err) {
// handle error
}
- Redirect
try {
msalInstance.loginRedirect({});
} catch (err) {
// handle error
}
Możesz też wysłać zestaw zakresów uprawnień, aby z góry wyrazić na nie zgodę:
- Popup
var loginRequest = {
scopes: ["user.read", "mail.send"] // optional Array<string>
};
try {
const loginResponse = await msalInstance.loginPopup(loginRequest);
} catch (err) {
// handle error
}
- Redirect
var loginRequest = {
scopes: ["user.read", "mail.send"] // optional Array<string>
};
try {
msalInstance.loginRedirect(loginRequest);
} catch (err) {
// handle error
}
Interfejsy API kont
Po pomyślnym wywołaniu logowania można użyć getAllAccounts() funkcji , aby pobrać informacje o aktualnie zalogowanych użytkownikach.
const myAccounts: AccountInfo[] = msalInstance.getAllAccounts();
Jeśli znasz informacje o koncie, możesz również pobrać informacje o koncie przy użyciu interfejsu getAccount() API:
const username = "test@contoso.com";
const myAccount: AccountInfo = msalInstance.getAccount({ username });
const homeAccountId = "userid.hometenantid"; // Best to retrieve the homeAccountId from an account object previously obtained through msal
const myAccount: AccountInfo = msalInstance.getAccount({ homeAccountId });
Note
Filtrowanie według username jest zapewniane dla wygody i powinno być uważane za mniej niezawodne niż wyszukiwanie na homeAccountIdpodstawie . Jeśli to możliwe, użyj polecenia homeAccountId.
W scenariuszach B2C dzierżawa B2C musi być skonfigurowana tak, aby zwracała roszczenie emails w idTokens, aby można było użyć filtru username w interfejsie API getAccount().
Te interfejsy API zwracają obiekt konta lub tablicę obiektów konta z następującym podpisem:
{
// home account identifier for this account object
homeAccountId: string;
// Entity who issued the token represented as a full host of it (e.g. login.microsoftonline.com)
environment: string;
// Full tenant or organizational id that this account belongs to
tenantId: string;
// preferred_username claim of the id_token that represents this account.
username: string;
};
Logowanie dyskretne przy użyciu funkcji ssoSilent()
Jeśli masz już sesję, która istnieje z serwerem uwierzytelniania, możesz użyć interfejsu API ssoSilent(), aby wysyłać żądania dotyczące tokenów bez interakcji.
Ze wskazówką użytkownika
Jeśli masz już informacje logowania użytkownika, możesz przekazać je do interfejsu API, aby zwiększyć wydajność i upewnić się, że serwer autoryzacji będzie szukać prawidłowej sesji konta. Aby pomyślnie uzyskać token w trybie dyskretnym, możesz przekazać jeden z poniższych elementów do obiektu żądania.
Zaleca się wykorzystanie opcjonalnegologin_hint oświadczenia tokenu identyfikatora (podanego ssoSilent jako loginHint), ponieważ jest to najbardziej niezawodna wskazówka konta dla dyskretnych (i interaktywnych) żądań.
-
account(które można pobrać za pomocą jednego z interfejsów API konta użytkownika) -
sid(co można pobrać zidTokenClaimsobiektuaccount) -
login_hint(można uzyskać na następujące sposoby)- Jako właściwość obiektu konta
loginHint(zalecane) - Jako oświadczenie tokenu identyfikatora
login_hintobiektu konta (zalecane) - Jako właściwość obiektu konta
username(niezalecane) - Jako oświadczenie tokenu identyfikatora
upnobiektu konta (niezalecane)
- Jako właściwość obiektu konta
Note
Właściwości username i upn są częściowo obsługiwane zamiast faktycznego roszczenia login_hint, ale nie są zalecane. Użyj właściwości konta loginHint lub idTokenClaims.login_hint, jeśli są dostępne.
Po przekazaniu konta system wyszuka opcjonalne roszczenie tokenu login_hint (preferowane), następnie opcjonalne roszczenie tokenu sid, a następnie w ostateczności użyje wartości loginHint (jeśli została podana) lub nazwy użytkownika konta.
const account = msalInstance.getAllAccounts()[0];
const silentRequest = {
scopes: ["User.Read", "Mail.Read"],
loginHint: account.loginHint, // alternatively, account.idTokenClaims.login_hint
};
try {
const loginResponse = await msalInstance.ssoSilent(silentRequest);
} catch (err) {
if (err instanceof InteractionRequiredAuthError) {
const loginResponse = await msalInstance.loginPopup(silentRequest).catch(error => {
// handle error
});
} else {
// handle error
}
}
Bez wskazówki użytkownika
Jeśli nie ma wystarczających informacji o użytkowniku, możesz spróbować użyć interfejsu ssoSilent API bez przekazywania account, sid ani login_hint.
const silentRequest = {
scopes: ["User.Read", "Mail.Read"]
};
Należy jednak pamiętać, że jeśli aplikacja ma ścieżki kodu dla wielu użytkowników w jednej sesji przeglądarki lub jeśli użytkownik ma wiele kont dla tej jednej sesji przeglądarki, istnieje większe prawdopodobieństwo błędów logowania dyskretnego. Może zostać wyświetlony następujący błąd w przypadku wielu sesji konta znalezionych przez serwer autoryzacji:
InteractionRequiredAuthError: interaction_required: AADSTS16000: Either multiple user identities are available for the current request or selected account is not supported for the scenario.
Oznacza to, że serwer nie może określić, do którego konta się zalogować, i będzie wymagać jednego z powyższych parametrów (account, login_hint, sid) lub interaktywnego logowania, aby wybrać konto.
Warning
Podczas korzystania z ssoSilent usługa próbuje załadować stronę URI przekierowania w niewidocznym osadzonym elemencie iframe. Zasady bezpieczeństwa treści i wartości nagłówków HTTP obecne w odpowiedzi strony pod adresem URI przekierowania aplikacji, takie jak X-FRAME-OPTIONS: DENY i X-FRAME-OPTIONS: SAMEORIGIN, mogą uniemożliwić załadowanie aplikacji w ramce iframe, co skutecznie blokuje ciche logowanie jednokrotne (SSO). Jeśli zamierzasz użyć ssoSilent, upewnij się, że identyfikator URI przekierowania wskazuje na stronę, która nie stosuje żadnych takich zasad.
Zagadnienia dotyczące identyfikatora RedirectUri
Wszystkie przepływy uwierzytelniania wymagają teraz dedykowanej strony przekierowania, która zawiera implementację mechanizmu przekierowania MSAL. Jest to konieczne, aby zapewnić obsługę nagłówków COOP (Cross-Origin-Opener-Policy) i umożliwić bezpieczną komunikację między oknami wyskakującymi/ramkami iframe a aplikacją główną.
Konfigurowanie strony przekierowania
Twój redirectUri musi wskazywać na dedykowaną stronę, która ładuje skrypt pośredniczący przekierowania. Ta strona powinna:
- Załaduj skrypt mostka przekierowania — ten skrypt obsługuje komunikację z głównym oknem
- Nie dołączaj żadnego skryptu JavaScript z wyjątkiem skryptu mostka — strona przekierowania powinna uruchamiać tylko skrypt mostka
- Nie obejmuje logiki routingu — unikaj bibliotek routerów, które mogą zakłócać obsługę skrótów
- Być zarejestrowany w obszarze Rejestracje aplikacji — identyfikator URI musi dokładnie odpowiadać temu, co zarejestrowano w portalu Azure
Przykładowa strona przekierowania (w przypadku korzystania z pakietu, takiego jak Vite lub Webpack):
<!DOCTYPE html>
<html>
<head>
<title>Redirect</title>
</head>
<body>
<p>Processing authentication...</p>
<script type="module">
import { broadcastResponseToMainFrame } from "@azure/msal-browser/redirect-bridge";
broadcastResponseToMainFrame();
</script>
</body>
</html>
Note
Specyfikator @azure/msal-browser/redirect-bridge musi być rozpoznawany przez pakiet (Vite, Webpack itp.) — nie jest to adres URL, który przeglądarki mogą pobrać bezpośrednio. Aby uzyskać instrukcje specyficzne dla platformy, zobacz Przewodnik konfigurowania mostka przekierowania.
Konfiguracja
Możesz ustawić element redirectUri globalnie w konfiguracji MSAL lub dla każdego żądania:
Konfiguracja globalna:
const msalConfig = {
auth: {
clientId: "your-client-id",
authority: "https://login.microsoftonline.com/common",
redirectUri: "http://localhost:3000/redirect"
}
};
const msalInstance = new PublicClientApplication(msalConfig);
Konfiguracja poszczególnych żądań:
msalInstance.loginPopup({
scopes: ["user.read"],
redirectUri: "http://localhost:3000/redirect"
});
Aby uzyskać więcej informacji i pełne przykładowe implementacje, zobacz:
Obsługa błędów wyskakujących okienek interaction_in_progress
W przypadku przepływów w wyskakującym oknie możesz użyć flagi overrideInteractionInProgress, aby anulować oczekującą interakcję i rozpocząć nową. Jest to przydatne w scenariuszach odzyskiwania, w których użytkownik anulował wyskakujące okienko lub interakcję nie powiodła się.
Note
Ta funkcja jest dostępna tylko dla przepływów wyskakujących i nie jest obsługiwana w przypadku przepływów przekierowania. Nagłówek COOP (Cross-Origin-Opener-Policy) zrywa tradycyjne połączenie window.opener, dzięki czemu okna podręczne mogą komunikować się z głównym oknem wyłącznie za pośrednictwem BroadcastChannel.
Ważna
Ustawienie tej opcji na true wymusi anulowanie wszystkich oczekujących żądań uwierzytelniania w wyskakujących oknach, ale nie zamknie żadnych już otwartych wyskakujących okien.
Po ustawieniu wartości na true:
- Jeśli trwa inna interakcja z okienkiem podręcznym, zostaje ona wymuszenie anulowana, ale żadne otwarte okienka podręczne nie są zamykane
- Oczekująca interakcja zostaje odrzucona i zwraca błąd
interaction_in_progress_cancelled - Nowy przepływ wyskakujących okienek jest natychmiast kontynuowany
Prawidłowe przypadki użycia:
- Odzyskiwanie po błędach polegających na tym, że użytkownik anulował wyskakujące okienko (wyskakujące okienko zostało zamknięte bez ukończenia uwierzytelniania)
- Implementowanie niestandardowych przepływów odzyskiwania błędów
- Zapewnienie mechanizmu ponawiania próby po nieudanej interakcji z oknem podręcznym
Domyślny:false
Ważne: używaj tylko po kliknięciu przycisku
Nie ponawiaj próby automatycznie w przypadku przechwycenia błędu interaction_in_progress. Zastąpienie powinno być tylko uruchamiane przez wyraźne działanie użytkownika (na przykład kliknięcie przycisku „Ponów próbę”). Automatyczne zastępowanie interakcji może prowadzić do:
- Warunki wyścigu między wieloma przepływami uwierzytelniania
- Nieoczekiwane anulowanie legalnych prób uwierzytelniania
- Niezadowalające doświadczenie użytkownika z powodu niespodziewanego uruchamiania i przerywania przepływów uwierzytelniania
- Wiele otwartych okien podręcznych, które nie doprowadzą do pomyślnej odpowiedzi uwierzytelnienia
Przykład: prawidłowa obsługa błędów przy użyciu ponawiania próby wyzwalanej przez użytkownika
Aby zobaczyć kompletne implementacje z wizualną informacją zwrotną, zobacz:
- Przykład express — demonstruje implementację języka JavaScript z niestandardowym arkuszem CSS
- Przykład routera React — demonstruje implementację platformy React za pomocą składników Material-UI
Oba przykłady pokazują:
- Komunikat ostrzegawczy wyświetlany podczas uwierzytelniania w oknie podręcznym
- Ponów próbę modalne/okno dialogowe z jasnym wyjaśnieniem, gdy
interaction_in_progresswystąpi błąd - Prawidłowe zarządzanie stanem podczas ponawiania operacji inicjowanego przez użytkownika
- Składniki interfejsu użytkownika gotowe do produkcji
// State to track if user wants to retry
let userWantsRetry = false;
// Button click handler
async function handleLoginClick() {
try {
const loginRequest = {
scopes: ["user.read"]
};
// If user explicitly clicked retry, override the existing interaction
if (userWantsRetry) {
loginRequest.overrideInteractionInProgress = true;
userWantsRetry = false; // Reset flag
}
const response = await msalInstance.loginPopup(loginRequest);
// Handle successful login
} catch (error) {
if (error.errorCode === 'interaction_in_progress') {
// Show retry button to user - DO NOT automatically retry
showRetryButton();
} else {
// Handle other errors
console.error(error);
}
}
}
// Retry button click handler
function handleRetryClick() {
userWantsRetry = true; // Set flag for next login attempt
handleLoginClick(); // User explicitly requested retry
}
Przykład: składnik React z ponawianymi próbami wyzwalanymi przez użytkownika
function LoginButton() {
const { instance } = useMsal();
const [showRetry, setShowRetry] = useState(false);
const [retryRequested, setRetryRequested] = useState(false);
const handleLogin = async () => {
try {
const loginRequest = {
scopes: ["user.read"],
// Only override if user clicked the retry button
overrideInteractionInProgress: retryRequested
};
setRetryRequested(false); // Reset retry flag
const response = await instance.loginPopup(loginRequest);
setShowRetry(false);
} catch (error) {
if (error.errorCode === 'interaction_in_progress') {
// Show retry button - let user decide whether to retry
setShowRetry(true);
} else {
console.error(error);
}
}
};
const handleRetry = () => {
setRetryRequested(true); // User explicitly requested retry
handleLogin();
};
return (
<div>
<button onClick={handleLogin}>Login</button>
{showRetry && (
<button onClick={handleRetry}>
Retry Login (Cancel Pending)
</button>
)}
</div>
);
}
Dalsze kroki
Dowiedz się, jak uzyskać token dostępu i korzystać z niego!