OAuth2 ROPC x autenticação básica para APIs REST públicas?


21

O caso de uso específico em que estou interessado aqui é autenticar clientes REST em pontos de extremidade do servidor publicamente disponíveis (como uma API REST pública).

A solução mais simples aqui é a autenticação básica . Mas ouço frequentemente o OAuth2 apresentado como uma solução de autenticação superior em quase todas as circunstâncias.

O problema é que o único tipo de concessão OAuth2 possível para um cliente REST autenticado em um servidor REST é credenciais de senha do proprietário do recurso (ROPC) , porque as concessões de código e concessões implícitas exigem uma interface do usuário / página da web (hospedada pelo servidor de autenticação) para o usuário para efetuar login e autorizar manualmente o aplicativo cliente.

A maneira como o ROPC funciona é enviando o nome de usuário / senha do proprietário do recurso e o ID do cliente como parâmetros de string de consulta ?!? Isso é ainda menos seguro (IMHO) do que o Basic Auth, que pelo menos a base 64 codifica as credenciais e as envia dentro de um cabeçalho que pode ser criptografado pelo TLS!

Então, pergunto: no contexto das APIs REST públicas, o OAuth2 ROPC é realmente melhor que o Auth básico? O que é mais seguro que o OAuth2 ROPC?


Atualizar

Acabei de ler este excelente artigo que explica a segurança REST não baseada em OAuth2 da Amazon para a AWS. É essencialmente uma solução baseada em chave privada, na qual os hashes de cada solicitação REST são gerados e enviados como barras laterais ao lado da solicitação normal (não criptografada). Somente o cliente e o servidor conhecem a chave privada; portanto, quando o servidor recebe a solicitação (novamente, contendo a solicitação normal + a solicitação de hash), o servidor consulta a chave privada do cliente, aplica o mesmo hash à solicitação normal e depois compara os dois hashes.

Isso parece muito mais complicado, complexo e seguro do que o ROPC do OAuth2! A menos que eu esteja perdendo algo importante aqui, o OAuth2 ROPC está apenas enviando e client_id, como parâmetros de string de consulta ... totalmente e totalmente inseguro! Essa solução baseada em HMAC / hash parece ser muito mais impressionante e segura.usernamepassword

A questão é que até o autor desse artigo continua dizendo:

Você também [lentamente] perceberá e aceitará que, em algum momento, precisará implementar o OAuth ...

Ba-ba-bwhat?!?! Se o OAuth2 é menos seguro que esta solução inteligente de HMAC / hash, por que o autor deste artigo acha que o OAuth precisa ser adotado em algum momento. Estou tão confuso.


De que tipo de cliente você está falando? Presumo que a maioria dos clientes terá uma interface do usuário. Nesse caso, você pode carregar a página de login do OAuth em uma visualização na web (computador, dispositivo móvel) ou redirecionar diretamente para ela (web). Não vejo por que você precisa evitar a interface do usuário.
Decyclone

@ decyclone, por favor leia a primeira frase da pergunta! Estou abordando clientes REST (HTTP sem cabeça) autenticados nos serviços REST.
smeeb 18/09/2015

A pergunta que estou fazendo é se esse cliente tem alguma interface do usuário? Mesmo se não tivesse, vi aplicativos sem interface do usuário abrirem uma caixa de diálogo pelo menos para autenticação.
decyclone

@decyclone nenhum cliente REST puro não possui interface do usuário, embora as UIs normalmente usem um cliente REST puro para conectar-se a um serviço REST. Um caso de uso é uma ferramenta de linha de comando que usa um cliente REST para enviar comandos do usuário (inseridos no shell) para o serviço REST. Retirar uma interface do usuário de um shell simplesmente não é uma solução aceitável aqui.
smeeb

1
Mas, devo observar, existem muitos outros casos de uso fora de uma linha de comando / shell. Outro caso de uso é um cliente REST / HTTP puro Java / Ruby / Python que não possui interface com o usuário e pode estar em execução em um servidor back-end que não possui interface com o usuário. O servidor back-end precisa se comunicar com outro servidor back-end pelo REST. Aqui, não seria estranho e hacky exibir uma interface do usuário quando o servidor de back-end nº 1 precisar falar com o servidor de back-end nº 2, o verdadeiro problema é que não há cliente de navegador / interface do usuário para exibir a página de login e não há recursos humanos estar lá para fazer login !!!
smeeb 18/09/2015

