Padrão de logon da API REST

181

Estou criando uma api REST, seguindo de perto as sugestões de apigee, usando substantivos, não verbos, versão api inserida no URL, dois caminhos de api por coleção, uso GET POST PUT DELETE etc.

Estou trabalhando no sistema de logon, mas não tenho certeza da maneira correta de REST para logar usuários. Não estou trabalhando na segurança neste momento, apenas no padrão ou fluxo de logon. (Mais tarde, adicionaremos 2 etapas oAuth, com um HMAC, etc.)

Possíveis opções

  • Um POST para algo como https://api...com/v1/login.json
  • Um ponto para algo como https://api...com/v1/users.json
  • Algo que eu não tenho ...

Qual é o estilo REST adequado para efetuar login nos usuários?

Scott Roepnack
fonte
9
Esse é o formato da resposta. .json diz ao servidor para responder com json, .xml diz ao servidor para responder no formato xml. Em vez disso, torná-lo um parâmetro opcional por trás do?. blog.apigee.com/detail/…
Scott Roepnack
28
Nunca vi negociação de conteúdo feita no URL, apenas em cabeçalhos. Na URL, isso significa que você perde os benefícios do cache e muito mais.
Oded
10
@ScottRoepnack, você deve considerar o Acceptcabeçalho HTTP.
Alessandro Vendruscolo
2
@Oded Se você usasse um Acceptcabeçalho, também teria um Vary: Accept, para que o cache não fosse afetado. Conneg em extensão já foi discutido antes ; Eu concordo com a resposta de Shonzilla lá.
cmbuckley
2
@ Oded - eu não entendo. por que você perderia o benefício do armazenamento em cache se especificar o tipo de conteúdo na URL (como um sufixo .json no caminho da consulta ou como um parâmetro type = json query)? E quem é "você" neste caso? Quem é a pessoa que perde os benefícios do cache? parece-me que os resultados de qualquer consulta podem ser armazenados em cache, independentemente do que está no caminho ou nos parâmetros da consulta.
Cheeso 29/05

Respostas:

138

O Design de Princípios da Arquitetura Moderna da Web, de Roy T. Fielding e Richard N. Taylor , ou seja, a sequência de trabalhos de todas as terminologias REST, contém definição de interação cliente-servidor:

Todas as interações REST são sem estado . Ou seja, cada solicitação contém todas as informações necessárias para que um conector entenda a solicitação, independentemente de quaisquer solicitações que possam ter precedido .

Essa restrição realiza quatro funções, 1 e 3 são importantes neste caso específico:

  • : elimina a necessidade de os conectores manterem o estado do aplicativo entre as solicitações , reduzindo o consumo de recursos físicos e melhorando a escalabilidade;
  • : permite ao intermediário visualizar e entender uma solicitação isoladamente , o que pode ser necessário quando os serviços são reorganizados dinamicamente;

E agora vamos voltar ao seu caso de segurança. Cada solicitação deve conter todas as informações necessárias e a autorização / autenticação não é uma exceção. Como conseguir isso? Envie literalmente todas as informações necessárias pelos fios a cada solicitação.

Um dos exemplos de como arquivar isso é o código de autenticação de mensagens baseado em hash ou HMAC . Na prática, isso significa adicionar um código de hash da mensagem atual a cada solicitação. Código hash calculado pela função hash criptográfica em combinação com uma chave criptográfica secreta . A função de hash criptográfico é predefinida ou faz parte da concepção REST de código sob demanda (por exemplo, JavaScript). A chave criptográfica secreta deve ser fornecida pelo servidor ao cliente como recurso, e o cliente a utiliza para calcular o código de hash para cada solicitação.

Existem muitos exemplos de implementações do HMAC , mas eu gostaria que você prestasse atenção nos três seguintes:

Como funciona na prática

Se o cliente conhece a chave secreta, está pronto para operar com recursos. Caso contrário, ele será redirecionado temporariamente (código de status 307 Redirecionamento temporário) para autorizar e obter chave secreta e, em seguida, redirecionado de volta ao recurso original. Nesse caso, não é necessário saber de antemão (ou seja, código fixo em algum lugar) qual é o URL para autorizar o cliente e é possível ajustar esse esquema com o tempo.

Espero que isso ajude você a encontrar a solução adequada!

Akim
fonte
23
Um MAC é destinado a provar mensagem de autenticidade e proteger contra adulteração - não tem nada a ver com a autenticação do usuário
Yrk
1
Adicionado um dos exemplos: como lidar com a autenticação de usuário / cliente sem conhecer o " URL de login " de antemão
Akim
Aqui está mais dois bons artigos com exemplos apátrida de autenticação para serviços REST: blog.jdriven.com/2014/10/... technicalrex.com/2015/02/20/...
Vladimir Rozhkov
41

