> ## Documentation Index
> Fetch the complete documentation index at: https://supastack.dev/llms.txt
> Use this file to discover all available pages before exploring further.
> For the full documentation corpus in one file, fetch: https://supastack.dev/llms-full.txt

# Início de sessão com passkey

Início de sessão sem palavra-passe através de um handoff pelo browser que devolve a sessão à app.

## Como funciona o handoff

O início de sessão com passkey começa na app e termina no browser do sistema. A app abre {API URL}/auth?mobile_callback=<deep link> através de WebBrowser.openAuthSessionAsync; depois de a página web concluir qualquer método de início de sessão, chama GET /api/auth/mobile-handoff, que redireciona de volta para <scheme>://auth/callback trazendo o cookie de sessão e um nonce de state.

Cada tentativa gera um nonce novo que tem de fazer a viagem de ida e volta inalterado — um parâmetro state diferente é rejeitado como stateMismatch, por isso um callback velho ou forjado não consegue injetar uma sessão. O cookie devolvido junta-se ao mesmo jar do SecureStore que o cliente Better Auth Expo usa (supastack.auth_cookie); depois a store de sessão é notificada e a app com sessão iniciada renderiza.

Um sheet de browser dispensado resolve-se num resultado silencioso cancelled em vez de um erro, por isso mantém o ecrã de início de sessão inalterado quando isso acontece.

```
# apps/mobile/.env.local
EXPO_PUBLIC_APP_SCHEME=supastack

# apps/web/.env.local — server side
AUTH_PASSKEY_ENABLED=true
MOBILE_ALLOWED_ORIGINS=
```


## Mantém a allow-list idêntica dos dois lados

Os dois lados validam o destino do callback: a app aceita apenas <scheme>://auth mais as suas origens de produção configuradas, e o servidor verifica a mesma lista construída a partir de EXPO_PUBLIC_APP_SCHEME e MOBILE_ALLOWED_ORIGINS. Callbacks com credenciais, esquemas desconhecidos ou sufixos parecidos são rejeitados antes de qualquer cookie se mover.

Em produção MOBILE_ALLOWED_ORIGINS é obrigatória e tem de listar origens HTTPS exatas e não-locais — wildcards não são aceites. A app sai empacotada enquanto o servidor lê o seu ambiente por pedido, por isso uma mudança de scheme ou origem exige um novo build da app e um deploy do servidor; mudar só um lado faz os handoffs falhar fechado.


## Os outros métodos sem palavra-passe

O mesmo ecrã de início de sessão oferece códigos de uso único por email (requestEmailOtp seguido de verifyEmailOtp) e início de sessão social Apple ou Google através de signIn.social com um callbackURL. As passkeys aparecem quando AUTH_PASSKEY_ENABLED=true no servidor; a configuração de passkey e de dois fatores de uma conta continua na app web em Configurações → Segurança.


## Verificação e resolução de problemas

Exercita um callback de arranque a frio, um regresso a uma app em execução, um sheet de browser cancelado e uma sessão expirada no build pretendido. As falhas tipadas — passkeyUnavailable, browserFailed, untrustedCallback, missingCookie, malformedCookie, cookieStoreFailed — descrevem cada uma uma quebra distinta; stateMismatch significa que o nonce não fez a viagem de ida e volta e a tentativa foi recusada corretamente.

Se todos os handoffs forem rejeitados, compara o EXPO_PUBLIC_APP_SCHEME do build publicado com o scheme e o MOBILE_ALLOWED_ORIGINS do servidor — o par desalinha quando um lado foi redesenvolvido sem o outro.


## Seguinte

[API mobile](https://supastack.dev/pt/docs/mobile/api.md)
