Qual é o objetivo do tipo de autorização de concessão implícita no OAuth 2?

254

Não sei se tenho algum tipo de ponto cego ou o quê, mas li as especificações do OAuth 2 várias vezes e examinei os arquivos da lista de discussão, e ainda não encontrei uma boa explicação sobre por que a concessão implícita foi desenvolvido um fluxo para obter tokens de acesso. Comparado com o código de autorização concedido, parece desistir da autenticação do cliente sem um motivo muito convincente. Como isso é "otimizado para clientes implementados em um navegador usando uma linguagem de script" (para citar a especificação)?

Ambos os fluxos começam da mesma forma (fonte: http://tools.ietf.org/html/draft-ietf-oauth-v2-22 ):

  1. O cliente inicia o fluxo direcionando o agente do usuário do proprietário do recurso para o terminal de autorização.
  2. O servidor de autorização autentica o proprietário do recurso (por meio do agente do usuário) e estabelece se o proprietário do recurso concede ou nega a solicitação de acesso do cliente.
  3. Supondo que o proprietário do recurso conceda acesso, o servidor de autorização redireciona o agente do usuário de volta ao cliente usando o URI de redirecionamento fornecido anteriormente (na solicitação ou durante o registro do cliente).
    • O URI de redirecionamento inclui um código de autorização (fluxo de código de autorização)
    • O URI de redirecionamento inclui o token de acesso no fragmento de URI (fluxo implícito)

Aqui é onde os fluxos se dividem. Nos dois casos, o URI de redirecionamento neste momento é para algum terminal hospedado pelo cliente:

  • No fluxo do código de autorização, quando o agente do usuário atinge esse ponto de extremidade com o código de autorização no URI, o código nesse ponto de extremidade troca o código de autorização junto com suas credenciais do cliente por um token de acesso que pode ser usado conforme necessário. Por exemplo, poderia gravá-lo em uma página da web que um script da página pudesse acessar.
  • O fluxo implícito ignora completamente esta etapa de autenticação do cliente e apenas carrega uma página da web com o script do cliente. Há um truque interessante aqui com o fragmento de URL que impede que o token de acesso seja transmitido muito, mas o resultado final é basicamente o mesmo: o site hospedado pelo cliente exibe uma página com algum script que pode capturar o token de acesso .

Daí a minha pergunta: o que foi ganho aqui ao pular a etapa de autenticação do cliente?

Dan Taflin
fonte
Dê uma olhada no seguinte: ibm.com/developerworks/wikis/display/…
Håvard Geithus
5
O link no comentário anterior está morto. Aqui está uma atualização
AndrewR
3
Li todas as respostas aqui, mas ainda não entendo como não é seguro exigir que um segredo de cliente privado para obter um token de acesso. Digamos que o TrustedAppDeveloper libere o TrustedPopularApp que permite que os usuários concedam permissões (digamos, usando o oauth do Twitter) usando uma concessão implícita. Se eu sou EvilAppDeveloper, o que me impede de criar um aplicativo que transmita TrustedPopularAppId como client_id em uma solicitação de concessão implícita e execute ações (como enviar um spam por feed) em nome do usuário, que agora parecem provenientes de TrustedPopularApp ?
adevine
Eu me pergunto a mesma coisa que adevine. Mas, os aplicativos mais prováveis ​​que exigem uma solicitação de concessão implícita, não precisam de mais autenticação, como todos recebem.
Mave
13
@adevine O que impediria o EvilApp no ​​seu cenário de se autenticar no Twitter como TrustedPopularApp é que ele não poderia receber os retornos de chamada do Twitter, eles sempre seriam enviados para o URI que foi definido ao registrar o ID do cliente
Ivan

Respostas:

196

Aqui estão os meus pensamentos:

O objetivo do código de autenticação + token no fluxo de código de autorização é que o token e o segredo do cliente nunca sejam expostos ao proprietário do recurso porque eles viajam servidor a servidor.

Por outro lado, o fluxo de concessão implícito é para clientes implementados inteiramente usando javascript e executando no navegador do proprietário do recurso. Você não precisa de nenhum código do lado do servidor para usar esse fluxo. Então, se tudo acontecer no navegador do proprietário do recurso, não faz mais sentido emitir o código de autenticação e o segredo do cliente, porque o token e o segredo do cliente ainda serão compartilhados com o proprietário do recurso. A inclusão do código de autenticação e do segredo do cliente apenas torna o fluxo mais complexo sem adicionar mais segurança real.

Então a resposta sobre "o que foi ganho?" é "simplicidade".

Philip Peshin
fonte
4
Obrigado. É um bom ponto que, no fluxo do código de autorização, o proprietário do recurso nunca precise ver o token de acesso, enquanto nos clientes javascript isso é inevitável. No entanto, o segredo do cliente ainda pode ser mantido pelos clientes javascript usando o fluxo do código de autorização: após a autenticação e a obtenção de um token de acesso, o código do servidor passará o token para o cliente javascript. O que vejo agora, no entanto, é que o fluxo implícito de concessão permite a distribuição de SDKs javascript oauth, como o Facebook, liberando os desenvolvedores de escreverem seu próprio código oauth completamente.
Dan Taflin
3
Talvez eu acrescentasse que, o fluxo do código de autorização permite que os clientes armazenem os tokens e os reutilizem. No fluxo implícito, você nem sempre tem essa opção e, como tal, o fluxo implícito é uma escolha pragmática entre nível de segurança e conveniência.
PålOliver
2
Isso responde apenas pela metade e "o que foi perdido"?
EralpB
3
Não acho que seja uma resposta abrangente, o fluxo implícito não se destina a obter vantagem na simplicidade, mas a comprometer as preocupações de segurança com o aplicativo do lado do cliente. Auth code, juntamente com client_ide client_secretsão usados ​​para identificar clientes confiáveis ​​que podem atualizar tokens para um logon prolongado e para "logon offline" . No entanto, em um aplicativo do lado do cliente, não há nenhuma maneira de registrar cada cliente, daí o "simplificado" concessão tipo implícito para acesso temporário às informações do usuário
Chen Xie
1
Incluir o segredo do cliente não apenas torna o fluxo mais complexo, mas também menos seguro . O segredo do cliente não é um segredo se precisar ser enumerado no código do lado do cliente e, portanto, seria exposto à Internet. Se o seu ID do cliente for usado apenas em fluxos implícitos, isso não será um problema. Mas se ele também for usado em outra parte da sua plataforma para conceder tokens de atualização ou concessões de código de autorização, expor o segredo correspondente será um grande problema.
Ataraxia
94

Está lá por razões de segurança, não por simplicidade.

Você deve considerar a diferença entre o agente do usuário e o cliente :

O user-agent é o software pelo qual o usuário ("proprietário do recurso") se comunica com outras partes do sistema (servidor de autenticação e servidor de recursos).

O cliente é o software que deseja acessar os recursos do usuário no servidor de recursos.

No caso de agente-usuário e cliente dissociados, a concessão do código de autorização faz sentido. Por exemplo, o usuário usa um navegador da web (agente do usuário) para fazer login com sua conta do Facebook no Kickstarter. Nesse caso, o cliente é um dos servidores do Kickstarter, que lida com os logins do usuário. Este servidor obtém o token de acesso e o token de atualização do Facebook. Portanto, esse tipo de cliente considerado "seguro", devido ao acesso restrito, os tokens podem ser salvos e o Kickstarter pode acessar os recursos dos usuários e até atualizar os tokens de acesso sem a interação do usuário.

Se o agente do usuário e o cliente estiverem acoplados (por exemplo, aplicativo móvel nativo, aplicativo javascript), o fluxo de trabalho de autorização implícita pode ser aplicado. Ele depende da presença do proprietário do recurso (para inserir as credenciais) e não suporta tokens de atualização. Se esse cliente armazenar o token de acesso para uso posterior, será um problema de segurança, pois o token poderá ser facilmente extraído por outros aplicativos ou usuários do cliente. A ausência do token de atualização é uma dica adicional, de que este método não foi projetado para acessar os recursos do usuário na ausência do usuário.

artkoenig
fonte
2
Vejo que meu navegador está conectado à minha conta do Google há meses. Então, o Google usa o token de acesso no navegador ou um token de acesso com um longo prazo de validade? que diferença de uso entre o token de acesso com um longo prazo de validade e o token de acesso? qualquer outro cliente pode pegar o token de acesso e usá-lo quando o proprietário do recurso não estiver presente.
Mohammad Nikravan
Suponho que você queira dizer a diferença entre o token de atualização e o token de acesso com um longo prazo de validade ? O token de atualização não deve ser salvo em cenários inseguros, mas você pode salvar seu token de acesso (por exemplo, no armazenamento local do navegador). A segurança é alcançada mantendo o tempo de vida útil do seu token de acesso o mais baixo possível, embora ainda seja confortável para os usuários (por exemplo, você pode desconectá-los automaticamente após x minutos de inatividade). Se você usar tokens de acesso de longa duração, praticamente tornará obsoletos os tokens de atualização.
artkoenig
Obrigado pela sua explicação, mas também tenho outra confusão. Não entendo por que precisamos do fluxo "Código de autorização". Podemos alcançar o mesmo resultado no servidor por fluxo implícito (access_token) e um token de atualização. Parece que a única consideração de segurança do fluxo implícito é que access_code deve ter vida curta, portanto não pode ser usado no servidor para servidor. OK, mas o token de atualização resolve esse problema. Por que devemos usar um fluxo auth_code e solicitar access_token por esse token em um servidor para obter access_code, enquanto podemos obter o mesmo resultado com refresh_token?
Mohammad Nikravan
"o token pode ser facilmente extraído por outros aplicativos" Como?
Mvmn 9/03
@MohammadNikravan procure a resposta em stackoverflow.com/q/13387698/355438 #
5555 Lu55
60

A explicação usual é que a concessão implícita é mais fácil de implementar quando você está usando um cliente JavaScript. Mas acho que essa é a maneira errada de encarar. Se você estiver usando um cliente JavaScript que solicita recursos protegidos diretamente via XMLHttpRequest, a concessão implícita é sua única opção, embora seja menos segura. *

A concessão do Código de Autorização fornece segurança adicional, mas só funciona quando você tem um servidor da Web solicitando os recursos protegidos. Como o servidor da Web pode armazenar o token de acesso, você corre menos risco de expor o token de acesso à Internet e pode emitir um token que dura muito tempo. E como o servidor da Web é confiável, ele pode receber um "token de atualização", para obter um novo token de acesso quando o antigo expirar.

Mas - e este é um ponto fácil de perder - a segurança do fluxo do código de autorização funciona apenas se o servidor da web estiver protegido com uma sessão, estabelecida com a autenticação do usuário (login). Sem uma sessão, um usuário não confiável poderia apenas fazer solicitações ao servidor da Web, usando o client_id, e seria o mesmo como se o usuário tivesse o token de acesso. Adicionar uma sessão significa que apenas um usuário autenticado pode acessar os recursos protegidos. O client_id é apenas a "identidade" do webapp JS, não a autenticação do referido webapp.

Isso também significa que você pode encerrar a sessão antes que o token OAuth expire. Não existe uma maneira padrão de invalidar um token de acesso. Mas se a sua sessão expirar, o token de acesso será inútil, pois ninguém o conhece, exceto o servidor da web. Se um usuário não confiável obtiver acesso à sua chave de sessão, ele poderá acessar os recursos protegidos apenas enquanto a sessão for válida.

Se não houver servidor da web, você precisará usar a concessão implícita. Mas isso significa que o token de acesso é exposto à Internet. Se um usuário não confiável obtiver acesso a ele, ele poderá usá-lo até que ele expire. Isso significa que eles terão acesso a ele por mais tempo do que com uma concessão do Código de autorização. Portanto, considere fazer com que o token expire mais cedo e evite dar acesso a recursos mais sensíveis.

* EDIT: Mais recentemente, as pessoas recomendam que você evite usar a concessão implícita, mesmo em aplicativos Web sem servidor. Em vez disso, você pode usar a concessão do Código de Autorização configurada com um segredo vazio, juntamente com o PKCE. A concessão do código de autenticação evita armazenar o token de acesso no histórico do navegador e o PKCE evita expô-lo se alguém seqüestrar o URL de redirecionamento para roubar o código de autenticação. Nesse caso, você precisaria do servidor para evitar o retorno de um token de atualização, pois seu cliente provavelmente não pode armazená-lo com segurança. E deve emitir um token de acesso com as mesmas limitações mencionadas acima.

JW.
fonte
21

Tudo se resume a: Se um usuário estiver executando um aplicativo Web baseado em navegador ou "público", (JavaScript) sem componente do servidor, o usuário confia implicitamente no aplicativo (e no navegador em que é executado, potencialmente com outro navegador) aplicativos baseados em ...).

Não há servidor remoto de terceiros, apenas o servidor de recursos. Não há benefício para um código de autorização, porque não há outro agente além do navegador agindo em nome do usuário. Não há benefício para as credenciais do cliente pelo mesmo motivo. ( Qualquer cliente pode tentar usar esse fluxo.)

As implicações de segurança, no entanto, são significativas. Em http://tools.ietf.org/html/rfc6749#section-10.3 :

Ao usar o tipo de concessão implícita, o token de acesso é transmitido no fragmento URI, o que pode expô-lo a partes não autorizadas.

Em http://tools.ietf.org/html/rfc6749#section-10.16 :

Um proprietário de recurso pode delegar voluntariamente o acesso a um recurso, concedendo um token de acesso ao cliente mal-intencionado de um invasor. Isso pode ser devido a phishing ou algum outro pretexto ...

Vai
fonte
o que você quer dizer com aplicativo Web "público" e (JavaScript) sem nenhum componente do lado do servidor? Como pode haver um aplicativo da web sem servidor?
Zammy Página
2
@ZammyPage, isso seria chamado de SPA (Single Page App). A totalidade da aplicação é disponibilizada a partir de um recurso estático. O Javascript no aplicativo acessa dinamicamente todos os recursos necessários, em qualquer servidor de recursos que ele puder acessar. Não há servidor que gere o conteúdo do cliente: o javascript no cliente modifica o DOM conforme necessário para representar os recursos que ele acessou.
Elroy Flynn
13

Não sei se entendi corretamente a resposta e o comentário de Dan. Parece-me que a resposta afirmou que alguns fatos estão corretos, mas indica exatamente o que o OP pediu. Se bem entendi, a principal vantagem do fluxo implícito de concessão é que um cliente como o aplicativo JS (por exemplo, extensão do Chrome) não precisa expor o segredo do cliente.

Dan Taflin disse:

... no fluxo do código de autorização, o proprietário do recurso nunca precisa ver o token de acesso, enquanto nos clientes javascript isso é inevitável. No entanto, o segredo do cliente ainda pode ser mantido de clientes javascript usando o fluxo de código de autorização.

Talvez eu tenha entendido mal você, mas o cliente (neste caso, o aplicativo JS) deve passar a credencial do cliente (chave e segredo do cliente) para o servidor de recursos no fluxo do código de autorização, certo? O segredo do cliente não pode ser "mantido de JS".

tzuchien.chiu
fonte
6
Sei que essa é uma pergunta antiga, mas é uma resposta melhor do que a aceita. A razão pela qual a concessão implícita existe é que um cliente javascript não pode manter um segredo e, portanto, não pode ser autenticado. Portanto, o servidor de autorização deve confiar apenas no registro da uri de redirecionamento e no agente do usuário para segurança. Você transmite tokens de autorização apenas para o agente do usuário e apenas em um URL de redirecionamento específico, teoricamente impedindo a interceptação (porque um usuário mal-intencionado que não possui o domínio do URL de redirecionamento não pode executar o código no agente do usuário nesse URL).
gregates 18/03/16
De fato, a resposta aceita me confundiu. Me fez pensar que eu não entendi o que é o client_secret! Esta resposta e o comentário acima estão no local.
Sarsaparilla
9

