OAuth 2.0: fluxos de obtenção de access token

OAuth 2.0[1] é um protocolo de autorização de padrão aberto que permite a terceiros (aplicações) acessarem dados de um usuário sem a obrigatoriedade de informar suas credenciais. Apps usam esse método para obter acesso à conta de um determinado usuário através de um client ID ou client secret (chaves de autenticação do OAuth).

Para saber mais, visite o site http://oauth.net/2/.

Tipos de clientes

No OAuth, há dois tipos de clientes:

  • Cliente confidencial: clientes que conseguem garantir que nenhum usuário mal intencionado irá obter um client secret ou client ID para tentar se passar por uma aplicação válida.

  • Cliente não confidencial: clientes que não conseguem garantir que um usuário mal intencionado irá obter seu client secret ou client ID para tentar se passar por uma aplicação válida. Nesses casos, é informada uma URL de callback para garantir que as informações só retornem à aplicação verdadeira. Alternativamente, pode-se reduzir o tempo de vida útil do client ID com a utilização de um refresh token.

Formas de se obter um access token

Há diferentes fluxos OAuth 2.0, que demandam formas distintas de obtenção de um token de acesso.

Há formas que requerem o envio de extraInfo. Valores enviados como extraInfo são exibidos no campo Extra Fields do Overview de um token, que pode ser acessado ao clicar sobre o nome de um token na página Access Tokens.

Authorization Code

1. Gerando o authorization code:

Primeiramente, é necessário ter uma app criada. Com ela, temos acesso ao client ID, que será o primeiro item passado para o endpoint <URL do gateway>/oauth/grant-code via POST.

O header deve conter a seguinte informação:

Content-Type: application/json

No corpo, devemos enviar os seguintes itens:

{
  "client_id": "f9212173-e705-373b-a698-61923e378359",
  "extraInfo": {},
  "redirect_uri": "string",
  "state": "string"
}
O client ID a ser passado deve ser o mesmo da app criada.

Feito isso, espera-se uma resposta contendo um authorization code, como no exemplo abaixo.

{
  "redirect_uri": "string?state=string&code=8748d39f-1d4f-311f-92c6-4b279db1b317"
}

2. Informando o authorization code para gerar o access token:

Em seguida, deve-se realizar uma nova requisição do tipo POST para o endpoint <URL do gateway>/oauth/access-token.

O header deve conter as seguintes informações:

Authorization: Basic client_id:client_secret
Esse client_id:client_secret deve ser uma string convertida em Base64, usando os dados da app criada.

Exemplo de header com o client_id e o client_secret convertidos para Base64:

Authorization: Basic ZjkyMTIxNzMtZTcwNS0zNzNiLWE2OTgtNjE5MjNlMzc4MzU5OjAyYWI1Mjg4LTkyZGItM2FiMy05OWZkLWZhYzRhZjg1N2Q4MQ==

No corpo, devemos passar o authorization code gerado pelo endpoint anterior e o grant type em formato x-www-form-urlencoded, como neste exemplo:

grant_type=authorization_code&code=8748d39f-1d4f-311f-92c6-4b279db1b317

Por fim, o access token será gerado e haverá um retorno como este:

{
  "access_token": "57f10f0e-3d2e-311f-a797-4011f66e1cbf",
  "refresh_token": "ca81cb16-43e4-3e96-aaea-4861e7791dc7",
  "token_type": "access_token",
  "expires_in": 3600
}

Refresh Token

O refresh token será utilizado para atualizar um access token que tenha sido expirado. Para atualizar o token, siga os passos abaixo.

Faça uma requisição do tipo POST para o endpoint <URL do gateway>/oauth/access-token.

O header deve conter as seguintes informações:

Authorization: Basic client_id:client_secret
Esse client_id:client_secret deve ser uma string convertida em Base64, usando os dados da app criada.

Exemplo de header com o client_id e o client_secret convertidos para Base64:

Authorization: Basic ZjkyMTIxNzMtZTcwNS0zNzNiLWE2OTgtNjE5MjNlMzc4MzU5OjAyYWI1Mjg4LTkyZGItM2FiMy05OWZkLWZhYzRhZjg1N2Q4MQ==