Respostas:


24

A resposta para sua pergunta pode estar no nível do código, do protocolo ou da arquitetura. Tentarei resumir aqui a maioria dos problemas no nível do protocolo, já que isso geralmente é crítico na análise de prós e contras. Lembre-se de que o OAuth2 é muito mais do que credenciais de senha do proprietário do recurso que, de acordo com a especificação, existem por "motivos herdados ou de migração", são consideradas "risco mais alto que outros tipos de concessão" e a especificação afirma explicitamente que os clientes e os servidores de autorização "DEVE minimizar o uso deste tipo de concessão e utilizar outros tipos de concessão sempre que possível".

Ainda existem muitas vantagens em usar o ROPC sobre a autenticação básica, mas antes de entrarmos nisso, vamos entender a diferença básica de protocolo entre o OAuth2 e a autenticação básica. Por favor, tenha paciência comigo enquanto explico isso e chegarei ao ROPC mais tarde.

Fluxos de autenticação do usuário

Existem quatro funções definidas na especificação do OAuth2. Com exemplos, eles são:

  1. Proprietário do recurso: o usuário que tem acesso a algum recurso, por exemplo, no seu caso, usuários diferentes podem ter diferentes níveis de acesso à API REST;
  2. O cliente: geralmente o aplicativo que o usuário está usando e precisa acessar o recurso para fornecer serviços ao usuário;
  3. Servidor de recursos: a API REST no seu caso; e
  4. Servidor de autorização: o servidor ao qual as credenciais do usuário são apresentadas e o que autenticará o usuário.

Quando um aplicativo cliente é executado, é concedido acesso aos recursos com base no usuário. Se um usuário tiver privilégios de administrador, os recursos e operações disponíveis para o usuário na API REST podem ser muito mais do que um usuário sem privilégios de administrador.

O OAuth2 também permite a possibilidade de usar um único servidor de autorização com vários clientes e para vários recursos. Como exemplo, um servidor de recursos pode aceitar a autenticação do usuário com o Facebook (que pode atuar como servidor de autorização nesse caso). Portanto, quando o usuário executa um aplicativo (ou seja, o cliente), ele envia o usuário para o Facebook. O usuário digita suas credenciais no Facebook e o cliente recebe um "token" que pode ser apresentado ao servidor de recursos. O servidor de recursos examina o token e o aceita depois de verificar se o Facebook realmente o emitiu e permite ao usuário acessar o recurso. Nesse caso, o cliente nunca vê as credenciais do usuário (ou seja, as credenciais do Facebook).

Mas digamos que você esteja gerenciando a identidade do usuário (e tenha um servidor de autorização) em vez do Facebook, que já concede tokens ao seu cliente. Agora, digamos que você também tenha um parceiro e deseje permitir que seu aplicativo (ou seja, cliente) acesse sua API REST. Com autenticação básica (ou mesmo ROPC), o usuário fornecerá credenciais para esse cliente, que a enviará ao servidor de autorização. O servidor de autorização fornecerá um token que pode ser usado pelo cliente para acessar os recursos. Infelizmente, isso significa que as credenciais do usuário agora também estão visíveis para esse cliente. No entanto, você não deseja que o aplicativo de um parceiro (que possa ser externo à sua organização) saiba a senha de um usuário. Esse é um problema de segurança agora. Para atingir esse objetivo,

Portanto, com o OAuth2, o ideal seria não usar o ROPC nesses casos, e sim usar um diferente, como o fluxo do código de autorização. Isso protege qualquer aplicativo de conhecer as credenciais do usuário que são apresentadas apenas ao servidor de autorização. Portanto, as credenciais de um usuário não são vazadas. Os mesmos problemas se aplicam à autenticação básica, mas na próxima seção, explicarei como o ROPC ainda é melhor porque as credenciais do usuário ainda não precisam ser armazenadas pelo cliente no ROPC para acesso persistente pelos clientes.

