Fazer login de usuários

Antes de começar aqui, certifique-se de entender como inicializar o objeto do aplicativo.

As APIs de logon no MSAL recuperam um authorization code que pode ser trocado por um token de ID para um usuário conectado, enquanto permitem escopos para um recurso adicional e um token de acesso que contém os escopos consentidos pelo usuário para permitir que seu aplicativo chame a API com segurança.

Escolhendo um tipo de interação

Veja aqui se você está incerto sobre as diferenças entre loginRedirect e loginPopup.

Fazer logon do usuário

Você deve passar um objeto de solicitação para as APIs de logon. Esse objeto permite que você use parâmetros diferentes na solicitação. Veja aqui mais informações sobre os parâmetros de objeto de solicitação.

Para solicitações de logon, todos os parâmetros são opcionais, portanto, você pode simplesmente enviar um objeto vazio.

  • Pop-up
try {
    const loginResponse = await msalInstance.loginPopup({});
} catch (err) {
    // handle error
}
  • Redirecionar
try {
    msalInstance.loginRedirect({});
} catch (err) {
    // handle error
}

Ou você pode enviar um conjunto de escopos para pré-consentimento:

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

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

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

APIs de conta

Quando uma chamada de logon tiver sido bem-sucedida, você poderá usar a getAllAccounts() função para recuperar informações sobre usuários conectados no momento.

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

Se você souber as informações da conta, também poderá recuperar as informações da conta usando a 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

A filtragem por username é fornecida por conveniência e deve ser considerada menos confiável do que a pesquisa baseada em homeAccountId. Quando possível, use homeAccountId.

Em cenários B2C, seu locatário B2C precisa ser configurado para retornar a declaração emails em idTokens para usar o filtro username na API getAccount().

Essas APIs retornarão um objeto de conta ou uma matriz de objetos de conta com a seguinte assinatura:

{
    // 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;
};

Logon silencioso com ssoSilent()

Se você já tiver uma sessão que exista com o servidor de autenticação, poderá usar a API ssoSilent() para fazer solicitações de tokens sem interação.

Com dica de usuário

Se você já tiver as informações de entrada do usuário, poderá passá-la para a API para melhorar o desempenho e garantir que o servidor de autorização procure a sessão de conta correta. Você pode passar um dos seguintes para o objeto de solicitação para obter com êxito um token silenciosamente.

Recomenda-se aproveitar a login_hint declaração de token de ID opcional (fornecida a ssoSilent como loginHint), pois é a dica de conta mais confiável para solicitações silenciosas (e interativas).

  • account (que pode ser recuperado usando uma das APIs da conta)
  • sid (que pode ser recuperado do idTokenClaims de um objeto account)
  • login_hint (pode ser recuperado das seguintes maneiras)
    • Como a propriedade loginHint do objeto da conta (recomendado)
    • Como a declaração do token de ID login_hint do objeto da conta (recomendado)
    • Como a propriedade username do objeto da conta (não recomendado)
    • Como a declaração do token de ID upn do objeto da conta (não recomendado)

Note

As propriedades username e upn têm suporte parcial em vez da propriedade login_hint propriamente dita, mas não são recomendadas. Use as propriedades da conta loginHint ou idTokenClaims.login_hint, se estiverem disponíveis.

Ao passar uma conta, o sistema procurará a declaração opcional do token de ID login_hint (preferencial), depois a declaração opcional do token de ID sid e, por fim, recorrerá a loginHint (se fornecida) ou ao nome de usuário da conta.

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

Sem Dica de Usuário

Se não houver informações suficientes disponíveis sobre o usuário, você pode tentar usar a API ssoSilentsem passar uma account, sid ou login_hint.

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

No entanto, esteja ciente de que, se o seu aplicativo tiver fluxos de código para vários usuários em uma única sessão do navegador, ou se o usuário tiver várias contas nessa mesma sessão do navegador, haverá uma probabilidade maior de erros no login silencioso. Você pode ver o seguinte erro aparecer no caso de várias sessões de conta encontradas pelo servidor de autorização:

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

Isso indica que o servidor não pôde determinar em qual conta entrar e exigirá um dos parâmetros acima (account, , login_hint) sidou uma entrada interativa para escolher a conta.

Warning

Ao usar ssoSilent, o serviço tenta carregar sua página de URI de redirecionamento em um iframe invisível inserido. As políticas de segurança de conteúdo e os valores de cabeçalho HTTP presentes na resposta da página de URI de redirecionamento do aplicativo, como X-FRAME-OPTIONS: DENY e X-FRAME-OPTIONS: SAMEORIGIN, podem impedir que seu aplicativo carregue no iframe, bloqueando efetivamente o SSO silencioso. Se você pretende usar ssoSilent, verifique se o URI de redirecionamento aponta para uma página que não implementa essas políticas.