No corpo, devemos passar o refresh_token recebido do endpoint anterior (que gerou o access token) e o grant type em formato x-www-form-urlencoded, como neste exemplo:

grant_type=refresh_token&refresh_token=ca81cb16-43e4-3e96-aaea-4861e7791dc7

Por fim, o access token será gerado novamente e um código como o seguinte será retornado:

{
  "access_token": "ca81cb16-43e4-3e96-aaea-4861e7791dc7",
  "refresh_token": "677b881a-d0b6-3b29-b9a8-f0cdb50ce035",
  "token_type": "access_token",
  "expires_in": 3600
}

Implicit

O fluxo Implicit é usado para obter tokens de acesso de forma otimizada para clientes públicos. Ele pode operar por uma IRO de redirecionamento particular, acompanhado do access token. Esses clientes são normalmente implementados em um navegador usando uma linguagem de script, como JavaScript.

Como para o fluxo OAuth 2.0 Authorization Code, é necessário que a app esteja criada para que tenhamos acesso ao client ID. Depois disso, faça uma requisição POST para o endpoint <URL do gateway>/oauth/access-token.

O cabeçalho deve conter a seguinte informação:

Content-Type: application/json

No corpo, devemos enviar os seguintes itens:

{
  "grant_type": "implicit",
  "redirect_uri": "<URL>",
  "client_id": "<client ID>"
}
O client ID a ser passado deve ser o mesmo da app criada.
Note também que a app deve conter um extra field chamado redirect_uri, com o valor de URL válida, que deverá ser informada na chamada de geração do token (por exemplo: http://supermock.demo.sensedia.com/). Veja mais informações sobre como criar e configurar apps, adicionando extra fields, aqui.

Acabado o processo, espera-se uma resposta com a URI e o access token, conforme o exemplo abaixo.

{
  "redirect_uri": "www.url.com?access_token=57f10f0e-3d2e-311f-a797-4011f66e1cbf",
  "expires_in": 3600
}

Client Credentials

Assim como o fluxo Implicit, o Client Credentials NÃO gera o refresh_token. Portanto, não é possível atualizar um access token depois de sua expiração.

Quando este fluxo for utilizado, ao criar um novo access token, deve-se inserir o nome da app e seu client ID no campo Extra Info do access token, inserindo também todos os valores de extra fields que estiverem cadastrados na app. Acesse aqui para ver mais informações sobre como criar e configurar apps, adicionando extra fields.

É necessário que uma app esteja criada para que possamos ter acesso ao client ID e ao client secret.

Em seguida, é necessário fazer uma requisição POST para o endpoint <URL do gateway>/oauth/access-token.

O header deve conter as seguintes informações:

Authorization: Basic client_id:client_secret
Esse client_id:client_secret deve ser uma string convertida em Base64, usando os dados da app criada.

Exemplo de header com o client_id e o client_secret convertidos para Base64:

Authorization: Basic ZjkyMTIxNzMtZTcwNS0zNzNiLWE2OTgtNjE5MjNlMzc4MzU5OjAyYWI1Mjg4LTkyZGItM2FiMy05OWZkLWZhYzRhZjg1N2Q4MQ==

No corpo, devemos passar o grant_type no formato x-www-form-urlencoded:

grant_type=client_credentials

Por fim, o seu access token será gerado e deverá ser retornado como no exemplo abaixo:

{
  "access_token": "6c164a82-84a6-3bc4-8122-f777121a4f62",
  "token_type": "access_token",
  "expires_in": 3600
}

É possível também criar novos extra fields na criação do access token. Para isso, é necessário adicionar ao cabeçalho o seguinte header:

Content-Type: application/json

No corpo, devemos passar o grant_type e os extra fields, como neste exemplo:

{
  "grant_type": "client_credentials",
  "extraInfo": {"value": "32423", "value2": "874yhgt3"}
}

Password

Como no fluxo Authorization Code, é necessário que a app esteja criada para que possamos ter acesso ao client ID e ao client secret.

Então, faça uma requisição POST para o endpoint <URL do gateway>/oauth/access-token.

O header deve conter as seguintes informações:

Authorization: Basic client_id:client_secret
Esse client_id:client_secret deve ser uma string convertida em Base64, usando os dados da app criada.

Exemplo de header com o client_id e o client_secret convertidos para Base64:

Authorization: Basic ZjkyMTIxNzMtZTcwNS0zNzNiLWE2OTgtNjE5MjNlMzc4MzU5OjAyYWI1Mjg4LTkyZGItM2FiMy05OWZkLWZhYzRhZjg1N2Q4MQ==

Além do grant_type, o corpo precisa conter mais duas informações que utilizam o userDirectory. Essas informações são o login e a senha do usuário, que podem ser de um LDAP ou de um REST, e devem estar no formato x-www-form-urlencoded:

grant_type=password&username=<login de usuário>&password=<senha>

Se o usuário e senha forem válidos na LDAP ou no REST, o retorno do access token deve ser semelhante ao modelo a seguir:

{
  "access_token": "6c164a82-84a6-3bc4-8122-f777121a4f62",
  "token_type": "refresh_token",
  "expires_in": 3600
}
Para que as funcionalidades acima estejam presentes na sua app, é necessário configurar uma API Identity.
No caso de LDAP, o usuário informado deve estar no formato User-Principal-Name (e.g., test@da.sa)
A propriedade oauth.grantTypes.resourceOwnerPassword.userDirectory não é mais necessária.

JWT

"JSON Web Token (JWT) é um padrão aberto (RFC 7519) que define uma forma compacta e auto-suficiente para a transmissão segura de informações entre as partes na forma de um objeto JSON. Essa informação pode ser verificada e confiável porque é assinada digitalmente. JWTs podem ser assinados usando um segredo (com o algoritmo HMAC) ou um par de chaves pública/privada usando RSA." (https://jwt.io/)

No fluxo JWT, também é necessário que a app esteja criada para que tenhamos acesso ao client ID e ao client secret.

Então, faça uma requisição POST para o endpoint <URL do gateway>/oauth/access-token.

O cabeçalho deve conter as seguintes informações:

Authorization: Basic client_id:client_secret
Esse client_id:client_secret deve ser uma string convertida em Base64, usando os dados da app criada.

Exemplo de header com o client_id e o client_secret convertidos para Base64:

Authorization: Basic ZjkyMTIxNzMtZTcwNS0zNzNiLWE2OTgtNjE5MjNlMzc4MzU5OjAyYWI1Mjg4LTkyZGItM2FiMy05OWZkLWZhYzRhZjg1N2Q4MQ==

No corpo, devemos passar o code gerado pelo endpoint de grant-code e o grant type em formato x-www-form-urlencoded, como neste exemplo:

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&code=8748d39f-1d4f-311f-92c6-4b279db1b317

Por fim, o seu access token será gerado novamente e deverá ser retornado conforme o exemplo abaixo.

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJsb2NhbGhvc3QiLCJpc3MiOiIxNzIuMTguMC4xIiwic3ViIjoiOWI1Zjc3MWUtNzgyZC0zNTEwLWI2YmEtMzZlOWM2NWJmZDVkIiwiZXhwIjozNjAwLCJpYXQiOjE1Mjg5MTg2MzcsIkFwcDogIjoiUmljYXJkb0FwcCIsIkNvZGU6ICI6IjRlNWIyMTEzLTJkYzYtM2RlNi1iN2ZkLWNkOTYxOTMxZWQyOSIsImxvZ2luIjoidXNlci5sb2dpbiJ9.bhvFpiZ6em9tUgpHxGQGuH7cmvMy4I7STJDRBUybuPM",
  "token_type": "access_token",
  "expires_in": 3600
  }

Com o código gerado, será necessário adicionar o interceptor de JWT no fluxo da API. Ele será responsável por verificar se o token é valido. Veja mais sobre o interceptor aqui.

Thanks for your feedback!
EDIT
How useful was this article to you?