O logon TL; DR para cada solicitação não é um componente necessário para implementar a segurança da API, é a autenticação.

É difícil responder à sua pergunta sobre o login sem falar em segurança em geral. Com alguns esquemas de autenticação, não há logon tradicional.

O REST não determina nenhuma regra de segurança, mas a implementação mais comum na prática é o OAuth com autenticação de três vias (como você mencionou na sua pergunta). Não há login propriamente dito, pelo menos não com cada solicitação de API. Com autenticação de três vias, você apenas usa tokens.

  1. O usuário aprova o cliente da API e concede permissão para fazer solicitações na forma de um token de longa duração
  2. O cliente da API obtém um token de vida curta usando o de longa duração.
  3. O cliente da API envia o token de curta duração a cada solicitação.

Esse esquema oferece ao usuário a opção de revogar o acesso a qualquer momento. Praticamente todas as APIs RESTful disponíveis publicamente que eu vi usam OAuth para implementar isso.

Apenas acho que você não deve enquadrar seu problema (e pergunta) em termos de login, mas sim pensar em proteger a API em geral.

Para obter mais informações sobre autenticação de APIs REST em geral, consulte os seguintes recursos:

Slavo
fonte
Sim, OAuth! Resposta muito direta, deve ser a resposta aceita, imho.
Levite
26

Uma grande parte da filosofia REST é explorar o maior número possível de recursos padrão do protocolo HTTP ao projetar sua API. Ao aplicar essa filosofia à autenticação, o cliente e o servidor utilizariam os recursos de autenticação HTTP padrão na API.

As telas de login são ótimas para casos de uso de usuários humanos: visite uma tela de login, forneça usuário / senha, defina um cookie, o cliente fornece esse cookie em todas as solicitações futuras. Não se espera que humanos que usam navegadores da Web forneçam um ID de usuário e senha a cada solicitação HTTP individual.

Mas para uma API REST, uma tela de login e cookies de sessão não são estritamente necessários, pois cada solicitação pode incluir credenciais sem afetar o usuário humano; e se o cliente não cooperar a qualquer momento, uma 401resposta "não autorizada" pode ser dada. O RFC 2617 descreve o suporte à autenticação em HTTP.

O TLS (HTTPS) também seria uma opção e permitiria a autenticação do cliente no servidor (e vice-versa) em cada solicitação, verificando a chave pública da outra parte. Além disso, isso garante ao canal um bônus. Obviamente, uma troca de pares de chaves antes da comunicação é necessária para fazer isso. (Observe, trata-se especificamente de identificar / autenticar o usuário com TLS. Proteger o canal usando TLS / Diffie-Hellman é sempre uma boa ideia, mesmo que você não identifique o usuário por sua chave pública.)

Um exemplo: suponha que um token OAuth seja suas credenciais completas de login. Depois que o cliente tiver o token OAuth, ele poderá ser fornecido como o ID do usuário na autenticação HTTP padrão a cada solicitação. O servidor pode verificar o token no primeiro uso e armazenar em cache o resultado da verificação com um tempo de vida útil renovado a cada solicitação. Qualquer solicitação que exija autenticação retornará 401se não for fornecida.

amora
fonte
1
"uma vez que cada solicitação pode incluir credenciais sem afetar o usuário humano", a autenticação de três vias e o OAuth foram inventados porque o conteúdo das aspas é ruim. Se você fornecer credenciais com cada solicitação sem um mecanismo no servidor para revogá-las, isso seria inseguro se usado sem SSL.
Slavo
1
Sempre que existe um conceito de usuário, algo precisa ser passado do cliente para o servidor para identificar qual usuário. Um token OAuth certamente pode servir como "credenciais" aqui, em vez de uma combinação real de usuário / senha. Proteger o canal com TLS certamente é sempre uma coisa boa, mas isso não vem ao caso. Mesmo se você usar um cookie, algum tipo de token ainda será enviado ao servidor a cada solicitação, apenas com um cabeçalho de cookie em vez de um cabeçalho de autenticação.
wberry
E se você não estiver usando TLS ou OAuth por qualquer motivo, o envio de um usuário / senha é sempre muito pior do que apenas uma vez? Se o invasor puder obter o usuário / senha, provavelmente também poderá obter o cookie da sessão.
W12 dez12
A diferença entre um cookie e um cabeçalho de autenticação como credenciais é que os cookies estão sempre associados a um domínio específico. Isso significa que, quando a API recebe um cookie, ela sabe de onde veio (foi escrita pelo mesmo domínio anteriormente). Com um cabeçalho, você nunca sabe e precisa implementar verificações específicas para isso. Em geral, eu concordo, ambas são credenciais, mas acho que a transferência de credenciais não é login. Login é a ação ativa de abrir a porta. No caso de autenticação de três vias, apenas a primeira aprovação do cliente seria o login.
Slavo 19/12/12