INTRODUÇÃO
Em aplicações cliente-servidor tradicionais, quando o cliente necessita acessar um recurso protegido no servidor é necessário que ele primeiro informe credencias para que possa ser autenticado. Em um cenário onde o acesso ao recurso é feito através de uma aplicação intermediária o usuário precisará informar suas credenciais para que esta aplicação possa obter o recurso no servidor de dados. Isto cria uma série de problemas e limitações:
-
A aplicação intermediária precisa armazenar as credenciais do usuário para uso futuro, tipicamente mantendo um identificador do usuário e a senha não criptografada o que aumenta os riscos em relação a possíveis falhas de segurança.
-
A aplicação intermediária precisará implementar autenticação com senha e isso acarreta em todo um conjunto de problemas relacionados à força das senhas utilizadas (e.g. estabelecer conexões seguras).
-
As aplicações intermediárias, ao possuírem as credenciais do usuário, ganham acesso irrestrito as informações deles no servidor final. Dessa forma o usuário não pode especificar limitações de acesso e tempo de validade para a aplicação intermediária.
-
Em um cenário onde múltiplas aplicações intermediárias acessem os recursos do usuário no servidor final o usuário não poderia revogar a permissão de acesso de apenas de uma dessas aplicações. Ele precisaria modificar suas credenciais de acesso no servidor final o que "bloquearia" o acesso de todas as aplicações intermediárias.
O protocolo OAuth 2 visa resolver estes problemas ao introduzir uma camada de autorização intermediária entre a aplicação cliente (i.e. a aplicação intermediária) e o servidor onde encontra-se os recurso, chamado de resource server. No protocolo OAuth o cliente requisita acesso a recursos controlados pelo resource owner (i.e. usuário final) a um servidor de autorização (authorization server) e recebe um conjunto de credenciais diferentes das que seriam realmente utilizadas pelo próprio resource owner. Esse conjunto de credencias 'artificiais' estão contidas em um token de acesso – uma string que denota um escopo específico, tempo de vida e outros atributos de acesso. O cliente pode então utilizar o token para acessar os recursos no resource server de acordo com as restrições que o próprio token contém.
Exemplo: Um usuário final (o resource owner) pode prover à uma aplicação web (o cliente) acesso a fotos protegidas de sua conta no Instagram mas não precisará informar seu nome de usuário e senha para esta aplicação web. Ao invés disso, o usuário irá autenticar-se diretamente em um servidor de autorização que por sua vez concederá o token de acesso (com as devidas permissões) a aplicação web. Com o token a aplicação poderá requisitar as fotos do usuário diretamente no resource server.
PAPÉIS (ROLES)
O protocolo OAuth 2 define 4 papéis:
-
Resource owner: Uma entidade (tipicamente um usuário final) que é o 'dono' de um recurso protegido.
-
Resource server: É o servidor que hospeda o recurso protegido e é capaz de interpretar tokens de acesso. O resultado desta interpretação é o que possibilitará o acesso ao recurso protegido.
-
Client: Uma aplicação que faz uma requisição a um recurso protegido em nome do resource owner e com sua autorização.
-
Authorization server: Um servidor que cria tokens de acesso para clientes após realizar a autenticação 'real' do resource owner. O servidor de autorização pode ser o mesmo que o servidor que hospeda o recurso. Além disso, um único servidor de autorização pode gerar tokens de acesso válidos em diversos resource servers.
FLUXO_DO_PROTOCOLO
A ilustração acima descreve a interação entre os 4 papéis e inclui os seguintes passos:
-
Authorization request: O cliente requisita autorização do resource owner. Este pedido pode ser feito diretamente ao resource owner ou, preferencialmente, indiretamente através de um servidor de autorização (não consta na ilustração).
-
Authorization grant: Uma credencial representando a autorização concedida pelo resource owner para a aplicação cliente. O tipo de autorização concedida dependerá do método utilizado pelo cliente para realizar a requisição e também pelo tipo de concessões que o servidor de autorização suporta.
-
O cliente requisita o token de acesso enviando o authorization grant para o servidor de autorização.
-
O token de acesso é fornecido ao cliente.
-
Requisição ao recurso: Neste ponto o cliente já possui o token de acesso e pode requisitar recursos protegidos do servidor de recursos.
-
O servidor de recursos valida o token de acesso e, se válido, retorna o recurso protegido ao cliente.
AUTHORIZATION GRANT
É uma credencial que representa a autorização concedida pelo resource owner ao cliente. A especificação OAuth 2 define 4 tipos de authorization grant:
-
Authorization Code: Obtida através de um servidor de autorização que funciona como um intermediário entre o cliente e o resource owner. O cliente redireciona o resource owner para o servidor de autorização -- através do user-agent utilizado pelo resource owner (e.g. o browser) -- que por sua vez redireciona o resource owner de volta para o cliente junto ao authorization code. O authorization code é utilizado pelo client para requisitar o token de acesso ao servidor de autorização dessa forma protegendo o token de ficar exposto pelo user-agent.
-
Implicit: É um fluxo de autorização simplificado otimizado para clientes implementados em um browser utilizando uma linguagem como JavaScript, por exemplo. Neste fluxo, o servidor ao invés de retornar ao cliente um authorization code retorna diretamente o token de acesso.
-
Resource Owner Password Credentials: O cliente utiliza as credenciais do resource owner (i.e. username e senha) para obter o token de acesso junto ao servidor de autorização. Este cenário só deve ser utilizado quando há grande confiança na aplicação cliente ou quando outros tipos de authorization grants não estão disponíveis. O cliente utiliza as credenciais do usuário final apenas uma vez, para obter o token. Após isso sempre utilizará o token para obter recursos protegidos e dessa forma não necessita armazenar as credenciais. O cliente pode solicitar um token de acesso usando apenas suas credenciais de cliente (ou outros meios de autenticação suportados) quando o cliente está solicitando acesso aos recursos protegidos sob seu controle ou os de outro proprietário de recursos que foram previamente organizados com o serviço de autorização.
-
Client Credentials: Tipicamente utilizado quando o próprio client é também o resource owner ou quando está requisitando recursos que possuem uma autorização pré definida no servidor de autorização.
REGISTRO DO CLIENTE
Antes de iniciar o protocolo o cliente deve estar registrado junto ao servidor de autorização (tipicamente feito através de um formulário web disponibilizado diretamente pelo servidor de autorização). O desenvolvedor da aplicação cliente deve:
- Especificar o tipo do cliente
- Prover as URIs de redirecionamento que a aplicação cliente pode tratar
- Incluir informações adicionais que o servidor de autorização possa requerer (e.g., nome da aplicação, website, descrição, logotipo e termos legais).
TIPOS DE CLIENTE
Os tipos de cliente são classificados de acordo com o nível de confidencialidade ao obter o token do servidor de autorização:
-
Confidencial: Clientes implementados em servidores seguros que restringem o acesso das credenciais.
-
Público: Clientes incapazes de manter a confidencialidade de suas credenciais (e.g. aplicações nativas ou browser-based)
APLICAÇÕES WEB
São considerados clientes confidenciais. Os resource owners acessam o cliente via uma interface HTML em algum user-agent (i.e. browser). As credenciais do cliente assim como qualquer token gerado pelo servidor de autorização são armazenadas pelo servidor web do cliente e dessa forma não podem ser facilmente interceptadas.
USER-AGENT BASED (SINGLE PAGE APPS)
Clientes deste tipo são considerados públicos. O código deste tipo de aplicação é requisitado uma única vez do servidor web e a partir daí é executado inteiramente pelo user-agent. Dessa forma, credenciais e tokens de acesso são facilmente vísiveis ao resource owner.
APLICAÇÕES NATIVAS
Clientes deste tipo são considerados públicos. A aplicação é instalada em um dispositivo utilizado pelo resource owner e dessa forma credenciais e tokens de acesso ficam acessíveis.
GRANT: AUTHORIZATION CODE
Este tipo de authorization grant é utilizada por clientes confidenciais como aplicações web tradicionais.
Passo 1: O cliente redireciona o resource owner para a tela de autorização de grant
Este é o link que o usuário (resource owner) utilizará para fazer o pedido de grant (authorization grant) para a aplicação cliente no servidor de autorização.
- http://servidor_autorizacao.com/v1/oauth/authorize: o endpoint de autorização no servidor de autorização
- client_id=CLIENT_ID: O identificador do cliente previamente cadastrado no servidor de autorização.
- redirect_uri=CALLBACK_URL: o endereço para o qual o user-agent deve ser redirecionado quando o authorization code é concedido.
- response_type=code: Indica que a aplicação cliente está requisitando um grant do tipo authorization code.
- scope=read: Especifica o nível de acesso que o cliente necessita dos recursos do resource owner.
Passo 2: Resource owner autoriza o cliente
Assim que o usuário clicar no link ele precisará fazer login no servidor de autorização. Em seguida será exibida a tela na qual ele pode autorizar a aplicação cliente. Tipicamente este tela apresenta que tipo de permissões serão concedidas ao cliente.
Passo 3: O cliente recebe o grant do tipo Authorization Code
O servidor de autorização redireciona o user-agent (normalmente o browser) para a URI indicada no parâmetro redirect_uri. Também será enviado o authorization code como um parâmetro query string code=AUTHORIZATION_CODE. Exemplo:
https://cliente.com/callback?code=AUTHORIZATION_CODE
Passo 4: O cliente requisita o token
Com o código de autorização o cliente pode requisitar o token de acesso junto ao servidor de autorização. Veja que é neste momento que o parâmetro client_secret (chave secreta do cliente, previamente registrada no servidor de autorização) é informado.
Passo 5: O cliente recebe o token
Caso a requisição do passo 4 seja aceita pelo servidor de autorização ele então retornará o token de acesso em uma resposta do tipo:
{
"access_token":"ACCESS_TOKEN",
"token_type":"bearer",
"expires_in":2592000,
"refresh_token":"REFRESH_TOKEN",
"scope":"read",
"uid":100101,
"info":{
"name":"Nome do Usuario",
"email":"[email protected]"
}
}
Neste momento o cliente já pode fazer requisições ao servidor de recursos (sempre informando o token obtido junto). Se o token possuir o escopo de permissões adequado e não estiver expirado então o servidor retornará o recurso requisitado. Exemplo de uma requisição utilizando o utilitário curl com o token previamente recebido (um HTTP POST com o header "Authorization:Bearer ACCESS_TOKEN")
curl -X POST -H "Authorization: Bearer ACCESS_TOKEN""https://servidor_de_recursos/v2/$OBJECT"
GRANT: CLIENT CREDENTIALS
Este tipo de grant é utilizado quando o próprio cliente também é o resource owner ou está requisitando recursos baseado em uma autorização previamente definida no servidor de autorização. Neste caso o cliente faz a requisição ao servidor de autorização e recebe diretamente o token de acesso. Exemplo de requisição: