Errors

BrowserConfigurationAuthErrors

stubbed_public_client_application_called

Komunikat o błędzie: Wywołano atrapową instancję publicznej aplikacji klienckiej. Jeśli używasz biblioteki msal-react, upewnij się, że kontekst nie jest używany bez dostawcy.

Zobacz informacje o błędach msal-react

BrowserAuthErrors

Interakcja_w_toku

Komunikat o błędzie: Interakcja jest obecnie w toku. Przed wywołaniem interaktywnego interfejsu API upewnij się, że ta interakcja została ukończona.

Ten błąd jest zgłaszany, gdy interakcyjny interfejs API (loginPopup, loginRedirect, acquireTokenPopup, acquireTokenRedirect) jest wywoływany, gdy inny interaktywny interfejs API jest nadal w toku. Interfejsy API login i acquireToken są asynchroniczne, dlatego przed wywołaniem kolejnego należy upewnić się, że powiązane z nimi obietnice zostały zrealizowane.

Używanie loginPopup lub acquireTokenPopup

Przed wywołaniem kolejnego interfejsu API upewnij się, że obietnica zwrócona przez te interfejsy API została spełniona.

❌ Poniższy przykład spowoduje wystąpienie tego błędu, ponieważ loginPopup nadal będzie wykonywane w momencie wywołania acquireTokenPopup:

const request = { scopes: ["openid", "profile"] };
loginPopup();
acquireTokenPopup(request);

✔️ Aby rozwiązać ten problem, przed wywołaniem innego interfejsu API upewnij się, że wszystkie interakcyjne interfejsy API zostały rozwiązane:

const request = { scopes: ["openid", "profile"] };
await msalInstance.loginPopup();
await msalInstance.acquireTokenPopup(request);

Używanie loginRedirect lub acquireTokenRedirect

W przypadku korzystania z interfejsów API przekierowań po powrocie z przekierowania należy wywołać handleRedirectPromise. Dzięki temu odpowiedź tokenu z serwera jest prawidłowo obsługiwana, a wpisy tymczasowej pamięci podręcznej są czyszczone. Ten błąd jest zgłaszany, gdy handleRedirectPromise nie zdąży się zakończyć, zanim aplikacja wywoła loginRedirect lub acquireTokenRedirect.

❌ Poniższy przykład zgłosi ten błąd, ponieważ handleRedirectPromise nadal będzie przetwarzać odpowiedź z poprzedniego loginRedirect wywołania, gdy loginRedirect jest wywoływany drugi raz:

msalInstance.handleRedirectPromise();

const accounts = msalInstance.getAllAccounts();
if (accounts.length === 0) {
    // No user signed in
    msalInstance.loginRedirect();
}

✔️ Aby rozwiązać ten problem, przed wywołaniem jakiegokolwiek interakcyjnego interfejsu API należy poczekać, aż handleRedirectPromise się zakończy:

await msalInstance.handleRedirectPromise();

const accounts = msalInstance.getAllAccounts();
if (accounts.length === 0) {
    // No user signed in
    msalInstance.loginRedirect();
}

Lub alternatywnie:

msalInstance
    .handleRedirectPromise()
    .then((tokenResponse) => {
        if (!tokenResponse) {
            const accounts = msalInstance.getAllAccounts();
            if (accounts.length === 0) {
                // No user signed in
                msalInstance.loginRedirect();
            }
        } else {
            // Do something with the tokenResponse
        }
    })
    .catch((err) => {
        // Handle error
        console.error(err);
    });

Uwaga: Jeśli wywołujesz loginRedirect lub acquireTokenRedirect ze strony, która nie jest Twoją stroną redirectUri, musisz upewnić się, że handleRedirectPromise zostanie wywołane i że system będzie oczekiwać na jego zakończenie zarówno na stronie redirectUri, jak i na stronie, z której zainicjowano przekierowanie. Dzieje się tak, ponieważ strona redirectUri zainicjuje przekierowanie z powrotem do strony, która pierwotnie wywołała loginRedirect, a ta strona przetworzy odpowiedź tokena.

Biblioteki opakowujące

