O que significa a autenticação RESTful e como funciona? Não consigo encontrar uma boa visão geral no Google. Meu único entendimento é que você passa a chave da sessão (remeberal) na URL, mas isso pode estar terrivelmente errado.
O que significa a autenticação RESTful e como funciona? Não consigo encontrar uma boa visão geral no Google. Meu único entendimento é que você passa a chave da sessão (remeberal) na URL, mas isso pode estar terrivelmente errado.
Respostas:
Como lidar com a autenticação em uma arquitetura RESTful Client-Server é uma questão de debate.
Geralmente, isso pode ser alcançado no mundo SOA sobre HTTP via:
Você terá que se adaptar, ou ainda melhor, misturar essas técnicas, para combinar com sua arquitetura de software, na melhor das hipóteses.
Cada esquema de autenticação possui seus próprios PROs e CONs, dependendo do objetivo da sua política de segurança e arquitetura de software.
Autenticação básica HTTP sobre HTTPS
Essa primeira solução, baseada no protocolo HTTPS padrão, é usada pela maioria dos serviços web.
GET /spec.html HTTP/1.1
Host: www.example.org
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
É fácil de implementar, disponível por padrão em todos os navegadores, mas possui algumas desvantagens conhecidas, como a terrível janela de autenticação exibida no Navegador, que persiste (não há recurso semelhante ao LogOut aqui), algum consumo adicional de CPU no servidor, e o fato de o nome de usuário e a senha serem transmitidos (via HTTPS) para o servidor (deve ser mais seguro permitir que a senha permaneça apenas no lado do cliente, durante a entrada do teclado e seja armazenada como hash seguro no servidor) .
Podemos usar a autenticação Digest , mas também requer HTTPS, pois é vulnerável a ataques MiM ou Replay e é específico para HTTP.
Sessão via Cookies
Para ser sincero, uma sessão gerenciada no servidor não é verdadeiramente sem estado.
Uma possibilidade poderia ser manter todos os dados no conteúdo do cookie. E, por padrão, o cookie é manipulado no lado do servidor (o cliente, na verdade, nem tenta interpretar esses dados do cookie: apenas o devolve ao servidor a cada solicitação sucessiva). Mas esses dados do cookie são dados do estado do aplicativo, portanto, o cliente deve gerenciá-los, não o servidor, em um mundo sem Estado puro.
GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123
A técnica do cookie em si é vinculada ao HTTP, portanto, não é verdadeiramente RESTful, que deve ser independente do protocolo, IMHO. É vulnerável a ataques MiM ou Replay .
Concedido por token (OAuth2)
Uma alternativa é colocar um token nos cabeçalhos HTTP para que a solicitação seja autenticada. É isso que o OAuth 2.0 faz, por exemplo. Veja o RFC 6749 :
GET /resource/1 HTTP/1.1
Host: example.com
Authorization: Bearer mF_9.B5f-4.1JqM
Em resumo, isso é muito semelhante a um cookie e sofre os mesmos problemas: não estático, depende de detalhes de transmissão HTTP e está sujeito a muitas deficiências de segurança - incluindo MiM e Replay -, portanto, deve ser usado apenas por HTTPS. Normalmente, um JWT é usado como um token.
Autenticação de consulta
A autenticação de consulta consiste em assinar cada solicitação RESTful por meio de alguns parâmetros adicionais no URI. Veja este artigo de referência .
Foi definido como tal neste artigo:
Todas as consultas REST devem ser autenticadas assinando os parâmetros de consulta classificados em ordem alfabética minúscula, usando a credencial privada como o token de assinatura. A assinatura deve ocorrer antes do URL que codifica a string de consulta.
Essa técnica é talvez a mais compatível com uma arquitetura Stateless e também pode ser implementada com um gerenciamento de sessões simples (usando sessões na memória em vez de persistência de banco de dados).
Por exemplo, aqui está uma amostra de URI genérica no link acima:
GET /object?apiKey=Qwerty2010
deve ser transmitido como tal:
GET /object?timestamp=1261496500&apiKey=Qwerty2010&signature=abcdef0123456789
A cadeia de caracteres assinada é /object?apikey=Qwerty2010×tamp=1261496500
e a assinatura é o hash SHA256 dessa cadeia de caracteres usando o componente privado da chave da API.
O cache de dados do servidor pode estar sempre disponível. Por exemplo, em nossa estrutura, armazenamos em cache as respostas no nível SQL, não no URI. Portanto, adicionar esse parâmetro extra não quebra o mecanismo de cache.
Consulte este artigo para obter alguns detalhes sobre autenticação RESTful em nossa estrutura ORM / SOA / MVC cliente-servidor, com base em JSON e REST. Como permitimos a comunicação não apenas por HTTP / 1.1, mas também por pipes nomeados ou mensagens GDI (localmente), tentamos implementar um padrão de autenticação verdadeiramente RESTful e não dependemos da especificidade do HTTP (como cabeçalho ou cookies).
Nota posterior : adicionar uma assinatura ao URI pode ser considerado uma má prática (uma vez que, por exemplo, aparecerá nos logs do servidor http), pelo que deve ser mitigado, por exemplo, por um TTL adequado para evitar replays. Mas se seus logs http estiverem comprometidos, você certamente terá maiores problemas de segurança.
Na prática, a próxima autenticação de token MAC para OAuth 2.0 pode ser uma grande melhoria em relação ao esquema atual "Granted by Token". Mas este ainda é um trabalho em andamento e está vinculado à transmissão HTTP.
Conclusão
Vale a pena concluir que o REST não é apenas baseado em HTTP, mesmo que, na prática, ele também seja implementado principalmente por HTTP. O REST pode usar outras camadas de comunicação. Portanto, uma autenticação RESTful não é apenas sinônimo de autenticação HTTP, independentemente do que o Google responder. Ele nem deve usar o mecanismo HTTP, mas deve ser abstraído da camada de comunicação. E se você usar a comunicação HTTP, graças à iniciativa Let's Encrypt, não há razão para não usar HTTPS adequado, necessário além de qualquer esquema de autenticação.
Cookie
como um substituto melhor, HTTP Basic Auth
poderá fazer uma autenticação verdadeiramente sem estado com um método para expirar a autenticação e a capacidade de sair. Um exemplo de implementação pode usar o cookie chamado Emulated-HTTP-Basic-Auth
com valor semelhante ao HTTP Basic Auth real e, além disso, definir o tempo de expiração. O logout pode ser implementado com a remoção desse cookie. Eu acho que qualquer cliente capaz de oferecer suporte a autenticação básica HTTP também pode suportar autenticação de cookies feita dessa maneira.
Cookie
) pode ser usado.
Duvido que as pessoas que gritavam com entusiasmo "Autenticação HTTP" alguma vez tentaram criar um aplicativo baseado em navegador (em vez de um serviço da web máquina a máquina) com REST (sem ofensas - apenas acho que nunca enfrentaram as complicações) .
Os problemas encontrados ao usar a autenticação HTTP nos serviços RESTful que produzem páginas HTML para serem exibidas em um navegador são:
Um artigo muito perspicaz que aborda esses pontos por ponto está aqui , mas isso resulta em uma muitos hackers de javascript específicos do navegador, soluções alternativas para soluções alternativas, etc. Como tal, também não é compatível com o futuro, portanto, será necessária manutenção constante à medida que novos navegadores forem lançados. Eu não considero esse design limpo e claro, além de sentir que é muito trabalho extra e dor de cabeça, para que eu possa mostrar com entusiasmo meu distintivo REST aos meus amigos.
Eu acredito que os cookies são a solução. Mas espere, biscoitos são maus, não são? Não, não são, a maneira como os cookies são frequentemente usados é ruim. Um cookie em si é apenas uma informação do lado do cliente, assim como as informações de autenticação HTTP que o navegador acompanharia enquanto você navega. E essas informações do lado do cliente são enviadas ao servidor a cada solicitação, novamente como as informações de autenticação HTTP. Conceitualmente, a única diferença é que o conteúdo dessa parte do estado do lado do cliente pode ser determinado pelo servidor como parte de sua resposta.
Tornando as sessões um recurso RESTful com apenas as seguintes regras:
A única diferença para a autenticação HTTP, agora, é que a chave de autenticação é gerada pelo servidor e enviada ao cliente que continua enviando de volta, em vez de o cliente computá-la a partir das credenciais inseridas.
converter42 acrescenta que, ao usar https (o que deveríamos), é importante que o cookie tenha seu sinalizador seguro definido para que as informações de autenticação nunca sejam enviadas por uma conexão não segura. Ótimo ponto, eu não tinha visto.
Sinto que esta é uma solução suficiente que funciona bem, mas devo admitir que não sou especialista em segurança o suficiente para identificar possíveis falhas nesse esquema - tudo o que sei é que centenas de aplicativos da Web não RESTful usam essencialmente o mesmo protocolo de login ($ _SESSION em PHP, HttpSession em Java EE, etc.). O conteúdo do cabeçalho do cookie é simplesmente usado para endereçar um recurso do lado do servidor, assim como um idioma de aceitação pode ser usado para acessar recursos de tradução, etc. Eu sinto que é o mesmo, mas talvez outros não? O que vocês acham pessoal?
Já chega de falar sobre esse assunto por gente boa aqui. Mas aqui estão meus 2 centavos.
Existem 2 modos de interação:
A máquina é o denominador comum, expresso como APIs REST, e os atores / clientes são os humanos ou as máquinas.
Agora, em uma arquitetura verdadeiramente RESTful, o conceito de apatridia implica que todos os estados de aplicativos relevantes (ou seja, os estados do lado do cliente) devem ser fornecidos com cada solicitação. Por relevante, significa que tudo o que é exigido pela API REST para processar a solicitação e fornecer uma resposta apropriada.
Quando consideramos isso no contexto de aplicativos humano-para-máquina, "com base no navegador", como o Skrebbel aponta acima, isso significa que o aplicativo (web) em execução no navegador precisará enviar seu estado e informações relevantes a cada solicitação cria para as APIs REST de back-end.
Considere o seguinte: Você tem um ativo exposto na plataforma de dados / informações de APIs REST. Talvez você tenha uma plataforma de BI de autoatendimento que lida com todos os cubos de dados. Mas você deseja que seus clientes (humanos) acessem esse recurso via (1) aplicativo Web, (2) aplicativo móvel e (3) algum aplicativo de terceiros. No final, uma cadeia uniforme de MTMs leva ao HTM - certo. Portanto, os usuários humanos permanecem no ápice da cadeia de informações.
Nos 2 primeiros casos, você tem um caso de interação homem-máquina, as informações sendo realmente consumidas por um usuário humano. No último caso, você tem um programa de máquina consumindo as APIs REST.
O conceito de autenticação se aplica de maneira geral. Como você projetará isso para que suas APIs REST sejam acessadas de maneira uniforme e segura? Do jeito que eu vejo isso, existem 2 maneiras:
Maneira-1:
Caminho-2:
Claramente, no Modo 2, as APIs REST precisarão de uma maneira de reconhecer e confiar no token como válido. A API de logon executou a verificação de autenticação e, portanto, essa "chave com manobrista" precisa ser confiável por outras APIs REST em seu catálogo.
Obviamente, isso significa que a chave / token de autenticação precisará ser armazenada e compartilhada entre as APIs REST. Esse repositório de token confiável e compartilhado pode ser local / federado, o que permite, permitindo que APIs REST de outras organizações confiem uma na outra.
Mas eu discordo.
O ponto é que um "estado" (sobre o status autenticado do cliente) precisa ser mantido e compartilhado para que todas as APIs REST possam criar um círculo de confiança. Se não fizermos isso, que é o Caminho-1, devemos aceitar que um ato de autenticação deve ser realizado para qualquer / todas as solicitações que chegarem.
Executar autenticação é um processo que consome muitos recursos. Imagine executar consultas SQL, para cada solicitação recebida, no seu repositório de usuários para verificar a correspondência de uid / pwd. Ou, para criptografar e executar correspondências de hash (o estilo da AWS). E, arquitetonicamente, todas as APIs REST precisarão executar isso, suspeito, usando um serviço de login de back-end comum. Porque, se não o fizer, você distribui o código de autenticação em todos os lugares. Uma grande bagunça.
Mais camadas, mais latência.
Agora, pegue o Caminho 1 e aplique ao HTM. O seu usuário (humano) realmente se importa se você precisa enviar uid / pwd / hash ou qualquer outra coisa a cada solicitação? Não, contanto que você não a incomode jogando a página de autenticação / login a cada segundo. Boa sorte em ter clientes, se você tiver. Então, o que você fará é armazenar as informações de login em algum lugar do lado do cliente, no navegador, logo no início e enviá-las com todas as solicitações feitas. Para o usuário (humano), ele já fez login e uma "sessão" está disponível. Mas, na realidade, ela é autenticada em todos os pedidos.
Mesmo com a maneira 2. Seu usuário (humano) nunca notará. Portanto, nenhum dano foi feito.
E se aplicarmos o Caminho 1 ao MTM? Nesse caso, como é uma máquina, podemos aborrecer esse cara pedindo que ele envie informações de autenticação a cada solicitação. Ninguém se importa! Executar o Way-2 no MTM não evocará nenhuma reação especial; é uma máquina maldita. Poderia se importar menos!
Então, realmente, a questão é o que se adequa às suas necessidades. Apatridia tem um preço a pagar. Pague o preço e siga em frente. Se você quer ser um purista, pague o preço também e siga em frente.
No final, filosofias não importam. O que realmente importa é a descoberta de informações, a apresentação e a experiência de consumo. Se as pessoas amam suas APIs, você fez seu trabalho.
Way-3
, a abordagem híbrida. O cliente efetua login como em Way-2
, mas, como em Way-1
, as credenciais não são verificadas em nenhum estado do lado do servidor. Independentemente disso, um token de autenticação é criado e enviado de volta ao cliente como em Way-2
. Mais tarde, esse token é verificado quanto à autenticidade usando criptografia assimétrica, sem procurar qualquer estado específico do cliente.
Aqui está uma solução de autenticação RESTful verdadeira e completamente:
Quando um cliente se autentica:
3.1 emita um token que contém o seguinte:
3.2 Criptografe o token com a chave privada.
3.3 Envie o token criptografado de volta ao usuário.
Quando o usuário acessa qualquer API, ele também deve passar seu token de autenticação.
Esta é uma autenticação sem estado / RESTful.
Observe que, se um hash de senha fosse incluído, o usuário também enviaria a senha não criptografada junto com o token de autenticação. O servidor pôde verificar se a senha correspondia à senha usada para criar o token de autenticação comparando hashes. Uma conexão segura usando algo como HTTPS seria necessária. O Javascript no lado do cliente pode lidar com a obtenção da senha do usuário e o armazenamento no lado do cliente, na memória ou em um cookie, possivelmente criptografado com a chave pública do servidor .
Para ser honesto com você, já vi ótimas respostas aqui, mas algo que me incomoda um pouco é quando alguém leva todo o conceito de Stateless ao extremo, onde se torna dogmático. Isso me lembra aqueles velhos fãs do Smalltalk que queriam apenas adotar OO puro e se algo não é um objeto, então você está fazendo errado. Me dá um tempo.
A abordagem RESTful deve facilitar sua vida e reduzir a sobrecarga e o custo das sessões, tente segui-la da maneira mais sábia, mas no minuto em que você seguir uma disciplina (qualquer disciplina / orientação) ao extremo onde não fornece mais o benefício a que se destinava, então você está fazendo errado. Atualmente, algumas das melhores linguagens possuem programação funcional e orientação a objetos.
Se a maneira mais fácil de resolver seu problema é armazenar a chave de autenticação em um cookie e enviá-la no cabeçalho HTTP, faça-o, apenas não abuse. Lembre-se de que as sessões são ruins quando se tornam pesadas e grandes, se toda a sua sessão consiste em uma sequência curta contendo uma chave, então qual é o problema?
Estou aberto a aceitar correções nos comentários, mas simplesmente não vejo sentido (até agora) em tornar nossas vidas miseráveis para simplesmente evitar manter um grande dicionário de hashes em nosso servidor.
Em primeiro lugar, um serviço da web RESTful é STATELESS (ou, em outras palavras, SESSIONLESS ). Portanto, um serviço RESTful não possui e não deve ter um conceito de sessão ou cookies envolvidos. A maneira de realizar autenticação ou autorização no serviço RESTful é usando o cabeçalho HTTP Authorization, conforme definido nas especificações HTTP do RFC 2616. Cada solicitação única deve conter o cabeçalho de Autorização HTTP e a solicitação deve ser enviada por uma conexão HTTPs (SSL). Esta é a maneira correta de fazer autenticação e verificar a autorização de solicitações em um serviço da Web HTTP RESTful. Eu implementei um serviço da Web RESTful para o aplicativo Cisco PRIME Performance Manager na Cisco Systems. E como parte desse serviço da web, implementei autenticação / autorização também.
Certamente, não se trata de "chaves de sessão", pois geralmente é usado para se referir à autenticação sem sessão, que é realizada dentro de todas as restrições do REST. Cada solicitação é auto-descritiva, carregando informações suficientes para autorizá-la por si própria, sem nenhum estado de aplicativo do lado do servidor.
A maneira mais fácil de abordar isso é iniciando com os mecanismos de autenticação internos do HTTP no RFC 2617 .
O artigo 'muito perspicaz' mencionado por @skrebel ( http://www.berenddeboer.net/rest/authentication.html ) discute um método de autenticação complicado, mas realmente quebrado.
Você pode tentar visitar a página (que deveria ser visível apenas para usuários autenticados) http://www.berenddeboer.net/rest/site/authenticated.html sem nenhuma credencial de login.
(Desculpe, não posso comentar a resposta.)
Eu diria que REST e autenticação simplesmente não se misturam. REST significa sem estado, mas 'autenticado' é um estado. Você não pode ter os dois na mesma camada. Se você é um defensor do RESTful e desaprova os estados, precisa seguir o HTTPS (por exemplo, deixe o problema de segurança para outra camada).
Acho que a autenticação repousante envolve a passagem de um token de autenticação como parâmetro na solicitação. Exemplos são o uso de apikeys por api's. Não acredito que o uso de cookies ou a autenticação http se qualifique.
A abordagem mencionada anteriormente abaixo é essencialmente o tipo de concessão "Credencial de senha do proprietário do recurso" do OAuth2.0 . Essa é uma maneira fácil de começar a funcionar. No entanto, com essa abordagem, todos os aplicativos da organização terão seus próprios mecanismos de autenticação e autorização. A abordagem recomendada é o tipo de concessão "Código de autorização". Além disso, na minha resposta anterior abaixo, recomendei o localStorage do navegador para armazenar tokens de autenticação. No entanto, acredito que o cookie é a opção certa para esse fim. Eu detalhei meus motivos, abordagem de implementação do tipo de concessão de código de autorização, considerações de segurança etc. nesta resposta do StackOverflow .
Eu acho que a seguinte abordagem pode ser usada para autenticação de serviço REST:
Com essa abordagem, estamos fazendo a operação dispendiosa de carregar o cache com os detalhes certos de acesso específico do usuário a cada 30 minutos. Portanto, se um acesso for revogado ou novo acesso for concedido, leva 30 minutos para refletir ou um logout seguido de um logon.
Essa é a maneira de fazer isso: usando o OAuth 2.0 para logon .
Você pode usar outros métodos de autenticação que não sejam do Google, desde que sejam compatíveis com o OAuth.
O uso de uma infra-estrutura de chave pública na qual o registro de uma chave envolve ligação adequada garante que a chave pública seja vinculada ao indivíduo ao qual está atribuída, de maneira a garantir não-repúdio
Veja http://en.wikipedia.org/wiki/Public_key_infrastructure . Se você seguir os padrões adequados de PKI, a pessoa ou agente que usar indevidamente a chave roubada poderá ser identificado e bloqueado. Se for necessário que o agente use um certificado, a ligação fica bastante rígida. Um ladrão inteligente e veloz pode escapar, mas deixa mais migalhas.
Para responder a esta pergunta do meu entendimento ...
Um sistema de autenticação que usa o REST para que você não precise realmente rastrear ou gerenciar os usuários em seu sistema. Isso é feito usando os métodos HTTP POST, GET, PUT, DELETE. Nós pegamos esses 4 métodos e pensamos neles em termos de interação com o banco de dados como CREATE, READ, UPDATE, DELETE (mas na web usamos POST e GET porque é isso que as tags âncoras suportam atualmente). Portanto, tratando POST e GET como nosso CREATE / READ / UPDATE / DELETE (CRUD), podemos projetar rotas em nosso aplicativo da Web que serão capazes de deduzir que ação do CRUD estamos realizando.
Por exemplo, em um aplicativo Ruby on Rails, podemos criar nosso aplicativo da web para que, se um usuário logado, visite http://store.com/account/logout , o GET dessa página possa ser visto como o usuário tentando fazer logout. . Em nosso controlador rails, criaríamos uma ação que desconecta o usuário e os envia de volta à página inicial.
Um GET na página de login renderia um formulário. um POST na página de login seria visto como uma tentativa de logon e pegaria os dados do POST e os usaria para efetuar login.
Para mim, é uma prática usar métodos HTTP mapeados para o significado do banco de dados e, em seguida, criar um sistema de autenticação com isso em mente que você não precisa repassar nenhum ID de sessão ou acompanhar sessões.
Ainda estou aprendendo - se você encontrar alguma coisa que eu disse estar errada, corrija-me e, se souber mais, poste aqui. Obrigado.
Dicas válidas para proteger qualquer aplicativo Web
Se você deseja proteger seu aplicativo, definitivamente deve começar usando HTTPS em vez de HTTP , isso garante um canal seguro de criação entre você e os usuários que evitará cheirar os dados enviados aos usuários e ajudará a mantê-los trocado confidencial.
Você pode usar JWTs (JSON Web Tokens) para proteger APIs RESTful ; isso tem muitos benefícios quando comparado às sessões do servidor, os benefícios são principalmente:
1- Mais escalável, pois seus servidores de API não precisarão manter sessões para cada usuário (o que pode ser um grande fardo quando você tiver muitas sessões)
2- Os JWTs são independentes e possuem as reivindicações que definem a função do usuário, por exemplo, o que ele pode acessar e emitido na data e data de validade (após o qual o JWT não será válido)
3- Mais fácil de lidar com balanceadores de carga e se você tiver vários servidores de API, não precisará compartilhar dados da sessão nem configurar o servidor para rotear a sessão para o mesmo servidor, sempre que uma solicitação com um JWT atingir qualquer servidor, ela pode ser autenticada e autorizado
4- Menos pressão no seu banco de dados e você não precisará armazenar e recuperar constantemente o ID da sessão e os dados para cada solicitação
5- Os JWTs não podem ser violados se você usar uma chave forte para assinar o JWT, para que possa confiar nas reivindicações no JWT enviadas com a solicitação sem precisar verificar a sessão do usuário e se ele está autorizado ou não , basta verificar o JWT e pronto para saber quem e o que esse usuário pode fazer.
Muitas bibliotecas fornecem maneiras fáceis de criar e validar JWTs na maioria das linguagens de programação, por exemplo: no node.js, uma das mais populares é jsonwebtoken
Como as APIs REST geralmente têm como objetivo manter o servidor sem estado, as JWTs são mais compatíveis com esse conceito, pois cada solicitação é enviada com o token de autorização independente (JWT) sem que o servidor tenha que acompanhar a sessão do usuário em comparação com as sessões que tornam o com estado do servidor, para que ele se lembre do usuário e de sua função; no entanto, as sessões também são amplamente usadas e têm seus profissionais, que você pode procurar se quiser.
Uma coisa importante a ser observada é que você deve entregar com segurança o JWT ao cliente usando HTTPS e salvá-lo em um local seguro (por exemplo, no armazenamento local).
Você pode aprender mais sobre JWTs neste link