Estou criando uma API RESTful que usa tokens JWT para autenticação do usuário (emitidos por um login
nó de extremidade e enviados em todos os cabeçalhos posteriormente), e os tokens precisam ser atualizados após um período fixo de tempo (invocando um renew
nó de extremidade, que retorna um token renovado )
É possível que a sessão da API de um usuário se torne inválida antes que o token expire, portanto, todos os meus pontos de extremidade começam verificando: 1) o token ainda é válido e 2) a sessão do usuário ainda é válida. Não há como invalidar diretamente o token, porque os clientes o armazenam localmente.
Portanto, todos os meus pontos de extremidade precisam sinalizar para meus clientes duas condições possíveis: 1) que é hora de renovar o token ou 2) que a sessão se tornou inválida e que eles não têm mais permissão para acessar o sistema. Posso pensar em duas alternativas para meus pontos de extremidade sinalizarem seus clientes quando uma das duas condições ocorrer (suponha que os clientes possam ser adaptados a qualquer uma das opções):
- Retorne um código http 401 (não autorizado) se a sessão se tornar inválida ou retorne um código 412 (falha na pré-condição) quando o token expirar e for hora de chamar o
renew
terminal, que retornará um código 200 (ok). - Retorne 401 para sinalizar que a sessão é inválida ou que o token expirou. Nesse caso, o cliente chamará imediatamente o
renew
terminal, se retornar 200, o token será atualizado, mas serenew
também retornar 401, significa que o cliente está fora do sistema.
Qual das duas alternativas acima você recomendaria? Qual deles seria mais padrão, mais simples de entender e / ou mais RESTful? Ou você recomendaria uma abordagem completamente diferente? Você vê algum problema óbvio ou risco à segurança com qualquer uma das opções? Pontos extras se sua resposta incluir referências externas que apóiam sua opinião.
ATUALIZAR
Pessoal, por favor, concentrem-se na questão real - qual das duas alternativas de código http para sinalizar uma invalidação de renovação / sessão é a melhor? Não se importe com o fato de meu sistema usar sessões JWT e do lado do servidor, essa é uma peculiaridade da minha API para regras de negócios muito específicas, e não a parte para a qual estou procurando ajuda;)
fonte
Respostas:
Isso soa como um caso de autenticação versus autorização .
JWTs são reivindicações criptograficamente assinadas sobre o originador de uma solicitação. Um JWT pode conter declarações como "Esta solicitação é para o usuário X" e "O usuário X tem funções de administrador". Obter e fornecer essa prova por meio de senhas, assinaturas e TLS é o domínio da autenticação - provando que você é quem diz ser.
O que essas declarações significam para o servidor - o que usuários e funções específicos podem fazer - é o problema da autorização . A diferença entre os dois pode ser descrita em dois cenários. Suponha que Bob queira entrar na seção de armazenamento restrito do armazém de sua empresa, mas primeiro ele deve lidar com um guarda chamado Jim.
Cenário A - Autenticação
Cenário B - Autorização
Os tempos de expiração do JWT são um dispositivo de autenticação usado para impedir que outros os roubem. Se todas as suas JWTs tiverem um prazo de validade de cinco minutos, não será tão grande coisa se elas forem roubadas porque elas rapidamente se tornarão inúteis. No entanto, a regra "expiração da sessão" que você discute parece um problema de autorização. Alguma mudança de estado significa que o usuário X não tem mais permissão para fazer algo que costumava fazer. Por exemplo, o usuário Bob pode ter sido demitido - não importa que seu crachá diga que ele é mais Bob, porque simplesmente ser Bob não lhe dá mais autoridade na empresa.
Esses dois casos têm códigos de resposta HTTP distintos:
401 Unauthorized
e403 Forbidden
. Infelizmente, o código 401 é indicado para problemas de autenticação, como credenciais ausentes, expiradas ou revogadas. 403 é para autorização, onde o servidor sabe exatamente quem você é, mas você simplesmente não tem permissão para fazer o que está tentando fazer. No caso de a conta de um usuário ser excluída, tentar fazer algo com um JWT em um nó de extremidade resultaria em uma resposta 403 Proibida. No entanto, se o JWT expirar, o resultado correto será 401 Não autorizado.Um padrão JWT comum é ter tokens de "longa vida" e "curta duração". Os tokens de longa duração são armazenados no cliente como tokens de curta duração, mas têm escopo limitado e são usados apenas com o seu sistema de autorização para obter tokens de curta duração. Os tokens de longa duração, como o nome indica, têm períodos de validade muito longos - você pode usá-los para solicitar novos tokens por dias ou semanas a fio. Os tokens de vida curta são aqueles que você está descrevendo, usados com tempos de expiração muito curtos para interagir com seu sistema. Os tokens de longa duração são úteis para implementar a funcionalidade Remember Me, para que você não precise fornecer sua senha a cada cinco minutos para obter um novo token de curta duração.
O problema da "invalidação de sessão" que você está descrevendo parece semelhante à tentativa de invalidar uma JWT de longa duração, pois as de curta duração raramente são armazenadas no lado do servidor, enquanto as de longa duração são rastreadas caso precisem ser revogadas. Nesse sistema, tentar adquirir credenciais com um token de longa duração revogado resultaria em 401 não autorizado, porque o usuário pode tecnicamente adquirir credenciais, mas o token que está usando não é adequado para a tarefa. Então, quando o usuário tentar adquirir um novo token de longa duração usando seu nome de usuário e senha, o sistema poderá responder com 403 Proibido se for expulso do sistema.
fonte
Sua sessão da API é algo que não deveria existir em um mundo RESTful. As operações RESTful devem ser sem estado, a sessão contém estado e, portanto, não tem lugar em um mundo RESTful.
O JWT deve ser sua única maneira de determinar se um usuário ainda é elegível para acessar um terminal ou não. Uma sessão não deve desempenhar absolutamente nenhum papel nela. Caso isso aconteça, você não possui uma API RESTful.
Quando você elimina a sessão completamente, o que, se você deseja uma API RESTful, deve fazer e usar apenas o JWT como um fator de autenticação, um usuário está autorizado a usar seu terminal ou não - nesse caso, o
401 Unauthorized
código de resposta é apropriado - e deve ligar para orenew
terminal comgrant_type=refresh_token
ou qualquer identificação de renovação que você esteja usando.Atualizar:
Pelo comentário, parece que o fluxo de validação do JWT que você está usando no momento não está correto. A validação deve ficar assim:
O servidor
RESTful API
,, deve verificar a validade do token que está sendo enviado como a autorização. Essa não é a responsabilidade doClient
. Parece que você não está fazendo isso no momento. Implemente a verificação do JWT dessa maneira e você não precisa de sessões.fonte
Portanto, confesso que não faz muito sentido me preocupar com qual abordagem é mais RESTful quando você já está violando as convenções REST com a sessão, mas entendo satisfazer os requisitos de negócios.
Do ponto de vista REST, o cliente é autenticado ou não. A arquitetura não se importa muito com o motivo (que está injetando um estado desnecessário); portanto, para responder à sua pergunta principal, eu não teria um ponto de extremidade renovado. Um cliente conectado sempre envia seu JWT sempre e o servidor sempre o valida e aceita enviando o código de Sucesso apropriado com base nas ações 200, 201, etc.) ou rejeitando com um 401 ou 403, conforme apropriado.
Agora, o JWT será associado a uma conta de algum tipo. Essa conta pode estar bloqueada ou estrangulada ou o que for, e assim o próprio token pode ser válido, mas a ação ainda será rejeitada em outro lugar. Se for o caso de a conta do usuário estar bloqueada por causa das regras de negócios, ainda será 401 ou 403, dependendo da quantidade de informações que você deseja fornecer ao cliente (empresas diferentes têm opiniões diferentes sobre isso).
Finalmente, se você está afirmando que a conta pode ser desbloqueada e válida, mas o JWT só precisa ser revogado, AINDA continuarei com o 401 ou 403 e manteria algo como uma lista de revogação de certificado de JWTs inválidos nos quais você pode colocar um , desde que se limpe quando o JWT expirou (a maioria dos bancos de dados tem uma maneira de fazer isso ou você pode ter eventos no código do aplicativo).
fonte