Segurança da API REST Token armazenado vs JWT vs OAuth

92

Ainda estou tentando encontrar a melhor solução de segurança para proteger a API REST, porque a quantidade de aplicativos e APIs móveis está aumentando a cada dia.

Eu tentei diferentes formas de autenticação, mas ainda tem alguns mal-entendidos, então eu preciso de conselhos de alguém mais experiente.

Deixe-me dizer, como eu entendo tudo isso. Se eu entendi algo incorretamente, por favor me avise.

Na medida em que a API REST é stateless, assim como a WEB em geral, precisamos enviar alguns dados de autenticação em cada solicitação (cookies, token ...). Eu conheço três mecanismos amplamente utilizados para autenticar o usuário

  1. Token com HTTPS. Eu usei essa abordagem muitas vezes é bom o suficiente com HTTPS. Se o usuário fornecer a senha e o login corretos, ele receberá o token em resposta e o usará para as solicitações posteriores. Token é gerado pelo servidor e armazenado, por exemplo, na tabela separada ou a mesma onde as informações do usuário são armazenadas. Portanto, para cada servidor de solicitações, verifica se o usuário tem token e é o mesmo que no banco de dados. Tudo é bem direto.

  2. Token do JWT. Esse token é autodescritivo, contém todas as informações necessárias sobre o próprio token, o usuário não pode alterar por exemplo a data de expiração ou qualquer outra declaração, porque esse token é gerado (assinado) pelo servidor com a palavra-chave secreta. Isso também é claro. Mas um grande problema, pessoalmente para mim, é invalidar o token.

  3. OAuth 2. Não entendo por que essa abordagem deve ser usada quando a comunicação é estabelecida diretamente entre o servidor e o cliente. Tanto quanto eu entendo, o servidor OAuth é usado para emitir token com escopo restrito para permitir que outros aplicativos acessem informações do usuário sem armazenar senha e login. Esta é uma ótima solução para as redes sociais, quando o usuário quer se inscrever em alguma página, o servidor pode solicitar permissões para obter informações do usuário, por exemplo, do twitter ou facebook, e preencher campos de registro com dados do usuário e assim por diante.

Considere clientes móveis para lojas on-line.

Primeira pergunta devo preferir o JWT ao primeiro tipo de token? Tanto quanto eu preciso de login / logout usuário no cliente móvel, eu preciso armazenar token em algum lugar ou no caso de JWT, token deve ser invalidado no logout. Abordagens diferentes são usadas para invalidar o token, uma das quais é criar uma lista de tokens inválidos (lista negra). Hmm. A tabela / arquivo terá um tamanho muito maior do que se o token fosse armazenado na tabela e associado ao usuário e apenas removido no logout.

Então, quais são os benefícios do token JWT?

Segunda pergunta sobre o OAuth, devo usá-lo em caso de comunicação direta com o meu servidor? Qual é o propósito de mais uma camada entre cliente e servidor apenas para emitir o token, mas a comunicação não será com o servidor oauth, mas com o servidor principal. Pelo que entendi o servidor OAuth é responsável apenas por dar permissões de aplicativos de terceiros (tokens) para acessar informações privadas do usuário. Mas meu aplicativo cliente móvel não é de terceiros.

    
por CROSP 04.10.2015 / 21:22
fonte

3 respostas

77

Considere o primeiro caso. Cada cliente recebe um ID aleatório que dura a duração da sessão - o que pode levar vários dias, se desejar. Então você armazena as informações relevantes para aquela sessão em algum lado do servidor. Pode estar em um arquivo ou banco de dados. Vamos supor que você passe o ID por meio de um cookie, mas você pode usar o URL ou um cabeçalho HTTP.

IDs de sessão / cookies

Prós:

  • Fácil de codificar o cliente e o servidor.
  • Fácil de destruir uma sessão quando alguém faz logout.

Contras:

  • O servidor periodicamente precisa excluir as sessões expiradas em que o cliente não efetuou o logout.
  • Toda solicitação HTTP exige uma pesquisa no armazenamento de dados.
  • Os requisitos de armazenamento aumentam à medida que mais usuários têm sessões ativas.
  • Se houver vários servidores HTTP front-end, os dados da sessão armazenada precisam estar acessíveis a todos eles. Isso poderia ser um pouco mais de trabalho do que armazená-lo em um servidor. Os problemas maiores são o armazenamento de dados se torna um ponto único de falha e pode se tornar um gargalo.

JSON Web Tokens (JWT)