Embora o Implicit Grant tenha sido projetado para oferecer suporte a aplicativos que não poderiam proteger um segredo do cliente, incluindo aplicativos JavaScript do lado do cliente, alguns provedores estão implementando uma alternativa usando o Código de Autorização sem um Segredo do Cliente. O OAuth 2.0 IETF RFC-6749 foi publicado em 2012 e as recomendações atuais são de algumas discussões recentes a partir de 2017.

A discussão de 2017 na lista de discussão IETF OAuth está disponível nestes implementadores:

Leia mais aqui:

O implícito foi anteriormente recomendado para clientes sem segredo, mas foi substituído pelo uso da concessão do Código de Autorização sem segredo.

...

Anteriormente, era recomendado que aplicativos baseados em navegador usassem o fluxo "Implícito", que retorna um token de acesso imediatamente e não possui uma etapa de troca de token. Desde que a especificação foi originalmente escrita, a melhor prática do setor mudou para recomendar que o fluxo do código de autorização seja usado sem o segredo do cliente. Isso fornece mais oportunidades para criar um fluxo seguro, como o uso do parâmetro state. Referências: Redhat , Deutsche Telekom , Smart Health IT .

A mudança para o código de autenticação sem o segredo do cliente da concessão implícita também é mencionada para aplicativos móveis aqui:

Grokify
fonte
Eu acho que você quer ter cuidado com esta recomendação. Isso foi recomendado nas orientações para aplicativos nativos, em vez de spas. Infelizmente, não há boas orientações sobre os SPAs, como documentado em muitas discussões on-line, fóruns e até na lista de discussão oauth-wg.
Tom
A recomendação para migrar para o código de autenticação sem segredo da concessão implícita é uma recomendação para SPAs e aplicativos móveis, mas meu trecho acima é específico para SPAs. O artigo mencionado usa texto semelhante para SPAs e aplicativos móveis, mas com o idioma "aplicativos baseados em navegador" "aplicativos móveis e nativos" no texto respectivo. As referências para Redhat, DT e Smart Health IT também são específicas para SPAs e não estão incluídas na nota para aplicativos móveis. Adicionei um link direto para os SPAs na resposta para facilitar a localização. Por favor, poste alguns links para as discussões que você mencionou.
Grokify
Uma discussão bastante recente (2018) sobre oauth-wg pode ser encontrada aqui ietf.org/mail-archive/web/oauth/current/msg18020.html . O RFC 8252 é para aplicativos nativos, pois o título sugere "OAuth 2.0 para aplicativos nativos". As referências a Redhat, DT, inteligente Saúde de TI são respostas a uma discussão lista de discussão, não um RFC, projecto de trabalho, etc ...
Tom
3