Observe que quando o usuário acessa o servidor de autorização, ele também pode solicitar ao usuário que confirme que deseja permitir que o cliente acesse os recursos em seu nome ou não. É por isso que é chamado servidor de autorização, porque o processo de autorização de um cliente para acessar recursos está envolvido no processo. Se o usuário não autorizar o cliente, ele não terá acesso aos recursos. Da mesma forma, se o próprio usuário não tiver acesso aos recursos, o servidor de autorização ainda poderá negar o acesso e não emitir um token.

Na autenticação básica, até o servidor de autorização e o servidor de recursos são combinados em uma única entidade. Portanto, o servidor de recursos deseja autorizar o usuário, solicitando as credenciais do cliente. O cliente fornece as credenciais usadas pelo servidor de recursos para autenticar o usuário. Isso significa que vários servidores de recursos exigirão essencialmente credenciais do usuário.

Emissão de tokens

Os clientes obtêm tokens do servidor de autorização, mantêm-nos por perto e os utilizam para acessar os recursos (mais detalhes sobre os próprios tokens abaixo). Os clientes nunca sabem a senha do usuário (em fluxos diferentes do ROPC) e não precisam armazená-la. No ROPC, mesmo que os clientes saibam a senha do usuário, eles ainda não precisam armazená-la porque usam esses tokens para acessar recursos. Por outro lado, na autenticação básica, se um cliente não deseja que o usuário forneça credenciais em todas as sessões, o cliente deve armazenar a senha do usuário para fornecê-la na próxima vez. Essa é uma grande desvantagem do uso da autenticação básica, a menos que o cliente seja apenas um aplicativo da Web; nesse caso, os cookies podem resolver algumas dessas preocupações. Com aplicativos nativos, isso geralmente não é uma opção.

Há outro aspecto do OAuth2 que está relacionado à forma como os tokens são emitidos e funcionam. Quando um usuário fornece credenciais ao servidor de autorização (mesmo no ROPC), o servidor de autorização pode fornecer um ou mais dos dois tipos de tokens: 1) token de acesso e 2) token de atualização.

Os tokens de acesso são enviados ao servidor de recursos, que concederá acesso aos recursos após a validação, e geralmente eles têm uma vida útil curta, por exemplo, 1 hora. Os tokens de atualização são enviados ao servidor de autorização pelo cliente para obter outro token de acesso quando ele expira e geralmente têm uma vida útil longa (por exemplo, alguns dias a meses ou até anos).

Quando o cliente fornece o token de acesso ao servidor de recursos, ele olha para o token e, após a validação, olha dentro do token para determinar se deve permitir acesso ou não. Desde que o token de acesso seja válido, o cliente pode continuar usando-o. Digamos que o usuário feche o aplicativo e o inicie no dia seguinte, e o token de acesso expirou. Agora, o cliente fará uma chamada para o servidor de autorização e apresentará o token de atualização, assumindo que ele não expirou. O servidor de autorização, uma vez que já emitiu o token, o verifica e pode determinar que o usuário não precisa fornecer as credenciais novamente e, portanto, fornece outro token de acesso ao cliente. O cliente agora tem acesso ao servidor de recursos novamente. É assim que geralmente os aplicativos clientes do Facebook e Twitter solicitam credenciais uma vez e, em seguida, não exigem que o usuário forneça credenciais novamente. Esses aplicativos nunca precisam conhecer as credenciais dos usuários e ainda podem acessar recursos toda vez que o usuário inicia o aplicativo.

Agora, o usuário pode acessar o servidor de autorização (por exemplo, no perfil de usuário do Facebook), alterar a senha sem afetar os aplicativos clientes. Todos continuarão funcionando corretamente. Se o usuário perder um dispositivo no qual ele já tinha um aplicativo com tokens de atualização, ele poderá solicitar ao servidor de autorização (por exemplo, o Facebook) para "desconectá-lo" dos aplicativos que o servidor de autorização (por exemplo, o Facebook) realizará por não respeitar nenhuma existente atualize os tokens e force o usuário a fornecer credenciais novamente quando tentar acessar recursos através desses aplicativos.

