Přihlášení uživatelů

Než začnete tady, ujistěte se, že rozumíte tomu, jak inicializovat objekt aplikace.

Přihlašovací rozhraní API v MSAL získávají authorization code, který lze vyměnit za token identity pro přihlášeného uživatele, a zároveň udělují souhlas s obory pro další zdroj a získávají přístupový token obsahující obory, s nimiž uživatel vyslovil souhlas, který vaší aplikaci umožňuje bezpečně volat rozhraní API.

Volba typu interakce

Podívejte se zde , pokud si nejste jisti rozdíly mezi loginRedirect a loginPopup.

Přihlášení uživatele

Do přihlašovacích rozhraní API musíte předat objekt požadavku. Tento objekt umožňuje použít v požadavku různé parametry. Další informace o parametrech objektu požadavku naleznete zde.

U žádostí o přihlášení jsou všechny parametry volitelné, takže stačí odeslat prázdný objekt.

  • Popup
try {
    const loginResponse = await msalInstance.loginPopup({});
} catch (err) {
    // handle error
}
  • Přesměrování
try {
    msalInstance.loginRedirect({});
} catch (err) {
    // handle error
}

Nebo můžete odeslat sadu rozsahů oprávnění k předběžnému souhlasu:

  • Popup
var loginRequest = {
    scopes: ["user.read", "mail.send"] // optional Array<string>
};

try {
    const loginResponse = await msalInstance.loginPopup(loginRequest);
} catch (err) {
    // handle error
}
  • Přesměrování
var loginRequest = {
    scopes: ["user.read", "mail.send"] // optional Array<string>
};

try {
    msalInstance.loginRedirect(loginRequest);
} catch (err) {
    // handle error
}

API pro účty

Po úspěšném přihlášení můžete pomocí getAllAccounts() funkce načíst informace o aktuálně přihlášených uživatelích.

const myAccounts: AccountInfo[] = msalInstance.getAllAccounts();

Pokud znáte informace o účtu, můžete informace o účtu načíst také pomocí getAccount() rozhraní 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

Filtrování podle username je poskytováno pro usnadnění a mělo by být považováno za méně spolehlivé než vyhledávání na homeAccountIdzákladě . Pokud je to možné, použijte homeAccountId.

Ve scénářích B2C musí být váš tenant B2C nakonfigurován tak, aby vracel claim emails u idTokens, aby bylo možné použít filtr username v rozhraní API getAccount().

Tato rozhraní API vrátí objekt účtu nebo pole objektů účtu s následujícím 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;
};

Tiché přihlášení pomocí ssoSilent()

Pokud už máte relaci, která existuje s ověřovacím serverem, můžete pomocí rozhraní ssoSilent() API vytvářet žádosti o tokeny bez interakce.

S nápovědou pro uživatele

Pokud už máte přihlašovací informace uživatele, můžete ho předat do rozhraní API, abyste zlepšili výkon a zajistili, že autorizační server vyhledá správnou relaci účtu. Pokud chcete úspěšně získat token bezobslužně, můžete do objektu požadavku předat jednu z následujících možností.

Doporučuje se využít login_hint volitelný deklarovaný údaj v tokenu ID (poskytovaný pro ssoSilent jako loginHint), protože jde o nejspolehlivější vodítko k určení účtu při tichých (i interaktivních) požadavcích.

  • account (které lze získat pomocí jednoho z rozhraní API pro účty)
  • sid (který lze načíst z idTokenClaims objektu account)
  • login_hint (lze získat následujícími způsoby)
    • Jako vlastnost objektu účtu loginHint (doporučeno)
    • Jako deklarace identity tokenu ID objektu login_hint účtu (doporučeno)
    • Jako vlastnost objektu username účtu (nedoporučuje se)
    • Jako deklarace identity tokenu ID objektu upn účtu (nedoporučuje se)

Note

Vlastnosti username a upn jsou částečně podporovány namísto skutečné deklarace identity login_hint, jejich použití se však nedoporučuje. Použijte vlastnosti účtu loginHint nebo idTokenClaims.login_hint, pokud jsou k dispozici.

Při předání účtu se vyhledá volitelný deklarovaný údaj login_hint v tokenu ID (upřednostňováno), poté volitelný deklarovaný údaj sid v tokenu ID a nakonec se použije loginHint (je-li k dispozici) nebo uživatelské jméno účtu.

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 nápovědy pro uživatele

Pokud není o uživateli k dispozici dostatek informací, můžete zkusit použít rozhraní API ssoSilentaniž byste předali account, sid nebo login_hint.

const silentRequest = {
    scopes: ["User.Read", "Mail.Read"]
};

Mějte ale na paměti, že pokud má vaše aplikace cesty kódu pro více uživatelů v jedné relaci prohlížeče nebo pokud má uživatel více účtů pro danou relaci prohlížeče, je vyšší pravděpodobnost chyb tichého přihlášení. Pokud autorizační server najde více relací účtu, může se zobrazit následující chyba:

InteractionRequiredAuthError: interaction_required: AADSTS16000: Either multiple user identities are available for the current request or selected account is not supported for the scenario.

To znamená, že server nemohl určit, ke kterému účtu se přihlásit, a bude vyžadovat jeden z výše uvedených parametrů (account, login_hint, sid) nebo interaktivní přihlášení k výběru účtu.

Warning