Jeśli używasz jednej z naszych bibliotek opakowujących (React lub Angular), zapoznaj się z dokumentacją dotyczącą błędów w tych bibliotekach, aby poznać dodatkowe przyczyny, dla których możesz otrzymywać ten błąd:

Jeśli nie używasz żadnej z bibliotek opakowujących, ale obawiasz się, że Twoja aplikacja może inicjować równoczesne żądania interakcyjne, przed wywołaniem interakcji w metodzie pozyskiwania tokenów należy sprawdzić, czy nie trwa już żadna inna interakcja. Można to osiągnąć, implementując globalny stan aplikacji lub usługę emisji itp., która emituje bieżący stan interakcji biblioteki MSAL za pośrednictwem interfejsu API zdarzeń biblioteki MSAL.

❌ W poniższym przykładzie wystąpi ten błąd, ponieważ acquireTokenPopup w bloku catch nie sprawdza, czy w danym momencie trwa inna interakcja:

async function myAcquireToken(request) {
    const msalInstance = getMsalInstance(); // get the msal application instance

    const tokenRequest = {
        account: msalInstance.getActiveAccount() || null;
        ...request
    };

    let tokenResponse;

    try {
        // attempt silent acquisition first
        tokenResponse = await msalInstance.acquireTokenSilent(tokenRequest);
    } catch (error) {
        if (error instanceof InteractionRequiredAuthError) {
            try {
                tokenResponse = await msalInstance.acquireTokenPopup(tokenRequest);
            } catch (err) {
                console.log(err);
                // handle other errors
            }
        }

        console.log(error);
        // handle other errors
    }

    return tokenResponse;
};

const request = {
    scopes: ["User.Read"]
};

myAcquireToken(request);
myAcquireToken(request);

✔️ Aby rozwiązać ten problem, przed wywołaniem jakiegokolwiek innego interaktywnego API należy poczekać, aż stan interakcji będzie miał wartość None:

async function myAcquireToken(request) {
    const msalInstance = getMsalInstance(); // get the msal application instance

    const tokenRequest = {
        account: msalInstance.getActiveAccount() || null;
        ...request
    };

    let tokenResponse;

    try {
        // attempt silent acquisition first
        tokenResponse = await msalInstance.acquireTokenSilent(tokenRequest);
    } catch (error) {
        if (error instanceof InteractionRequiredAuthError) {
            // check for any interactions
            if (myGlobalState.getInteractionStatus() !== InteractionStatus.None) {
                // throw a new error to be handled in the caller below
                throw new Error("interaction_in_progress");
            } else {
                // no interaction, invoke popup flow
                tokenResponse = await msalInstance.acquireTokenPopup(tokenRequest);
            }
        }

        console.log(error);
        // handle other errors
    }

    return tokenResponse;
};

async function myInteractionInProgressHandler() {
    /**
     * "myWaitFor" method polls the interaction status via getInteractionStatus() from
     * the application state and resolves when it's equal to "None".
     */
    await myWaitFor(() => myGlobalState.getInteractionStatus() === InteractionStatus.None);

    // wait is over, call myAcquireToken again to re-try acquireTokenSilent
    return (await myAcquireToken(tokenRequest));
};

const request = {
    scopes: ["User.Read"]
};

myAcquireToken(request).catch((e) => myInteractionInProgressHandler());
myAcquireToken(request).catch((e) => myInteractionInProgressHandler());

Kroki rozwiązywania problemów

  • Włącz szczegółowe rejestrowanie i śledź kolejność zdarzeń. Sprawdź, czy handleRedirectPromise zostanie wywołany i zakończy działanie przed wywołaniem dowolnego interfejsu API login lub acquireToken.

Jeśli nie możesz dowiedzieć się, dlaczego ten błąd jest zgłaszany, otwórz problem i przygotuj się do udostępnienia następujących informacji:

  • Pełne dzienniki
  • Przykładowa aplikacja i/lub fragmenty kodu, których możemy użyć do odtworzenia problemu
  • Odśwież stronę. Czy błąd zniknie?
  • Otwórz aplikację na nowej karcie. Czy błąd zniknie?