Considerações de RedirectUri

Todos os fluxos de autenticação agora exigem uma página de redirecionamento dedicada que implementa a ponte de redirecionamento msal. Isso é necessário para dar suporte aos cabeçalhos COOP (Cross-Origin-Opener-Policy) e permitir a comunicação segura entre janelas pop-up/iframe e o aplicativo principal.

Configurando a página de redirecionamento

Seu redirectUri deve apontar para uma página dedicada que carrega o script de redirecionamento. Esta página deve:

  1. Carregar o script de ponte de redirecionamento – Esse script manipula a comunicação com a janela principal
  2. Não incluir nenhum JavaScript, exceto o script de ponte – a página de redirecionamento só deve executar o script de ponte
  3. Não incluir lógica de roteamento – evitar bibliotecas de roteadores que possam interferir no tratamento de hash
  4. Estar registrado no registro do seu aplicativo - O URI deve corresponder exatamente ao que está registrado no portal do Azure

Página de redirecionamento de exemplo (ao usar um empacotador, como Vite ou 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

O especificador @azure/msal-browser/redirect-bridge deve ser resolvido por um empacotador (Vite, Webpack, etc.) — não é uma URL que os navegadores podem acessar diretamente. Para obter instruções específicas da estrutura, consulte o guia de instalação da Ponte de Redirecionamento.

Configuration

Você pode definir o redirectUri globalmente em sua configuração MSAL ou por solicitação:

Configuração global:

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

const msalInstance = new PublicClientApplication(msalConfig);

Configuração por solicitação:

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

Para obter mais informações e concluir implementações de exemplo, consulte:

Como lidar com erros de pop-up interaction_in_progress

Para fluxos pop-up, você pode usar o overrideInteractionInProgress sinalizador para cancelar uma interação pendente e iniciar uma nova. Isso é útil para cenários de recuperação em que o usuário cancelou um pop-up ou uma interação falhou.

Note

Esse recurso só está disponível para fluxos pop-up e não tem suporte para fluxos de redirecionamento. Com o cabeçalho COOP (Cross-Origin-Opener-Policy), a conexão tradicional window.opener é interrompida, permitindo que as janelas pop-up se comuniquem com o frame principal apenas por meio do BroadcastChannel.

Importante

Definir isso como true cancelará à força qualquer solicitação de autenticação em pop-up pendente, mas não fechará nenhum pop-up aberto.

Quando definido como true:

  • Se outra interação pop-up estiver em andamento, ela será cancelada com força, mas todos os pop-ups abertos não serão fechados
  • A interação pendente é rejeitada com erro interaction_in_progress_cancelled
  • O novo fluxo de pop-up prossegue imediatamente

Casos de uso válidos:

  • Recuperando-se de erros em que o usuário cancelou um pop-up (o pop-up foi fechado sem concluir a autenticação)
  • Implementando fluxos de recuperação de erros personalizados
  • Fornecendo um mecanismo de nova tentativa após uma interação com pop-up malsucedida

Padrão:false

Importante: Use apenas ao clicar no botão

Não tente novamente automaticamente ao capturar um interaction_in_progress erro. A sobreposição deve somente ser acionada por uma ação explícita do usuário (como clicar em um botão "Tentar novamente"). A sobreposição automática de interações pode levar a:

  • Condições de corrida entre vários fluxos de autenticação
  • Cancelamentos inesperados de tentativas de autenticação legítimas
  • Experiência ruim do usuário com fluxos de autenticação iniciando e parando inesperadamente
  • Muitos pop-ups estão abertos e não resultarão em respostas de autenticação bem-sucedidas

Exemplo: tratamento adequado de erros com nova tentativa iniciada pelo usuário

Para implementações completas com comentários visuais, consulte:

Ambos os exemplos demonstram:

  • Mensagem de aviso exibida durante a autenticação na janela pop-up
  • Modal/diálogo de "Tentar novamente" com explicação clara quando ocorrer um erro interaction_in_progress
  • Gerenciamento de estado adequado para nova tentativa iniciada pelo usuário
  • Componentes de interface do usuário prontos para produção
// 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
}

Exemplo: componente React com nova tentativa acionada pelo usuário

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

Próximas etapas

Saiba como adquirir e usar um token de acesso!