JWT é simplesmente o formato de token geralmente usado com OAuth2 e OpenID Connect. Os métodos de assinatura e validação do token também são padronizados com bibliotecas disponíveis para aqueles, em vez de todos os servidores de recursos que implementam outra solução. Portanto, a vantagem está na reutilização do código que foi examinado e continua a ser suportado.

Implicações de segurança

A autenticação básica será mais fraca quando qualquer um dos cenários acima estiver na imagem. Há também um extenso modelo de ameaça para o OAuth2 disponível para desenvolvedores que podem usar as sugestões contidas nele para evitar vulnerabilidades comuns em suas implementações. Se você seguir o modelo de ameaça, verá que muitas vulnerabilidades relacionadas à implementação (como redirecionador aberto e CSRF) também são cobertas. Não passei pela comparação daqueles contra autenticação básica nesta resposta.

A última grande vantagem do OAuth2 é que o protocolo é padronizado e vários servidores de autorização, clientes e servidores de recursos o honram. Várias bibliotecas estão disponíveis para desenvolvedores, que são mantidas para que problemas de segurança sejam encontrados nas implementações, as bibliotecas são atualizadas e permitem a interoperabilidade.

Conclusão

Se você estiver escrevendo um novo aplicativo, IMO, o caso ideal seria evitar a autenticação básica e o ROPC devido aos problemas inerentes a eles. No entanto, cada aplicativo tem necessidades, cronogramas, proficiência de desenvolvedor etc. diferentes, portanto, a decisão é caso a caso. Mas mesmo que você não tenha mais necessidade do que a autenticação básica, escolhendo-a, poderá se trancar em uma arquitetura que pode não ser fácil de estender (por exemplo, se você tiver vários servidores no futuro, não necessariamente precisará ter o usuário fornece credenciais para cada uma delas, apenas fornece ao servidor de autorização uma vez, o que pode distribuir tokens etc.)

Observe que eu não mencionei seu comentário sobre como as credenciais são enviadas por cabo, porque elas podem ser protegidas usando TLS ou um protocolo semelhante ou prova de posse, etc. Como alguém já sugeriu, a codificação da base 64 é 0 de segurança, por favor, não ser iludido por isso. As diferenças mencionadas acima geralmente são no nível arquitetural e, portanto, é aí que eu me concentro, porque a arquitetura é a mais difícil de mudar depois de implementada.

O Azure Active Directory B2C Basic , um serviço no qual trabalho e foi lançado recentemente para visualização pública, permite que aplicativos de terceiros usem o AAD como servidor de autorização com interoperabilidade com IDPs sociais (como Facebook, Google etc.). Ele também permite que os usuários criem suas próprias contas em vez de usar IDPs sociais e esses podem ser usados ​​posteriormente para fins de autenticação. Existem alguns outros serviços como esse (por exemplo, outro que eu conheço é o auth0), que pode ser usado pelos desenvolvedores para terceirizar completamente a autenticação e o gerenciamento de usuários para seus aplicativos e recursos. As mesmas características de protocolo mencionadas acima são usadas pelos desenvolvedores para desacoplar o servidor de autorização (AAD), um recurso (por exemplo, suas APIs REST), o cliente (por exemplo, seus aplicativos móveis) e usuários. Espero que esta explicação ajude um pouco.


Obrigado por uma grande angular, mas não acho que essas vantagens (a) letting the user agent hold just the token instead of the password, (b) allowing a password change without disrupting existing client apps, (c) allowing users log out other sessionssejam específicas para os fluxos de autenticação de token. As autenticações Basic e token não mencionam as funções (b) e (c) em suas especificações. A implementação (b) e (c) parece possível para qualquer tipo de autenticação. Isso envolveria o controle de senhas (de preferência seus hashes). A vantagem (a) parece depender do escopo mais amplo da senha.
eel ghEEz 26/02

Como podemos usar o OAuth se o usuário (Proprietário do Recurso) não possui credenciais com um servidor de Autorização externo, mas ele possui credenciais no aplicativo Cliente? Ou seja, temos o Proprietário do recurso (usuário), o Cliente (representando o usuário e também contendo credenciais para o usuário) e o Servidor de recursos. Como um servidor de recursos pode autenticar e autorizar o usuário?
Arun Avanathan 14/03