block_iframe_reload

Komunikat o błędzie: Żądanie zostało zablokowane w elemencie iframe, ponieważ biblioteka MSAL wykryła odpowiedź uwierzytelnienia.

Ten błąd jest zgłaszany podczas wywoływania ssoSilent lub acquireTokenSilent, gdy strona używana jako redirectUri próbuje wywołać funkcję logowania lub acquireToken. Naszym zalecanym sposobem obejścia problemu jest ustawienie redirectUri na pustą stronę, która nie korzysta z biblioteki MSAL podczas wywoływania interfejsów API w trybie cichym. Spowoduje to również dodatkową korzyść poprawy wydajności, ponieważ ukryty element iframe nie musi renderować strony.

✔️ Można to zrobić na podstawie poszczególnych żądań, na przykład:

msalInstance.acquireTokenSilent({
    scopes: ["User.Read"],
    redirectUri: "http://localhost:3000/blank.html",
});

Pamiętaj, że musisz zarejestrować ten nowy redirectUri w rejestracji aplikacji.

Jeśli nie chcesz używać do tego celu dedykowanego redirectUri, zamiast tego upewnij się, że element redirectUri nie próbuje wywoływać interfejsów API biblioteki MSAL podczas renderowania wewnątrz ukrytego elementu iframe używanego przez interfejsy API działające w tle.

limit_czasu_okna_monitora

Komunikaty o błędach:

  • Uzyskanie tokenu w ramce iframe nie powiodło się z powodu przekroczenia limitu czasu.

Ten błąd może wystąpić podczas wywoływania ssoSilent, acquireTokenSilent, acquireTokenPopup lub loginPopup, a przyczyn takiej sytuacji może być kilka. Oto kilka z najbardziej typowych:

  1. Strona, której używasz jako redirectUri, usuwa fragment identyfikatora lub manipuluje nim
  2. Strona używana jako redirectUri automatycznie przekierowuje na inną stronę
  3. Jesteś ograniczany przez dostawcę tożsamości
  4. Dostawca tożsamości nie przekierował z powrotem do elementu redirectUri.

Ważne: Jeśli aplikacja korzysta z biblioteki routingu (np. React Router, Angular Router), upewnij się, że nie usuwa ona hasha ani nie przekierowuje automatycznie, gdy trwa pozyskiwanie tokenu przez MSAL. Jeśli to możliwe, najlepiej, aby strona redirectUri w ogóle nie wywoływała routera.

Problemy spowodowane przez stronę redirectUri

Gdy wykonasz ciche wywołanie, w niektórych przypadkach zostanie otwarty iframe, który zostanie przekierowany na stronę autoryzacji dostawcy tożsamości. Gdy dostawca tożsamości autoryzuje użytkownika, przekieruje ramkę iframe z powrotem do redirectUri z kodem autoryzacji lub informacją o błędzie we fragmencie hash. Wystąpienie biblioteki MSAL uruchomione w ramce lub oknie, które pierwotnie złożyło żądanie, wyodrębni ten skrót odpowiedzi i przetworzy go. Jeśli element redirectUri usuwa ten fragment adresu URL lub manipuluje nim albo przechodzi do innej strony, zanim biblioteka MSAL go odczyta, wystąpi ten błąd przekroczenia limitu czasu.

✔️ Aby rozwiązać ten problem, upewnij się, że strona, której używasz jako redirectUri, nie wykonuje żadnej z tych czynności, przynajmniej gdy jest ładowana w oknie podręcznym lub elemencie iframe. Zalecamy użycie pustej strony w redirectUri przypadku przepływów dyskretnych i wyskakujących, aby upewnić się, że żadne z tych elementów nie może wystąpić.

Można to zrobić na podstawie poszczególnych żądań, na przykład:

msalInstance.acquireTokenSilent({
    scopes: ["User.Read"],
    redirectUri: "http://localhost:3000/blank.html",
});

Pamiętaj, że musisz zarejestrować ten nowy element redirectUri w rejestracji aplikacji.