além das outras respostas, também é importante perceber que o perfil implícito permite um fluxo apenas do canal frontal, em oposição ao fluxo do código de autorização que requer uma chamada de volta ao servidor de autorização; isso se torna evidente no OpenID Connect, que é um protocolo SSO construído sobre o Auth 2.0, em que o fluxo implícito se assemelha à ligação SAML POST bastante popular e o fluxo do código de autorização se assemelha à ligação SAML Artifact menos amplamente implantada

Hans Z.
fonte
3

No fluxo implícito, se o navegador do usuário estiver corrompido (extensão / vírus incorreto), a corrupção obterá acesso aos recursos do usuário e poderá fazer as coisas ruins.

No fluxo de autenticação, a corrupção não pode porque não conhece o segredo do cliente.

Ritmo
fonte
2

https://tools.ietf.org/html/rfc6749#page-8

Implícito

A concessão implícita é um fluxo de código de autorização simplificado otimizado para clientes implementados em um navegador usando uma linguagem de script como JavaScript. No fluxo implícito, em vez de emitir ao cliente um código de autorização, o cliente recebe um token de acesso diretamente (como resultado da autorização do proprietário do recurso). O tipo de concessão está implícito, pois nenhuma credencial intermediária (como um código de autorização) é emitida (e posteriormente usada para obter um token de acesso).

Ao emitir um token de acesso durante o fluxo de concessão implícito, o
servidor de autorização não autentica o cliente. Em alguns
casos, a identidade do cliente pode ser verificada por meio do URI de redirecionamento
usado para entregar o token de acesso ao cliente. O token de acesso pode ser exposto ao proprietário do recurso ou a outros aplicativos com acesso ao agente do usuário do proprietário do recurso.

As concessões implícitas melhoram a capacidade de resposta e a eficiência de alguns
clientes (como um cliente implementado como um aplicativo no navegador),
pois reduzem o número de viagens de ida e volta necessárias para obter um
token de acesso.

Rzv Razvan
fonte
1

Acho que Will Cain respondeu isso quando disse: "Não há benefício para as credenciais do cliente pelo mesmo motivo. (Qualquer cliente pode tentar usar esse fluxo.)" Considere também que o redirect_uri para o fluxo implícito talvez seja "localhost" - sem retorno de chamada é feito do servidor de autorização para o fluxo implícito. Como não há como confiar previamente no cliente, o usuário precisaria aprovar a liberação das declarações do usuário.

Mike Schwartz
fonte
1

A concessão implícita permite obter tokens do ponto de extremidade de autorização com a GET. Isso significa que o servidor de autorização não precisa suportar o CORS.

Se isso não for uma preocupação e se não houver outros problemas relacionados ao servidor de autorização que não sejam flexíveis (por exemplo, os tokens de atualização não são opcionais, por algum motivo), o fluxo do código de autorização será o preferido, mesmo para clientes públicos, de acordo com as tendências recentes do setor e, pelo menos, para esta instância (atual) de um rascunho oficial .

Historicamente, havia outros motivos para implementar o fluxo implícito, mas parece que eles atualmente são superados pelas vantagens de segurança oferecidas pela concessão do código de autorização, incluindo:

  • opção para entregar e usar os tokens em um canal posterior para clientes confidenciais
  • não expondo tokens no histórico do navegador para clientes públicos
  • interromper um fluxo não autorizado antes da emissão de tokens - com PKCE , para "todos os tipos de clientes OAuth"
ko la
fonte
0

Acabei de encontrar um artigo sobre o OAuth 2.0. O autor afirma que a razão por trás do fluxo implícito é que os aplicativos JS eram muito restritos nas solicitações:

se você se perguntar por que o tipo implícito foi incluído no OAuth 2.0, a explicação é simples: mesma política de origem. Naquela época, os aplicativos de front-end não tinham permissão para enviar solicitações a hosts diferentes para obter o token de acesso usando o código. Hoje, temos o CORS (compartilhamento de recursos de origem cruzada).

https://medium.com/securing/what-is-going-on-with-oauth-2-0-and-why-you-should-not-use-it-for-authentication-5f47597b2611

Lu55
fonte