Por que existe um fluxo de "Código de autorização" no OAuth2 quando o fluxo "implícito" funciona tão bem?


264

Com o fluxo "Implícito", o cliente (provavelmente um navegador) receberá um token de acesso, depois que o Proprietário do Recurso (ou seja, o usuário) deu acesso.

No entanto, com o fluxo "Código de Autorização", o cliente (geralmente um servidor da Web) obtém um código de autorização depois que o Proprietário do Recurso (ou seja, o usuário) concede acesso. Com esse código de autorização, o cliente faz outra chamada para a API, passando client_id e client_secret junto com o código de autorização para obter o token de acesso. Tudo bem descrito aqui .

Ambos os fluxos têm exatamente o mesmo resultado: um token de acesso. No entanto, o fluxo "implícito" é muito mais simples.

A pergunta: por que se preocupar com o fluxo "Código de autorização", quando o fluxo "implícito" parece estar bom? Por que não usar também "Implícito" para servidor da web?

É mais trabalho, tanto para o provedor quanto para o cliente.



1
Obrigado, leia já. Mas não responde à pergunta.
Aron Woost

1
Boa pergunta, na verdade, e raramente respondida :) Veja abaixo.
Nicolas Garnier

1
@AronWoost Eu acho que você não entendeu aplicativo web Server e aplicativo navegador
onmyway133

@entropy Essa foi a minha pergunta; por que não usar o fluxo do navegador também para o servidor.
Aron Woost

Respostas:


293

tl; dr: Tudo isso por motivos de segurança.

O OAuth 2.0 queria atender a esses dois critérios:

  1. Você deseja permitir que os desenvolvedores usem URI de redirecionamento não HTTPS, porque nem todos os desenvolvedores têm um servidor habilitado para SSL e, se o fazem, ele nem sempre é configurado corretamente (certificados SSL confiáveis ​​e não autoassinados, relógio do servidor sincronizado ...).
  2. Você não deseja que os hackers possam roubar acesso / atualizar tokens interceptando solicitações.

Detalhes abaixo:

O fluxo implícito só é possível em um ambiente de navegador por motivos de segurança:

No fluxo implícito, o token de acesso é passado diretamente como um fragmento de hash (não como um parâmetro de URL). Uma coisa importante sobre o fragmento de hash é que, depois de seguir um link que contém um fragmento de hash, apenas o navegador está ciente do fragmento de hash. Os navegadores passarão o fragmento de hash diretamente para a página da web de destino (o URI de redirecionamento / a página do cliente). Fragmento de hash tem as seguintes propriedades:

  • Eles não fazem parte da solicitação HTTP, portanto, não podem ser lidos pelos servidores e, por isso, não podem ser interceptados por servidores / roteadores intermediários (isso é importante).
  • Eles existem apenas no navegador - lado do cliente -, portanto, a única maneira de ler o fragmento de hash é usando JavaScript que é executado na página.

Isso torna possível transmitir um token de acesso diretamente ao cliente sem o risco de ser interceptado por um servidor intermediário. Isso tem a ressalva de ser possível apenas no lado do cliente e precisa de javascript executando o lado do cliente para usar o token de acesso.

O fluxo implícito também possui problemas de segurança que requerem mais lógica para solucionar / evitar, por exemplo:

  • Um invasor pode obter um token de acesso de um usuário em um site / aplicativo diferente (digamos se ele é o proprietário do outro site / aplicativo), registrar o token em seu site e passá-lo como um parâmetro de URL no seu site portanto, representando o usuário em seu site. Para evitar isso, verifique o ID do cliente associado ao token de acesso (por exemplo, para o Google, você pode usar o ponto de extremidade tokeninfo) para garantir que o token tenha sido emitido com seu próprio ID de cliente (por exemplo, por seu próprio aplicativo) ou verifique a assinatura se você estiver usando um IDToken (mas isso requer o segredo do seu cliente).
  • Se a solicitação de autenticação não se originou de sua própria propriedade (chamada ataques de fixação de sessão), para evitar isso, você deseja gerar um hash aleatório no seu site, salve-o em um cookie e passe o mesmo hash no parâmetro de URL do estado de a solicitação de autenticação, quando o usuário voltar, verifique o parâmetro state com o cookie e ele deverá corresponder.