Uwagi dotyczące platform Angular i React:

  • Jeśli używasz @azure/msal-angular, Twoja strona redirectUri nie powinna być chroniona przez komponent MsalGuard.
  • Jeśli używasz @azure/msal-react, Twoja strona redirectUri nie powinna renderować elementu MsalAuthenticationComponent ani korzystać z hooka useMsalAuthentication.

Problemy spowodowane przez dostawcę tożsamości

Throttling

Jednym z najczęstszych powodów, dla których ten błąd może zostać zgłoszony, jest to, że aplikacja utknęła w pętli lub wykonała zbyt wiele żądań tokenu w krótkim czasie. Kiedy tak się stanie, dostawca tożsamości może przez krótki czas ograniczać kolejne żądania, przez co nie nastąpi przekierowanie z powrotem do Twojego redirectUri, a w efekcie wystąpi ten błąd.

✔️ Aby rozwiązać problemy wynikające z ograniczania przepustowości, do wyboru są 2 opcje:

  1. Przestań wysyłać żądania na krótki czas przed ponowną próbą.
  2. Wywoływanie interakcyjnego interfejsu API, takiego jak acquireTokenPopup lub acquireTokenRedirect.
X-Frame-Options Odmów

Ten błąd może również wystąpić, jeśli dostawca tożsamości nie przekieruje z powrotem do Twojej aplikacji. W scenariuszach bez interakcji temu błędowi czasami towarzyszy błąd X-Frame-Options: Deny, wskazujący, że dostawca tożsamości próbuje wyświetlić komunikat o błędzie albo wymaga interakcji.

✔️ Błąd X-Frame-Options zwykle będzie miał w nim adres URL i otwarcie tego adresu URL na nowej karcie może pomóc w rozpoznaniu, co się dzieje. Jeśli zamiast tego wymagana jest interakcja, rozważ użycie interakcyjnego interfejsu API. Jeśli wyświetlany jest błąd, rozwiąż ten błąd.

Należy oczekiwać, że niektóre przepływy B2C powodują wystąpienie tego błędu, ponieważ wymagają interakcji z użytkownikiem. Te przepływy obejmują:

  • Resetowanie hasła
  • Edytowanie profilu
  • Zarejestruj się
  • Niektóre niestandardowe zasady w zależności od sposobu ich konfiguracji
Opóźnienie sieci

Innym potencjalnym powodem, dla którego dostawca tożsamości może nie przekierować z powrotem do Twojej aplikacji na czas, może być dodatkowe opóźnienie sieciowe.

✔️ Domyślny limit czasu wynosi około 10 sekund i w większości przypadków powinien być wystarczający, jednak jeśli dostawca tożsamości potrzebuje więcej czasu, aby Cię przekierować, możesz zwiększyć ten limit czasu w konfiguracji MSAL za pomocą parametrów konfiguracji iframeHashTimeout, windowHashTimeout lub loadFrameTimeout.

const msalConfig = {
    auth: {
        clientId: "your-client-id",
    },
    system: {
        windowHashTimeout: 9000, // Applies just to popup calls - In milliseconds
        iframeHashTimeout: 9000, // Applies just to silent calls - In milliseconds
        loadFrameTimeout: 9000, // Applies to both silent and popup calls - In milliseconds
    },
};

hash_empty_error

Komunikaty o błędach:

Nie można przetworzyć wartości skrótu, ponieważ jest pusta. Sprawdź, czy parametr redirectUri nie usuwa fragmentu po znaku #.

Ten błąd występuje, gdy strona używana jako identyfikator redirectUri usuwa skrót lub automatycznie przekierowuje do innej strony. Dzieje się tak najczęściej, gdy aplikacja implementuje router, który przechodzi do innej trasy, upuszczając skrót.

Aby rozwiązać ten błąd, zalecamy użycie dedykowanej strony redirectUri, która nie jest obsługiwana przez router. W przypadku cichych i wyskakujących wywołań najlepiej używać pustej strony. Jeśli nie jest to możliwe, upewnij się, że router nie wykonuje nawigacji, gdy trwa pozyskiwanie tokenu przez bibliotekę MSAL. Można to zrobić, wykrywając, czy aplikacja jest uruchomiona w elemencie iframe na potrzeby wywołań w trybie cichym, w wyskakującym oknie w przypadku wywołań popup lub oczekując na handleRedirectPromise w przypadku wywołań przekierowania.

