Documentação

Sessões e tokens

O que mantém alguém autenticado, o que encerra isso, e as configurações que decidem os dois.

Três coisas são fáceis de confundir, e quase todo bug de sessão vem de tratá-las como uma só:

a sessãoregistro no servidor

Um período autenticado, num dispositivo. Tem id, impressão digital e expiração. É o que você revoga.

o access tokencurta duração

O que viaja em cada requisição. Rotaciona o tempo todo e não vale rastrear.

o refresh tokenlonga duração

O que compra o próximo access token. Vinculado a uma sessão — não ao usuário.

A sessão dura o que o refresh token durar

É esta a regra que vale internalizar, porque é onde as configurações encontram a realidade.

Com refresh tokens habilitados, a sessão expira quando o refresh token expira. O access token expirar no meio do caminho é um não-evento: o SDK troca ele e o usuário não percebe nada.

Com eles desabilitados, a sessão expira quando o access token expira. Não há com o que renovar, então "fique conectado por 30 dias" vira "fique conectado por uma hora" — a mesma configuração, um produto completamente diferente.

Elas ficam no console, em Autenticações.

Expiração do token de acesso

Por quanto tempo um access token vale. Curto é mais seguro: um token vazado tem uma janela menor.

Habilitar token de atualização

Se as sessões podem sobreviver a um access token.

Tempo limite do token de atualização

A resposta real para "por quanto tempo as pessoas ficam conectadas".

A renovação é automática, e não vale brigar com ela

O cliente de navegador renova por dois gatilhos, e você não dirige nenhum. Ele renova sob demanda com uma margem de 90 segundos — peça um token que expira em menos que isso e ele é renovado antes de ser entregue — e renova por tempo, verificando a cada 30 segundos, para que uma sessão que ninguém está usando também nunca vença.

const token = await nulvless.auth.getAccessToken();

É essa a API inteira. O erro a evitar é guardar a string:

// Errado — este token vai acabar sendo rejeitado.
const token = await nulvless.auth.getAccessToken();
setInterval(() => fetch('/api/things', { headers: auth(token) }), 60_000);

Peça de novo a cada requisição. É leitura de memória quando o token está fresco, e a margem existe justamente para ele nunca ser entregue prestes a expirar.

Para qualquer coisa que segure o token fora do SDK — um websocket, um worker — assine em vez de consultar:

nulvless.auth.on('token-refreshed', (session) => {
  socket.updateAuth(session.access_token);
});

Saber quando realmente acabou

Um 401 de uma chamada não significa que a sessão acabou. Normalmente significa que o access token expirou, e o SDK renova e repete.

A sessão acabou quando a renovação falha, e existe um sinal só para isso:

nulvless.auth.on('unauthorized', () => {
  clearAppState();
  router.push('/sign-in');
});

Não fique consultando getSession() para detectar isso. É mais lento, custa uma requisição por ciclo, e mesmo assim não diz nada entre um ciclo e outro. O evento dispara no instante em que o SDK desiste.

Encerrando sessões

Quatro formas, e elas não são intercambiáveis:

signOut()este dispositivo

O caso comum. Limpa o armazenamento local só depois de o servidor confirmar.

signOut('others')todos os outros

Mantém o usuário onde ele está. É o que "desconectar meus outros dispositivos" deve chamar.

signOut('global')todos, inclusive este

Combine com uma troca de senha depois de suspeita de comprometimento.

sessions.revoke({ id })uma sessão específica

A partir da lista de "onde você está conectado". Protegido por sudo.

Como o refresh token é vinculado a uma sessão, revogar a sessão mata o refresh token junto. Não há como uma sessão revogada se renovar de volta à existência.

A tela de "onde você está conectado"

const { data: sessions } = await nulvless.auth.sessions.list();

Tudo que a tela precisa está em cada entrada: finger_print para a linha de dispositivo e localização, amr para como entrou, created_at para quando, e is_current_session para o selo de "este dispositivo".

O finger_print só é preenchido quando o client foi criado com trackUser: true — e, no servidor, só quando você repassa os headers do usuário com forwardUserHeaders. Sem um dos dois, toda sessão aparece vindo da sua infraestrutura, o que deixa a tela pior que inútil: parece que a conta foi acessada de um data center.

Claims customizadas

Um ambiente pode injetar claims próprias no access token, a partir de um template. Se a sua própria API lê o JWT direto em vez de chamar verify, é assim que ela recebe os seus campos sem uma segunda consulta.

Ainda assim prefira o verify quando a pergunta é sobre permissão — uma claim é uma fotografia de quando o token foi emitido, e um grant revogado desde então continua lá dentro.

Próximos

Nesta página