Modo sudo e reautenticação: perguntar de novo antes das coisas perigosas

Uma sessão diz quem entrou. Ela não diz quem está no teclado agora. Veja como a Nulvless fecha essa lacuna sem desconectar ninguém.

Gleisson MatosFundador e CEO3 min de leitura
Nesta página

Uma sessão é uma afirmação sobre o passado: em algum momento, esta pessoa provou quem era neste dispositivo. Ela não diz nada sobre o presente. O notebook pode estar desbloqueado em uma mesa, o token pode ter sido copiado, ou alguém da família pode ter pegado o celular.

Para quase tudo o que um usuário faz, tudo bem. Para uma lista curta de ações, não, porque essas ações são exatamente o que um atacante precisa para ficar com uma conta: desligar um segundo fator, adicionar o próprio e-mail, trocar a senha, revogar as sessões do dono de verdade.

O modo sudo é como a Nulvless trata essa lista.

Uma janela curta, provada de novo

O modo sudo é uma janela curta em que a pessoa acabou de provar, de novo, que é ela quem está no teclado. Ele não desconecta ninguém e não substitui a sessão. Ele adiciona uma prova recente por cima dela, com prazo para expirar.

Quais ações exigem isso é configuração, definida por ambiente:

GrupoO que protege
manage_mfaCadastrar ou remover fatores, ler códigos de recuperação
manage_credentialsMudanças de credenciais
manage_grantsConvidar, revogar, bloquear, mudar permissões
manage_identitiesAdicionar ou remover um e-mail ou telefone
manage_sessionsRevogar sessões
manage_passwordsTrocar a senha

Uma chave geral liga o modo sudo, e um tempo limite define quanto dura uma elevação.

Não fixe no código quais chamadas precisam dele

Como é configuração, um ambiente pode proteger outro grupo no mês que vem. Código que tenta prever quais chamadas precisam de sudo quebra no dia em que isso acontece. Em vez disso, o SDK avisa quando uma chamada foi recusada por esse motivo:

nulvless.auth.on('sudo-required', async () => {
  await nulvless.auth.sessions.sudo();
  openSudoPrompt();
});

Um único handler cobre todas as chamadas protegidas do app. Na rede, é um 403 com o código protected_action_denied, se você tratar os erros diretamente.

Duas formas de atender

As duas começam igual: sessions.sudo() envia um código e devolve um desafio. O que muda é onde o código é gasto.

Eleve a sessão quando o usuário estiver prestes a fazer várias coisas sensíveis em sequência, como passar por uma tela de configurações de segurança:

await nulvless.auth.sessions.sudo();
const { data } = await nulvless.auth.sessions.sudoVerify({ code });

A sessão é reemitida com sudo ativo, e toda chamada protegida passa até a janela fechar.

Autorize uma chamada quando houver uma única ação destrutiva:

await nulvless.auth.sessions.sudo();
await nulvless.auth.grants.revoke({ id, nonce: code });

O código é gasto só nessa requisição. A sessão nunca é elevada, então nada mais fica liberado como efeito colateral. Esse é o padrão mais seguro.

O nonce é o código

nonce não é um token separado. É o código que o usuário digitou, conferido contra o desafio de sudo já pendente para a sessão dele. Ele é de uso único e viaja no header nlv-sudo-nonce.

A mesma garantia na sua própria API

Sua API provavelmente tem ações que a plataforma não conhece: apagar um workspace, rotacionar uma das suas próprias chaves de API. Elas merecem a mesma checagem. O navegador obtém o código exatamente como acima e o envia junto, e o seu handler repassa para a chamada protegida:

app.delete('/keys/:id', requireAuth, async (req, res) => {
  const { error } = await nulvless.auth.sessions.revoke({
    id: req.params.id,
    nonce: req.headers['nlv-sudo-nonce'] as string,
  });

  if (error) return res.status(403).json({ error });
  res.status(204).end();
});

Construa com seu agente

Um prompt pronto para Claude Code, Cursor, ChatGPT ou qualquer agente de código. Ele aponta o agente para este guia e para as docs, para que siga a API real em vez de adivinhar.

Proteja as ações sensíveis do meu app com o modo sudo da Nulvless.

Siga estas páginas. Elas documentam a API real, então não invente nomes de métodos:
- https://www.nulvless.com/pt/llms.mdx/blog/sudo-mode/content.md
- https://www.nulvless.com/pt/llms.mdx/docs/guides/sudo/content.md
- https://www.nulvless.com/pt/llms.mdx/docs/sdk/sessions/content.md

Requisitos:
- Não fixe no código quais chamadas precisam de sudo. Registre um único handler para o evento sudo-required que chama auth.sessions.sudo() e abre um campo para o código.
- Para uma única ação destrutiva, passe o código como nonce nessa chamada em vez de elevar a sessão.
- Na minha própria API, leia o header nlv-sudo-nonce e repasse para a chamada protegida da Nulvless. Retorne 403 quando falhar.
- Mantenha as checagens de autorização separadas. Sudo prova que a pessoa está presente, não que ela tem permissão.
ou abra no

O que sudo não é

Sudo não é uma checagem de permissão. Ele responde "esta pessoa ainda está aqui?", não "ela pode fazer isso?". Um usuário com a sessão recém-elevada ainda falha em uma checagem de autorização para a qual não tem a concessão. As duas rodam de forma independente, e uma ação sensível normalmente quer as duas.

A própria Nulvless usa o modo sudo: fazer merge de configuração de um ambiente para outro pede sudo, e a confirmação dura uma hora para que uma série de promoções pergunte uma vez só. Você pode ler sobre esse fluxo em Por que usuários de staging nunca chegam à produção, e sobre cada opção no guia de modo sudo. Para exigir sudo dentro de uma edge function, veja Autenticação de usuários em edge functions.

Continue lendo