# Reautenticação facial

<https://unifokal.com/docs/modulos/face-reauth>

## Reautenticação facial

O módulo `face_reauth` reconfirma, numa ação sensível (um saque, uma troca de chave Pix, um login em aparelho novo), que quem age agora é a **mesma pessoa** que você já aprovou no onboarding. O titular faz a prova de vida e uma selfie, e o módulo compara essa selfie com a **matrícula biométrica** daquela conta, sem pedir documento e sem refazer o onboarding. É **step-up sob evento**, disparado pelo seu backend quando ele decide que a ação merece biometria, e nunca uma checagem contínua rodando em segundo plano.

! **Em breve.** A venda deste módulo está pausada: ele aparece na [tabela de preços](https://unifokal.com/precos) com preço e com o selo "Em breve", e o `create` de flow o recusa até a abertura. A criação de sessão de reautenticação também ainda não está publicada. O que está descrito abaixo é o contrato de resposta que o backend já emite, para você planejar a integração, não uma porta que dá para chamar hoje.

**A matrícula é a referência, e ela é sua.** Ela nasce de graça num onboarding aprovado: você marca o flow de onboarding para matricular, esse flow precisa ter `face` e `liveness`, e a matrícula é criada quando a verificação aprova **pelo caminho automático**, fora do sandbox e com o desafio de gestos cumprido. Aprovação manual na fila de revisão **não** matricula, e o sandbox também não: matrícula biométrica nasce de prova, nunca de decisão de operador. Existe uma matrícula ativa por conta (o seu `reference_id`), dentro da sua organização e do seu ambiente: não há base compartilhada entre clientes, e a comparação nunca acontece contra o índice de detecção de múltiplas contas, que serve a outra pergunta. Você paga a autenticação, nunca a matrícula.

**O flow de reautenticação é curto de propósito:** `liveness` mais `face_reauth`, sem documento. A prova de vida é **exigida** pelo catálogo, e o motivo é direto: sem ela, a foto impressa do titular bateria contra a matrícula e a reautenticação entregaria a conta. Pelo mesmo raciocínio, `face_reauth` não convive com `face` nem com `doclink` no mesmo flow: os dois comparam contra outra referência, e num flow sem documento o `face` nunca teria a foto do documento para comparar. Flow com reautenticação também desliga a renovação de sessão pelo widget: quem decide quando exigir biometria é o seu backend, não o navegador do titular.

```
// face_reauth no check_details: é a mesma pessoa da matrícula
{ "module": "face_reauth", "passed": true, "outcome": "approved", "score": 92,
  "data": { "match": true,                  // a resposta: true | false | null (indeterminado)
            "similarity": 0.83,             // cosseno 0..1 contra a matrícula
            "similarity_band": "high",      // high | gray | low
            "enrolled_at": "2026-03-02T18:20:11.000Z",
            "enrollment_age_days": 159,     // idade da matrícula, para a sua política
            "model_version": "face-reauth-v1" } }

// face_reauth: a comparação foi MEDIDA e não bateu (portão duro: reprova)
{ "module": "face_reauth", "passed": false, "outcome": "failed", "score": 40,
  "data": { "match": false, "similarity": 0.21, "similarity_band": "low",
            "enrolled_at": "2026-03-02T18:20:11.000Z", "enrollment_age_days": 159,
            "reason": "reauth_mismatch",
            "model_version": "face-reauth-v1" } }

// face_reauth: banda de dúvida (o cosseno ficou entre os dois limiares). Revisão humana,
// nunca recusa automática, e SEM "reason": quem identifica o caso é a própria banda.
{ "module": "face_reauth", "passed": null, "outcome": "pending", "score": 80,
  "data": { "match": null, "similarity": 0.39, "similarity_band": "gray",
            "enrolled_at": "2026-03-02T18:20:11.000Z", "enrollment_age_days": 159,
            "model_version": "face-reauth-v1" } }

// face_reauth: não havia matrícula utilizável (nunca houve, foi revogada ou venceu).
// Também revisão, e aqui o "reason" vem preenchido.
{ "module": "face_reauth", "passed": null, "outcome": "pending", "score": 80,
  "data": { "match": null, "similarity": null, "similarity_band": null,
            "enrolled_at": null, "enrollment_age_days": null,
            "reason": "reauth_enrollment_unavailable",
            "model_version": "face-reauth-v1" } }
```

No resumo `checks` o módulo sai com o vocabulário da própria pergunta: `"face_reauth": "match"`, `"no_match"` ou `"pending"`. O `pending` cobre toda a família de revisão. Na **banda de dúvida** o `reason` não vem, e quem identifica o caso é o `similarity_band` igual a `"gray"`; nos demais casos de revisão o `reason` vem preenchido.

**Os três caminhos de recusa por veredito, e só eles:** a comparação medida abaixo do limiar (`reauth_mismatch`), o desafio de gestos executado por um rosto e a selfie enviada de outro (`challenge_selfie_mismatch`) e o documento que você mesmo pôs na sua lista de bloqueio (`document_blocklisted`). Todo o resto que dependa do titular é **revisão**, e essa escolha é deliberada: quem não tem matrícula, ou está com a matrícula vencida, não tem selfie nenhuma que possa tirar para fazer aparecer uma matrícula que não existe, e recusar seria punir o titular legítimo pela ausência de um dado nosso.

Existe ainda um **quarto desfecho**, e ele não é um veredito sobre a pessoa: quando a falha é **nossa** (a selfie não chegou, o serviço de visão não respondeu, a consulta à matrícula falhou), o módulo sai `failed` e **sem o bloco `data`**. Bloco ausente é a assinatura de erro interno, nunca de fraude: a leitura correta é repetir a autenticação, e jamais punir a conta por ela.

Os motivos que chegam a você em `data.reason`: `reauth_mismatch` (recusa medida), `document_blocklisted` (o documento estava na sua lista de bloqueio), `challenge_selfie_mismatch` (o vínculo entre desafio e selfie reprovou), `reauth_binding_unavailable` (não foi possível provar esse vínculo, que é diferente de tê-lo provado falso), `reauth_enrollment_unavailable` (sem matrícula utilizável, incluindo a vencida), `reauth_locked` (matrícula travada por tentativas seguidas que não bateram), `reauth_rate_limited` (teto de tentativas da conta estourado), `reauth_capture_unusable` (a captura não serviu) e `reauth_embedder_drift` (a matrícula foi feita com outra versão do extrator e comparar seria comparar espaços diferentes).

O `reauth_rate_limited` sai como **429 com o cabeçalho** `Retry-After`, sempre em segundos e sempre um prazo real: é quando a vaga efetivamente abre para aquela conta, nunca um número fixo. Respeite o cabeçalho em vez de retentar em laço; a conta tem mais de um relógio, e quando mais de um está cheio o prazo devolvido já é o do relógio que libera por último. Esperar o que o cabeçalho diz basta: você não vai gastar uma chamada para descobrir que ainda falta outra espera.

! **Trate o `reauth_locked` como um evento de segurança.** Ele significa tentativas seguidas contra a matrícula daquela conta, e travar a conta do seu lado é a única reação que encerra um ataque de força bruta de rosto. O titular, por outro lado, recebe sempre o mesmo motivo genérico: os códigos finos existem para o seu backend e para a sua fila de revisão, nunca para quem está do outro lado da câmera.

**A matrícula tem prazo, e ele é curto por escolha.** Cada autenticação aprovada renova a guarda por 180 dias; quem passa 180 dias sem reautenticar perde a matrícula, que deixa de valer e entra na fila de expurgo, e existe um teto absoluto de um ano desde a criação. Passado o prazo, a próxima reautenticação sai como `pending` com `reauth_enrollment_unavailable`, e o caminho é refazer o onboarding, que cria uma matrícula nova.

**No painel.** A matrícula se liga no construtor de flow, na opção **Criar matrícula para reautenticação facial**, que só aparece habilitada quando o flow tem Face Match e Liveness (pela API, o campo é `enroll_reauth`, e o mesmo par de módulos é exigido, com o erro `enroll_reauth_requires_face_liveness`). O estado da matrícula de cada titular (ativa, travada, vencida ou ausente), com a data de criação e a validade, aparece no detalhe de qualquer verificação dele e na linha dele em Sessões. O painel mostra estado e datas, nunca o modelo do rosto.

**Matrícula travada não se destrava.** Um proprietário ou administrador da sua conta pode **revogar** a matrícula pelo painel, a partir da verificação ou da sessão do titular. A revogação pede o segundo fator de quem revoga e fica registrada com quem fez e quando. Depois dela, a matrícula renasce no próximo onboarding aprovado daquele titular. É também o que fazer quando você descobre que a conta foi tomada: tirar a matrícula até a pessoa provar de novo quem é.

**Tenha sempre um caminho sem biometria.** A reautenticação facial confirma que é a mesma pessoa, e não deve ser a única porta para a ação sensível: ofereça ao titular uma alternativa que não dependa do rosto dele. A aprovação com passkey, vinculada à conta do titular, é esse caminho no produto e está em breve.
