Ainda estou tentando encontrar a melhor solução de segurança para proteger a API REST, porque a quantidade de aplicativos móveis e API está aumentando a cada dia.
Tentei diferentes formas de autenticação, mas ainda tenho alguns mal-entendidos, por isso preciso de conselhos de alguém mais experiente.
Deixe-me dizer, como eu entendo todas essas coisas. Se eu entender algo incorretamente, entre em contato.
Quanto à API REST é sem estado e WEB em geral, precisamos enviar alguns dados de autenticação em cada solicitação (cookies, token ...). Conheço três mecanismos amplamente utilizados para autenticar usuários
Token com HTTPS. Eu tenho usado essa abordagem muitas vezes, é boa o suficiente com HTTPS. Se o usuário fornecer a senha e o login corretos, ele receberá o token em resposta e o utilizará para as solicitações adicionais. O 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ção, verifique se o usuário possui token e é o mesmo que no banco de dados. Tudo é bem direto.
Token JWT. Esse token é auto-descritivo, contém todas as informações necessárias sobre o próprio token, o usuário não pode alterar, por exemplo, data de validade ou qualquer outra reivindicação, porque esse token é gerado (assinado) pelo servidor com a palavra-chave secreta. Isso também está claro. Mas um grande problema, pessoalmente, para mim, como invalidar o token.
OAuth 2. Não entendo por que essa abordagem deve ser usada quando a comunicação é estabelecida diretamente entre servidor e cliente. Pelo que entendi, 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 logon. Esta é uma ótima solução para as redes sociais, quando o usuário deseja se inscrever em alguma página, o servidor pode solicitar permissões para obter informações do usuário, por exemplo, do twitter ou do facebook, preencher campos de registro com dados do usuário e assim por diante.
Considere o cliente móvel para a loja online.
Primeira pergunta: devo preferir o JWT ao invés do primeiro tipo de token? Na medida em que eu preciso de usuário de logon / logout no cliente móvel, preciso armazenar um token em algum lugar ou, no caso de JWT, o token deve ser invalidado no logout. Diferentes abordagens são usadas para invalidar o token, uma das é criar lista de tokens inválidos (lista negra). Hmm. A tabela / arquivo terá um tamanho muito maior do que se o token estivesse 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 meu servidor? Qual é o objetivo de mais uma camada entre cliente e servidor apenas para emitir 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 conceder permissões (tokens) a aplicativos de terceiros para acessar informações privadas do usuário. Mas meu aplicativo cliente móvel não é de terceiros.
Respostas:
Considere o primeiro caso. Cada cliente obtém um ID aleatório que dura a duração da sessão - que pode demorar vários dias, se você desejar. Em seguida, você armazena as informações relevantes para essa sessão em algum lugar do servidor. Pode estar em um arquivo ou em um 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:
Contras:
Tokens da Web JSON (JWT)
No segundo caso, os dados são armazenados em um JWT que é passado ao invés de no servidor.
Prós:
Contras:
O lado do servidor precisa de código para gerar, validar e ler JWTs. Não é difícil, mas existe uma curva de aprendizado e a segurança depende disso.
Qualquer pessoa que obtenha uma cópia da chave de assinatura pode criar JWTs. Você pode não saber quando isso acontece.
Havia (há?) Um bug em algumas bibliotecas que aceitavam qualquer JWT assinado com o algoritmo "none" para que qualquer um pudesse criar JWTs nos quais o servidor confiaria.
Para revogar um JWT antes que ele expire, é necessário usar uma lista de revogação. Isso leva você de volta aos problemas de armazenamento do lado do servidor que você 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 tem o direito de fazer o download. Também pode ser usado para conceder acesso à gravação em dados armazenados por terceiros. Você pode usar o OAuth para autenticar usuários e, em seguida, usar armazenamento do lado do servidor ou JWT para os dados da sessão.
Prós:
Contras:
Diversos
fonte
Pergunte a si mesmo por que você precisa invalidar o token original.
Um usuário efetua login, um token é gerado e o aplicativo é desativado.
O usuário pressiona o logout, um novo token é gerado e substitui o token original. Mais uma vez, está tudo bem.
Você parece estar preocupado com o caso em que os dois tokens ficam por aqui. 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 tempo de expiração no token original. Então, se acabar sendo roubado ou algo assim, seria bom apenas por um curto período de tempo.
Caso contrário, acho que você precisaria ter informações de estado no servidor. Não coloque na lista negra os tokens, mas coloque na lista branca a assinatura do token atual.
fonte
Você pode lidar com os problemas de JWT mencionados, armazenando um valor de salt junto com o usuário e usando o salt como parte do token para o usuário. Então, quando você precisar invalidar o token, basta alterar o sal.
Sei que já faz alguns anos, mas na verdade faria isso de forma diferente agora. Acho que garantiria que os tokens de acesso tivessem uma vida útil relativamente curta, digamos uma hora. Também usaria tokens de atualização com estado no servidor e, quando desejasse encerrar a sessão de alguém, revogaria o token de atualização removendo-o do servidor. Depois de uma hora, o usuário seria desconectado e precisaria fazer login novamente para recuperar o acesso.
fonte