No fluxo do código de autorização , não é possível transmitir um token de acesso diretamente em um parâmetro de URL, porque os parâmetros de URL fazem parte da Solicitação HTTP; portanto, qualquer servidor / roteador intermediário pelo qual sua solicitação passaria (poderia ser centenas) poderia leia o token de acesso se você não estiver usando uma conexão criptografada (HTTPS), permitindo o que é conhecido como ataques Man-in-the-middle.

Passar o token de acesso diretamente em um parâmetro de URL poderia, em teoria, ser possível, mas o servidor de autenticação teria que garantir que o URI de redirecionamento esteja usando HTTPS com criptografia TLS e um certificado SSL 'confiável' (normalmente de uma Autoridade de Certificação que não é gratuita) para garantir que o servidor de destino seja legítimo e que a solicitação HTTP esteja totalmente criptografada. Ter todos os desenvolvedores que compram um certificado SSL e configuram o SSL adequadamente em seu domínio seria uma grande dor e retardaria tremendamente a adoção. É por isso que é fornecido um "código de autorização" intermediário de uso único que apenas o destinatário legítimo poderá trocar (porque você precisa do segredo do cliente) e que o código será inútil para hackers em potencial que interceptem os pedidos em transações não criptografadas (porque eles não

Você também pode argumentar que o fluxo implícito é menos seguro; existem vetores de ataque em potencial, como falsificar o domínio durante o redirecionamento - por exemplo, seqüestrando o endereço IP do site do cliente. Esse é um dos motivos pelos quais o fluxo implícito concede apenas tokens de acesso (que deveriam ter um tempo de uso limitado) e nunca atualiza tokens (que são ilimitados no tempo). Para solucionar esse problema, recomendamos que você hospede suas páginas da Web em um servidor habilitado para HTTPS sempre que possível.


12
@AndyDufresne Essas duas solicitações precisam ser feitas por HTTPS (obrigatório), pois são solicitações ao servidor OAuth que devem oferecer suporte apenas a HTTPS. É apenas o servidor cliente / solicitante que não precisa oferecer suporte a HTTPS; portanto, somente o Auth Codepotencial é enviado em HTTP claro. Mas o Auth Codeé inútil sem o ID / Segredo do cliente. Basicamente, o ponto do fluxo do Código OAuth é que o ônus de ter um servidor habilitado para SSL está no provedor OAuth (Google / Facebook etc ...) e não nos usuários das APIs (você, eu).
Nicolas Garnier

5
Ok, agora sigo que o código de autenticação pode ser passado através de HTTP simples e corre o risco de ser farejado. Tornando-o um código único e aceitando o segredo do cliente para trocá-lo por um token de acesso, o servidor de autorização pode impedir o ataque Man-in-the-middle. Mas isso também não se aplica ao token de acesso? Como o usuário da API pode estar em HTTP simples, não haverá o risco de o token de acesso ser detectado pelo hacker? PS - Aprecio seus esforços em explicar o conceito mesmo depois de um tempo desde que esse segmento estava ativo. Obrigado !
Andy Dufresne

8
no pb :) As solicitações para a API - que é quando o token de acesso é enviado pela conexão (para autorizar a solicitação) - também são feitas sobre HTTPS obrigatoriamente. Em teoria, o cliente nunca deve enviar o token de acesso por fio em HTTP simples a qualquer momento.
Nicolas Garnier

5
O token de acesso nesta etapa faz parte da resposta da solicitação HTTPS do cliente para o servidor de recursos. Essa resposta ainda está criptografada.
Nicolas Garnier