No segundo caso, os dados são armazenados em um JWT transmitido em vez de no servidor.

Prós:

  • Os problemas de armazenamento do lado do servidor desapareceram.
  • O código do lado do cliente é fácil.

Contras:

  • O tamanho do JWT pode ser maior que um ID de sessão. Isso pode afetar o desempenho da rede, já que está incluído em cada solicitação HTTP.
  • Os dados armazenados no JWT podem ser lidos pelo cliente. Isso pode ser um problema.
  • O lado do servidor precisa de código para gerar, validar e ler JWTs. Não é difícil, mas há uma curva de aprendizado e a segurança depende disso.

    Qualquer pessoa que receber uma cópia da chave de assinatura poderá criar JWTs. Você pode não saber quando isso acontece.

    Houve (é?) um erro em algumas bibliotecas que aceitaram qualquer JWT assinado com o algoritmo "nenhum", para que qualquer pessoa pudesse criar JWTs em que o servidor confiaria.

  • Para revogar um JWT antes que ele expire, você precisa usar uma lista de revogação. Isso faz com que você volte aos problemas de armazenamento do servidor que estava tentando evitar.

OAuth

Geralmente, o OAuth é usado para autenticação (ou seja, identidade), mas pode ser usado para compartilhar outros dados, como uma lista de conteúdo que o usuário comprou e está autorizado a fazer o download. Também pode ser usado para conceder acesso para gravar dados armazenados pelo terceiro. Você pode usar o OAuth para autenticar usuários e usar o armazenamento no servidor ou o JWT para os dados da sessão.

Prós:

  • Nenhum código para os usuários registrarem ou redefinirem suas senhas.
  • Nenhum código para enviar um email com um link de validação e validar o endereço.
  • Os usuários não precisam aprender / escrever outro nome de usuário e senha.

Contras:

  • Você depende do terceiro para que seus usuários usem seu serviço. Se o seu serviço cair ou eles pararem, então você precisa descobrir outra coisa. Por exemplo: como você migra os dados da conta do usuário se a identidade deles mudar de "[email protected]" para "[email protected]"?
  • Normalmente você tem que escrever código para cada provedor. por exemplo, Google, Facebook, Twitter.
  • Você ou seus usuários podem ter preocupações com a privacidade. Os provedores sabem quais usuários usam seu serviço.
  • Você está confiando no provedor. É possível que um provedor emita tokens válidos para um usuário para outra pessoa. Isso pode ser para fins legais ou não.

Diversos

  • Tanto os IDs de sessão quanto os JWTs podem ser copiados e usados por vários usuários. Você pode armazenar o endereço IP do cliente em um JWT e validá-lo, mas isso impede que os clientes façam roaming, digamos, de Wi-Fi para celular.
por 26.01.2016 / 21:07
fonte
5

Pergunte por que você precisa invalidar o token original.

Um usuário efetua login, um token é gerado e sai do app.

O usuário pressiona o logout, um novo token é gerado e substitui o token original. Mais uma vez, tudo está bem.

Você parece estar preocupado com o caso em que ambos os tokens estão pendurados. E se o usuário fizer logout e, de alguma forma, fizer uma solicitação usando o token conectado. Quão realista é esse cenário? É apenas um problema durante o logout ou há muitos cenários possíveis em que vários tokens podem ser um problema?

Eu mesmo não acho que vale a pena se preocupar. Se alguém estiver interceptando e decodificando seus dados https criptografados, você terá problemas muito maiores.

Você pode oferecer proteção adicional colocando um prazo de expiração no token original. Então, se acaba sendo roubado ou algo assim, só seria bom por um curto período de tempo.

Caso contrário, acho que você precisaria ter informações de estado no servidor. Não coloque os tokens na lista negra, mas coloque na lista de permissões a assinatura do token atual.

    
por 05.10.2015 / 16:43
fonte
3

Você pode manipular os problemas do JWT mencionados por armazenar um valor salt junto com o usuário e usar o salt como parte do token para o usuário. Então, quando você precisar invalidar o token, basta alterar o sal.

Eu sei que já faz alguns anos, mas eu faria isso de forma diferente agora. Acho que garantiria que os tokens de acesso tivessem uma duração relativamente curta, digamos uma hora. Também usaria tokens de atualização que fossem stateful no servidor e, quando eu quisesse encerrar a sessão de alguém, eu revogaria o token de atualização removendo-o do servidor. Depois de uma hora, o usuário seria desconectado e teria que fazer login novamente para recuperar o acesso.

    
por 05.10.2015 / 01:40
fonte