Back-End

19 jan, 2015

Autenticação OAuth2 em API com PHP usando Apigility – Parte 01

Publicidade

Neste artigo, explico como construir um sistema de autenticação OAuth2 em PHP utilizando Apigility. Em meu artigo anterior, já apresentei o Apigility, um novo projeto de código aberto para criar e manter APIs para projetos PHP.

Apigility oferece os seguintes sistemas de autenticação para APIs: HTTP Basic, HTTP Digest e OAuth2.

OAuth2 é um protocolo bem conhecido mundialmente, utilizado, por exemplo, por Facebook, GitHub, Twitter etc. para autenticar suas APIs. Antes de começar com as funcionalidades Oauth2 do Apigility, eu gostaria de introduzir brevemente os principais conceitos desse protocolo.

Na especificação do OAuth2 (RFC 6749) temos as seguintes definições:

  • Resource Owner: o usuário.
  • Resource Server: a API.
  • Authorization Server: quase sempre o mesmo que o servidor da API.
  • Client: as aplicativos de terceiros.

No Apigility, o Resource Server e o Authorization Server são entregues a partir do mesmo servidor da API. O protocolo OAuth2 pode ser considerado um framework para autorização. Um trecho do RFC 6749 que podemos ler:

O framework de autorização OAuth 2.0 permite que um aplicativo de terceiros possa obter acesso limitado a um serviço HTTP, tanto em nome do proprietário de um recurso ao orquestrar uma interação para a aprovação entre o proprietário do recurso e o serviço HTTP, ou ao permitir que o aplicativo de terceiros possa obter acesso em seu próprio nome.

Os casos de uso abrangidos pelo quadro OAuth2 são:

  • Aplicativos Web-servidor
  • Aplicativos baseados no navegador
  • Aplicativos móveis
  • Nome de usuário e senha de acesso
  • Acesso ao aplicativo

Em todos esses casos de uso, o objetivo do protocolo OAuth2 é a troca de uma cadeia de tokens entre o Cliente e Server Resource. Esse token é usado para autenticar todas as chamadas a API usando Authorization no cabeçalho do HTTP. Abaixo é relatado um exemplo do token Bearer (RFC 7650), o tipo de token mais utilizado no OAuth2:

Authorization: Bearer RsT5OjbzRn430zqMLgV3Ia

Considerações de segurança do OAuth2

O protocolo OAuth2 não garante a confidencialidade e a integridade das comunicações. Isso significa que você deve proteger as comunicações HTTP utilizando uma camada adicional. Uma solução possível é a utilização de TLS/SSL (https) para criptografar o canal de comunicação a partir do cliente até o servidor.

OAuth1 suportava um mecanismo de autenticação baseado no algoritmo HMAC para garantir a confidencialidade e a integridade, OAuth2 não (há um rascunho de proposta para apoiar token MAC). Essa é uma das principais preocupações em relação à segurança do OAuth2, e a maioria dos desenvolvedores reclama sobre isso (por exemplo, você pode ler este texto no blog de Eran Hammer, ex-líder e autor das especificações do OAuth).

Dito isso, sempre use HTTPS para OAuth2!

Configuração do OAuth2 no Apigility

Antes de saltar para os diferentes casos de uso para autenticação OAuth2, precisamos configurar o Apigility para usar o OAuth2. Se você não tem o Apigility instalado no seu computador, pode ir ao site apigility.org e seguir as instruções lá relatadas.

Para usar OAuth2 com Apigility, você precisa ir para a página do painel de administração da interface do usuário e clicar no botão OAuth2; você verá um formulário como este:

pic1

A implementação OAuth2 no Apigility usa a biblioteca oauth2-server-php de Brent Shaffer. O Apigility utiliza um banco de dados PDO para armazenar todas as informações relacionadas ao protocolo OAuth2. Você pode criar seu banco de dados usando o esquema relatado no arquivo /vendor/zfcampus/zf-oauth2/data/db_oauth2.sql em sua pasta de instalação do Apigility (zf-apigility-skeleton).

Para fins de teste, você pode usar o banco de dados SQLite de exemplo que nós colocamos no módulo zf-oauth2, /vendor/zfcampus/zf-oauth2/data/dbtest.sqlite. Nesse caso, é necessário especificar o caminho absoluto do banco de dados dbtest.sqlite no campo PDO DSN, usando a sintaxe sqlite:/ /dbtest.sqlite. Além disso, você precisa escolher a URI para a API de autenticação na rota do domínio OAuth2, por exemplo /oauth.