13
Basicamente, as solicitações iniciadas do cliente para o servidor de recursos são feitas via HTTPS (porque o servidor proprietário do recurso precisa oferecer suporte a HTTPS). Apenas as solicitações iniciadas de outro local para o cliente podem ser feitas por HTTP (porque o servidor do cliente pode não suportar HTTPS). Por exemplo, o redirecionamento que ocorre durante o fluxo de autenticação após o usuário conceder autorização na página gant é um redirecionamento iniciado do navegador para o servidor do cliente e pode ser feito em HTTP.
Nicolas Garnier

8

o fluxo implícito facilita todo o fluxo, mas também menos seguro .
Como o aplicativo cliente, que normalmente é JavaScript em execução em um navegador, é menos confiável, nenhum tokens de atualização para acesso de longa duração são retornados.
Você deve usar esse fluxo para aplicativos que precisam de acesso temporário (algumas horas) aos dados do usuário.
O retorno de um token de acesso aos clientes JavaScript também significa que seu aplicativo baseado em navegador precisa ter um cuidado especial - pense nos XSS Attacks que podem vazar o token de acesso para outros sistemas.

https://labs.hybris.com/2012/06/05/oauth2-the-implicit-flow-aka-as-the-client-side-flow


Eu esperava que, quando alguém tem uma vulnerabilidade XSS, mesmo o fluxo do código de autorização não ajuda muito. Mas eu concordo que, como a maneira como o token de acesso é passado para javascript no fluxo implícito é padronizada (como um fragmento de hash), e se houver vulnerabilidade XSS no site, construa um ataque que leia o token de acesso do hash da URL fragmento é bastante fácil. Com o fluxo do código de autorização, por outro lado, a falsificação de solicitação entre sites pode ser possível.
Marcel

Além disso, não se trata apenas de scripts entre sites. Qualquer biblioteca JavaScript em execução no seu site pode tentar roubar o token de acesso (por exemplo, bibliotecas CDN de terceiros ou bibliotecas de código aberto que sua estrutura javascript usa).
Marcel

2
O XSS não é um grande problema agora quando temos cabeçalhos da Política de Segurança de Conteúdo e hashes de Sub Resource Integrity (SRI).
Sergey Ponomarev 24/04

4

Na especificação do OAuth :

4.2 Concessão implícita

O tipo de concessão implícita é usado para obter tokens de acesso (não suporta a emissão de tokens de atualização) e é otimizado para clientes públicos conhecidos por operar um URI de redirecionamento específico. Esses clientes geralmente são implementados em um navegador usando uma linguagem de script como JavaScript.

Como esse é um fluxo baseado em redirecionamento, o cliente deve ser capaz de interagir com o agente do usuário do proprietário do recurso (geralmente um navegador da web) e receber pedidos de entrada (via redirecionamento) do servidor de autorização.

Diferentemente do tipo de concessão do código de autorização, no qual o cliente faz solicitações separadas de autorização e de um token de acesso, o cliente recebe o token de acesso como resultado da solicitação de autorização.

O tipo de concessão implícita não inclui autenticação de cliente e depende da presença do proprietário do recurso e do registro do URI de redirecionamento. Como o token de acesso é codificado no URI de redirecionamento, ele pode ser exposto ao proprietário do recurso e a outros aplicativos que residem no mesmo dispositivo.