hash_does_not_contain_known_properties

Komunikaty o błędach:

Skrót nie zawiera znanych właściwości. Sprawdź, czy parametr redirectUri nie zmienia fragmentu identyfikatora URI.

Zapoznaj się z wyjaśnieniem hash_empty_error powyżej. Główna przyczyna tego błędu jest podobna, różnica, że skrót został zmieniony, a nie porzucony.

nie_można_uzyskać_tokenu_z_natywnej_platformy

Komunikaty o błędach:

  • Nie można uzyskać tokenu z platformy natywnej.

Ten błąd występuje podczas wywoływania interfejsu API acquireTokenByCode przy użyciu nativeAccountId zamiast code, gdy aplikacja jest uruchomiona w środowisku, które nie pobiera tokenów od natywnego brokera. Aby uzyskać listę wymagań wstępnych, zapoznaj się z dokumentem na temat tokenów powiązanych z urządzeniem.

native_connection_not_established

Komunikaty o błędach:

  • Nie nawiązano połączenia z platformą natywną. Zainstaluj zgodne rozszerzenie przeglądarki i uruchom polecenie initialize().

Ten błąd jest zgłaszany, gdy użytkownik zalogował się za pomocą natywnego brokera, ale obecnie nie istnieje żadne połączenie z natywnym brokerem. Może tak się zdarzyć z następujących powodów:

  • Rozszerzenie Windows Accounts zostało odinstalowane lub wyłączone
  • Interfejs initialize API nie został wywołany lub nie był oczekiwany przed wywołaniem innego interfejsu API biblioteki MSAL

uninitialized_public_client_application

Komunikaty o błędach:

  • Przed podjęciem próby wywołania innego interfejsu API biblioteki MSAL należy wywołać funkcję i poczekać na jej zainicjowanie.

Ten błąd jest zgłaszany, gdy interfejs API login, acquireToken lub handleRedirectPromise zostanie wywołany przed wywołaniem interfejsu API initialize. Interfejs API initialize należy wywołać i oczekiwać na jego zakończenie przed podjęciem próby uzyskania tokenów.

❌ W poniższym przykładzie zostanie zgłoszony ten błąd, ponieważ handleRedirectPromise jest wywoływany przed ukończeniem inicjowania:

const msalInstance = new PublicClientApplication({
    auth: {
        clientId: "your-client-id",
    },
    system: {
        allowNativeBroker: true,
    },
});

await msalInstance.handleRedirectPromise(); // This will throw
msalInstance.acquireTokenSilent(); // This will also throw

✔️ Aby rozwiązać ten problem, należy poczekać, aż działanie initialize zostanie zakończone, przed wywołaniem dowolnego innego interfejsu API MSAL:

const msalInstance = new PublicClientApplication({
    auth: {
        clientId: "your-client-id",
    },
    system: {
        allowNativeBroker: true,
    },
});

await msalInstance.initialize();
await msalInstance.handleRedirectPromise(); // This will no longer throw this error since initialize completed before this was invoked
msalInstance.acquireTokenSilent(); // This will also no longer throw this error

Other

Błędy niewywoływane przez MSAL, takie jak błędy serwera

Dostęp do pobierania pod adresem [url] został zablokowany przez zasady MECHANIZMU CORS

Ten błąd występuje z MSAL.js w wersji 2.x i jest spowodowany niewłaściwą konfiguracją podczas rejestracji aplikacji w Azure Portal. W szczególności należy upewnić się, że element redirectUri jest zarejestrowany jako typ: Single-page application w sekcji Uwierzytelnianie w obszarze Rejestracja aplikacji. Jeśli operacja zakończy się pomyślnie, zobaczysz zielony znacznik wyboru z napisem:

Identyfikator URI przekierowania kwalifikuje się do przepływu kodu autoryzacji za pomocą protokołu PKCE.

obraz