No banco de dados de exemplo, criamos um cliente com client_id testclient e client_secret testpass; e um usuário testuser com senha testpass. Vamos usar esses dados de exemplo nos casos de uso seguintes.

Todos os dados sensíveis, tais como client_secret (na tabela oauth_clients) e senha (na tabela oauth_users), são criptografadas usando o algoritmo Apigility bcrypt. Se você deseja gerar o valor de hash bcrypt de uma senha de texto em PHP, você pode usar o componente \Zend\Crypt\Bcrypt do Zend Framework 2.

A fim de facilitar o uso do banco de dados PDO para OAuth2, incluímos um script PHP simples que pode ser executado a partir da linha de comando para gerar valores de hash bcrypt. Essa ferramenta de linha de comando está disponível em /vendor/zfcampus/zf-oauth2/bin. Por exemplo, você pode executar o seguinte comando para gerar o hash da string “teste” com um valor de custo de 10 (o custo é um parâmetro do algoritmo bcrypt que indica o tempo computacional para consumir):

php bcrypt.php test 10

Você verá uma saída assim:

$ 2a $ 10 $ 8gHQy / sn0vB8H5wbAbhUi.tbUfpf6aE7PBllKHeKaCYTqEyd7vjo6

A saída do algoritmo bcrypt é uma string de 60 bytes.

Aplicativos Web-servidor

Os cenários de aplicativos Web-servidor são usados para autenticar uma aplicação Web com um serviço de terceiros (por exemplo, imagine que você construiu uma aplicação web que precisa consumir a API do Facebook). Você pode autenticar seu aplicativo usando o servidor de terceiros com 3 passos conforme o diagrama abaixo:

pic2

A aplicação web envia um pedido (incluindo o client_id e o redirect_uri) para o serviço de terceiros pedindo um código de autorização (1).

O servidor de terceiros exibe uma página Alow/Deny para solicitar a autorização para o acesso. Se o usuário clicar em Permitir, o servidor envia o código de autorização para a aplicação web utilizando o redirect_uri (2). A aplicação web pode agora realizar uma solicitação de token passando o client_id, o redirect_uri e o client_secret, para provar que está autorizado a realizar esta solicitação (3). O servidor de terceiros envia o token como resposta se o pedido for válido (4).

Usando Apigility podemos solicitar um código de acesso usando os 3 passos seguintes:

1) Solicite o código de autorização

Usando um navegador, você pode solicitar a aprovação da autorização desta página:

http:///oauth/authorize?response_type=code
&client_id=testclient&redirect_uri=/oauth/receivecode&state=xyz

Você verá uma página web como a seguir:

pic3

Você pode personalizar a página usando o arquivo de view /vendor/zfcampus/zf-oauth2/view/zf/auth/authorize.phtml.

2) Aprove a autorização de acesso

Se você aprovar a autorização de acesso clicando no botão Yes, o Apigility redirecionará você para a URI especificada no redirect_uri, passando o código de autorização na string query (código). Em nosso exemplo, você será redirecionado para oauth/receive conforme abaixo:

pic4

3) Requisite um token Bearer

Agora que temos o código de autorização, podemos requisitar um token de acesso com um POST para /oauth passando o código de autorização, o client_id, o client_secret e o redirect_uri conforme reportado no seguinte comando HTTPie:

http -f POST http://<apigility URL>/oauth grant_type=authorization_code
redirect_uri=/oauth/receivecode client_id=testclient client_secret=testpass
code=e906c671ac845c60c7a6b9abee113f641524fc12

O servidor OAuth2 responderá com o token usando uma estrutura JSON semelhante a esta:

{
    "access_token": "907c762e069589c2cd2a229cdae7b8778caa9f07",
    "expires_in": 3600,
    "refresh_token": "43018382188f462f6b0e5784dd44c36f476ccce6",
    "scope": null,
    "token_type": "Bearer"
}

Você tem 30 segundos para solicitar o token de acesso a partir do momento que obtém o código de autorização.

Finalmente, podemos acessar a API usando o token Bearer no pedido do cabeçalho HTTP. Por exemplo, nós fornecemos um recurso de teste no módulo zf-oauth2, você pode acessá-lo usando o comando HTTPie a seguir:

http http:///oauth/resource
“Authorization:Bearer 907c762e069589c2cd2a229cdae7b8778caa9f07”

***

Na segunda e última parte, falarei sobre aplicativos baseados no navegador, aplicativos móveis, nome de usuário e senha de acesso e acesso ao aplicativo.

***

Artigo traduzido pela Redação iMasters com autorização do autor. Publicado originalmente em http://www.zimuel.it/oauth2-apigility/