Então, o que podemos considerar:

  1. Isso é para OAuth público, ou seja, quando o cliente não precisa ser registrado e não possui seus próprios segredos. Mas o servidor de autenticação verifica o URL de redirecionamento e isso é realmente suficiente para segurança.

  2. O token de acesso ocorre na barra de endereços do navegador, para que o usuário possa copiar o URL e enviar para outra pessoa, além de se registrar como usuário, ou seja, é como a fixação da sessão. Mas o navegador faz um redirecionamento adicional com a substituição do histórico para remover o fragmento de hash do URL. Também é possível para um hacker roubar o token de acesso, farejando um tráfego HTTP, mas isso pode ser facilmente protegido pelo HTTPS. Algumas extensões de navegador mal-intencionadas podem ter acesso a URLs da barra de endereço, mas isso é uma situação ruim, como certificado HTTPS quebrado. E mesmo o fluxo de código Auth não pode ajudar aqui éter. Então, o que vejo é que a passagem do token de acesso via fragmento hash de URL é absolutamente segura.

  3. A separação do token de acesso efêmero e do token de atualização é inútil ao usar um HTTPS e, para ser honesto, não é tão útil, mesmo em HTTP bruto. Mas o fato de o cliente via fluxo implícito não poder receber o token de atualização também é um absurdo.

Portanto, acho que devemos introduzir um novo fluxo de concessão "seguro implícito" que funcione estritamente em https, permita o token de atualização (ou devemos nos livrar deles) e é preferível ao fluxo de concessão do Auth Cose


3

Para nós, nossos clientes queriam se autenticar com o aplicativo em seus telefones uma vez e não precisam fazer login novamente por semanas. Com o fluxo de código, você recebe um token de atualização junto com o seu token de acesso. O fluxo implícito não fornece um token de atualização. O token de acesso tem uma validade relativamente curta, mas os tokens de atualização podem ter uma validade de até 90 dias. Sempre que o token de acesso expira, o código do cliente e do servidor pode usar esse token de atualização para obter um novo token de acesso mais o token de atualização, tudo nos bastidores, sem qualquer intervenção do usuário. Um token de atualização pode ser usado apenas uma vez. Você não pode fazer isso com o fluxo implícito. Se você estiver usando o Implicit Flow e seu usuário não interagir com seu aplicativo por mais de uma hora, eles deverão fazer login novamente quando voltarem. Isso não era aceitável em nosso caso de uso,

Isso funciona e é seguro porque os tokens de atualização podem ser revogados. Se um cliente disser que perdeu o telefone ou o laptop ou um hacker acessou a área de trabalho, podemos simplesmente revogar todos os tokens de atualização desse usuário. Durante todo o processo, nenhuma informação de identificação pessoal (PII) toca em nosso código - a senha do usuário.

O fluxo de código é incrível, mas é preciso mais trabalho. O MS não tem uma biblioteca Angular para lidar com isso atualmente, então tive que escrever uma. Se você estiver interessado, eu posso ajudá-lo.


2

Minha resposta é: você não pode implementar o fluxo implícito de maneira simples e segura com o servidor de aplicativos da web.

O processo de autorização de aplicativos da Web envolve a interação do usuário, portanto, o Authentication Server deve redirecionar o navegador do usuário de volta à página de destino do aplicativo Web após a autenticação e o consentimento do usuário (não vejo outra maneira de transmitir o usuário ao aplicativo Web após alguma interação com Servidor de autenticação).

Então, o token deve ser passado para o aplicativo da web usando o URL de redirecionamento, certo?

Como o @NicolasGarnier explicou em sua resposta e comentários, não há como passar o token como um fragmento de URL - ele não alcançará o servidor de aplicativos da web.

E passar o token como um parâmetro de URL do URL de redirecionamento seria inseguro, mesmo em HTTPS: se a página de destino (seja "página de cumprimentos") contiver recursos (imagens, scripts, etc), esses recursos serão obtidos pelo navegador através da série de solicitações HTTP (S) (cada uma com Referer cabeçalho HTTP contendo URL exato da "página de cumprimentos", incluindo parâmetros de URL). É assim que o token pode vazar.

Portanto, parece que não há como passar token no URL de redirecionamento. É por isso que você precisa da segunda chamada (do servidor de autenticação para o cliente (mas para qual URL?) Ou do cliente para o servidor de autenticação (a segunda chamada no fluxo do código de autorização))

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.