Při použití ssoSilent se služba pokusí načíst stránku URI pro přesměrování v neviditelném vloženém rámci iframe. Zásady zabezpečení obsahu a hodnoty hlaviček HTTP, které jsou přítomné v odpovědi na stránku URI přesměrování vaší aplikace, například X-FRAME-OPTIONS: DENY a X-FRAME-OPTIONS: SAMEORIGINmohou zabránit tomu, aby se vaše aplikace načítala do prvku iframe a efektivně blokuje tiché jednotné přihlašování. Pokud chcete použít ssoSilent, ujistěte se, že identifikátor URI přesměrování odkazuje na stránku, která neimplementuje žádné takové zásady.

Důležité informace o identifikátorech RedirectUri

Všechny toky ověřování teď vyžadují vyhrazenou stránku přesměrování , která implementuje most přesměrování MSAL. To je nezbytné pro podporu hlaviček COOP (Cross-Origin-Opener-Policy) a umožnění zabezpečené komunikace mezi okny popup/iframe a hlavní aplikací.

Nastavení stránky pro přesměrování

redirectUri musí směřovat na vyhrazenou stránku, která načte přemosťovací skript pro přesměrování. Tato stránka by měla:

  1. Načtení skriptu přesměrovacího mostu – tento skript zpracovává komunikaci s hlavním oknem.
  2. Nezahrnuje žádný JavaScript s výjimkou skriptu mostu – stránka pro přesměrování by měla spustit pouze skript mostu.
  3. Nezahrnujte logiku směrování – Vyhněte se knihovnám směrovačů, které můžou kolidovat s zpracováním hodnot hash.
  4. Musí být zaregistrován ve vaší registraci aplikace – URI musí přesně odpovídat tomu, co je zaregistrováno na portálu Azure.

Příklad stránky přesměrování (při použití bundleru, jako je Vite nebo 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

@azure/msal-browser/redirect-bridge Specifikátor musí být vyřešen nástrojem bundler (Vite, Webpack atd.) – nejedná se o adresu URL, kterou můžou prohlížeče načíst přímo. Pokyny specifické pro konkrétní framework najdete v příručce k nastavení nástroje Redirect Bridge.

Konfigurace

redirectUri můžete nastavit globálně v konfiguraci MSAL nebo pro jednotlivé požadavky:

Globální konfigurace:

const msalConfig = {
    auth: {
        clientId: "your-client-id",
        authority: "https://login.microsoftonline.com/common",
        redirectUri: "http://localhost:3000/redirect"
    }
};

const msalInstance = new PublicClientApplication(msalConfig);

Konfigurace pro jednotlivé požadavky:

msalInstance.loginPopup({
    scopes: ["user.read"],
    redirectUri: "http://localhost:3000/redirect"
});

Další informace a úplné ukázkové implementace najdete v tématech:

Řešení chyb vyskakovacích oken interaction_in_progress

U automaticky otevíracích toků můžete příznakem overrideInteractionInProgress zrušit čekající interakci a spustit novou. To je užitečné pro scénáře obnovení, kdy uživatel zrušil automaticky otevírané okno nebo došlo k selhání interakce.

Note

Tato funkce je dostupná pouze pro vyskakovací toky a není podporována pro toky přesměrování. S hlavičkou COOP (Cross-Origin-Opener-Policy) je tradiční window.opener spojení přerušeno, takže automaticky otevíraná okna mohou s hlavním oknem komunikovat pouze prostřednictvím BroadcastChannel.

Important

Nastavení této hodnoty na true vynutí zrušení všech nevyřízených požadavků na ověření ve vyskakovacím okně, ale neuzavře žádná otevřená vyskakovací okna.

Při nastavení na true:

  • Pokud právě probíhá jiná interakce s vyskakovacím oknem, bude vynuceně ukončena, ale žádná již otevřená vyskakovací okna se nezavřou.
  • Nevyřízená interakce selže s chybou interaction_in_progress_cancelled.
  • Nový automaticky otevíraný tok okamžitě pokračuje.

Platné případy použití:

  • Obnovení z chyb, kdy uživatel zrušil automaticky otevírané okno (automaticky otevírané okno se zavřelo bez dokončení ověřování)
  • Implementace vlastních toků obnovení chyb
  • Poskytnutí mechanismu pro opakování po neúspěšné interakci s vyskakovacím oknem

Výchozí:false

Důležité: Používejte pouze při kliknutí na tlačítko

Neopakujte pokus automaticky při zachycení chyby interaction_in_progress. K tomuto přepsání by mělo dojít pouze na základě výslovné akce uživatele (například kliknutím na tlačítko „Opakovat“). Automatické přepisování interakcí může vést k:

  • Souběžné podmínky mezi několika ověřovacími toky
  • Neočekávané zrušení legitimních pokusů o ověření
  • Špatné uživatelské prostředí s toky ověřování, které se spouští a neočekávaně zastavuje
  • Mnoho otevřených místních oken, která nevedou k úspěšným odpovědím ověření

Příklad: Správné zpracování chyb při opakování spuštěném uživatelem

Kompletní implementace s vizuální zpětnou vazbou najdete tady:

Obě ukázky ukazují:

  • Zpráva s upozorněním zobrazená během automaticky otevíraného ověřování
  • Možnost opakování v modálním okně nebo dialogu s jasným vysvětlením, když dojde k chybě interaction_in_progress
  • Správná správa stavu pro opakované pokusy aktivované uživatelem
  • Komponenty uživatelského rozhraní připravené pro produkční prostředí
// 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
}

Příklad: Komponenta React s opakovaným pokusem aktivovaným uživatelem

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

Další kroky

Přečtěte si, jak získat přístupový token a používat ho.