3

Acredito que você esteja mal informado sobre a criptografia em torno das variáveis ​​GET em um URL

As únicas pessoas que podem visualizar as variáveis ​​GET em uma solicitação são o computador original e o servidor de recebimento ( link ).

Somente a pesquisa de DNS com base no domínio para o qual a solicitação HTTPS é enviada não é criptografada. Tudo o resto, as portas, as variáveis ​​GET, o ID do recurso, são criptografadas.

A única ressalva é que o servidor de recebimento pode desconectar o caminho completo da solicitação, mas você está no controle para poder proteger esses dados da maneira que achar melhor.


3

A autenticação básica não é uma boa maneira de proteger sua API REST. Expliquei as razões pelas quais nesta resposta .

Ao criar uma API REST, você está implementando o servidor de recursos nos termos do OAuth2. Tudo o que sua API precisa fazer é validar se o token passado junto com a solicitação no cabeçalho HTTP de Autorização é válido e de um emissor confiável. Consulte este link para obter as etapas de como implementar a validação se não houver uma biblioteca disponível.

Como o seu cliente adquire o token do servidor de autorização depende de que tipo de cliente é. Lembre-se de que você precisa especificar o tipo de cliente que usará quando registrar o cliente no servidor de autorização.

No caso de um aplicativo Web conversando com seu servidor, ele poderá usar a concessão do código de autorização . Se for um cliente não confiável, como um aplicativo móvel ou um aplicativo JavaScript, deverá usar a concessão implícita .

Para serviços de back-end que não podem interagir com o proprietário de um recurso, você pode usar a concessão de credenciais do cliente . Para ferramentas de linha de comando, você pode usar credenciais do cliente ou a concessão de senha do proprietário do recurso .

Tudo depende do tipo de cliente que você está usando.

Por fim, a validação de um token JWT acontece no servidor de recursos sem a necessidade de conversar com o servidor de autorização. Isso leva a uma arquitetura escalável melhor do que soluções que precisam procurar dados particulares para cada cliente.


1

É seguro ou não seguro. Nem mais nem menos. Ter base64 não torna a autenticação básica (ou qualquer outra coisa) mais segura.

Não há nada errado em enviar algo não criptografado se estiver usando um tubo criptografado como o Https.

OAuth tem mais recursos, use-o se necessário. Para qualquer outra coisa, por exemplo, serviços bancários, o uso de respostas a desafios básicas é bom e seguro.


0

Eu acho que você precisa entender as terminologias primeiro. Você está comparando - Autorização e assinatura digital

OAuth é um padrão aberto para Autorização , onde o que a amazon está fazendo (conforme o artigo e os detalhes fornecidos em sua pergunta) está criando uma assinatura digital válida que fornece ao destinatário (aqui amazon) motivos para acreditar que a mensagem foi criada por um conhecido remetente, que o remetente não pode negar ter enviado a mensagem ( autenticação e não repúdio)

Para qual mecanismo de autorização usar, mais ou menos depende do seu caso de uso.

Abaixo está o que pode ser encontrado no StackOverflow aqui :

Autenticação básica que requer um hash muito simples para calcular o cabeçalho único necessário - o OAuth é sem dúvida uma autenticação mais cara. O importante é perceber que os dois mecanismos de autenticação servem a propósitos totalmente diferentes. A autenticação básica é para autenticar um cliente em um aplicativo primário. OAuth é para autorizar terceiros a acessar dados de clientes de um aplicativo primário. Ambos têm seu lugar e a seleção de um sobre o outro deve ser orientada pelo caso de uso específico da implementação.

E aqui está outro artigo interessante comparando os dois.

A autenticação básica sobre SSL é realmente bastante responsável, do ponto de vista simplista da segurança. Quando estamos lutando com nomes de usuário e senhas, a autenticação básica é uma solução predominante, pois é tão fácil de implementar. A transmissão de credenciais é criptografada em SSL, e o uso do cabeçalho "Autorização" é onipresente nos clientes e sistemas HTTP.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.