Verificação pós primeiro fator
A Ação de verificação pós primeiro fator oferece suporte à migração de usuários just-in-time de um sistema de senha legado.
Apesar do nome, esta Ação não é executada após todo primeiro fator bem-sucedido. Ela só é executada quando todas as seguintes condições são verdadeiras:
- A interação da Experience API é
SignIn. - O usuário enviou um nome de usuário, endereço de e-mail ou número de telefone com uma senha.
- A verificação de senha local do Logto falhou.
- Se o identificador pertence a um usuário Logto existente, esse usuário não está suspenso.
Se a senha local for válida, o Logto continua sem executar a Ação. Tentativas de registro, esqueci a senha, login sem senha e usuários suspensos não a acionam.
Payload do evento
O event tem este formato:
type PostFirstFactorVerificationEvent = {
// Mantido para compatibilidade retroativa após o recurso ser renomeado para Actions.
key: 'inlineHook.postFirstFactorVerification';
interactionEvent: 'SignIn';
verificationType: 'Password';
identifier: {
type: 'username' | 'email' | 'phone';
value: string;
};
user: {
id: string;
username: string | null;
primaryEmail: string | null;
primaryPhone: string | null;
name: string | null;
avatar: string | null;
customData: Record<string, unknown>;
profile: Record<string, unknown>;
} | null;
password: string;
};
user é null quando o identificador não pertence a um usuário Logto. Caso contrário, contém o contexto editável do perfil do usuário existente.
event.password é a senha em texto puro enviada pelo usuário. Envie-a apenas para o seu endpoint de autenticação legado confiável via HTTPS. Nunca registre, armazene, coloque em customData, inclua em um erro ou retorne da Ação.
Resultado
Após o sistema legado verificar as credenciais enviadas, retorne um destes resultados:
type PostFirstFactorVerificationResult =
| {
action: 'createUser';
passwordVerified: true;
user: ActionUserPatch;
}
| {
action: 'updateUser';
passwordVerified: true;
user: ActionUserPatch;
};
O resultado deve corresponder ao evento:
- Quando
event.userénull, retornecreateUser. - Quando
event.userestá presente, retorneupdateUser. passwordVerifieddeve ser literalmentetrue.userpode conter apenas os campos suportados de patch de usuário.
Para um novo usuário, o Logto adiciona o identificador de login enviado quando o resultado não o inclui. A Ação não pode alterar o identificador enviado para outro valor. A comparação de e-mails é case-insensitive, números de telefone são comparados após normalização e nomes de usuário devem coincidir exatamente.
Quando o resultado é aceito, o Logto faz o hash da senha enviada com Argon2i e a salva como senha local do usuário. O script não deve gerar ou retornar um hash de senha.
Retorne undefined quando o sistema legado rejeitar as credenciais. Um resultado vazio, malformado ou não suportado também é tratado como credenciais inválidas.
Exemplo de migração
Configure LEGACY_VERIFY_URL e LEGACY_API_TOKEN como variáveis de ambiente da Ação, depois adapte este script para sua API legada:
const runAction = async ({ event, environmentVariables = {} }) => {
const response = await fetch(environmentVariables.LEGACY_VERIFY_URL, {
method: 'POST',
headers: {
'content-type': 'application/json',
authorization: `Bearer ${environmentVariables.LEGACY_API_TOKEN}`,
},
body: JSON.stringify({
identifier: event.identifier,
password: event.password,
}),
});
// Trate uma rejeição de autenticação como um resultado comum de credenciais inválidas.
if (response.status === 401 || response.status === 404) {
return;
}
if (!response.ok) {
throw new Error(`O serviço de autenticação legado retornou ${response.status}`);
}
const legacyUser = await response.json();
if (!legacyUser.passwordVerified) {
return;
}
return {
action: event.user ? 'updateUser' : 'createUser',
passwordVerified: true,
user: {
...(legacyUser.name && { name: legacyUser.name }),
customData: {
migratedFrom: 'legacy',
legacyUserId: legacyUser.id,
},
},
};
};
O primeiro login aceito funciona da seguinte forma:
- A verificação de senha local falha, então o Logto executa a Ação.
- O script envia o identificador e a senha para o sistema legado.
- O sistema legado verifica as credenciais e o script retorna
createUserouupdateUser. - O Logto cria ou atualiza o usuário e armazena a senha enviada como uma nova credencial local Argon2i.
- O usuário completa a MFA se necessário, e o Logto conclui o login.
- Em logins posteriores, a senha local migrada é aceita, então esta Ação não é mais chamada para esse usuário.
Limites de segurança
Gravações de usuário e senha desta Ação ocorrem antes da conclusão da MFA. Se o usuário abandonar ou falhar na MFA, essas gravações permanecem.
Um usuário criado por esta Ação também ignora proteções exclusivas de registro, incluindo listas de bloqueio de e-mail, regras de domínio apenas SSO, modo de cadastro desativado e verificações obrigatórias de perfil no registro. A proteção Sentinel e a MFA ainda se aplicam.
Use estas salvaguardas:
- Retorne
passwordVerified: trueapenas após o sistema legado ter verificado positivamente a senha exata enviada. - Mantenha o endpoint legado privado sempre que possível, exija autenticação de serviço, use HTTPS e aplique limitação de taxa.
- Mantenha o patch de usuário retornado mínimo. Não copie identificadores ou dados de perfil não validados.
- Teste criação de usuário desconhecido, atualização de usuário existente, colisões de identificador, usuários suspensos, MFA, falhas upstream e tentativas concorrentes.
- Monitore
Action.PostFirstFactorVerificationnos logs de auditoria. - Mantenha a Ação habilitada apenas durante a migração, quando possível.
Se você puder exportar dados de usuário e hashes de senha compatíveis com antecedência, considere a migração em massa de usuários.