Bu örnek bize symfony ile password grant type kullanan bir OAuth2 API clientın nasıl yaratılacağını gösterecek ve daha önceden yazdığım OAuth2 API server ile ilişkilidir. Authentication password grant type ile yapılacak. Anlaşılması için adımları tek tek gideceğim. API @Security("has_role('xxxxx')") annotation ile controllerleri control ettiği için role_hierarchy kullanılıyor, bu nedenle password grant type en uygun ve basit seçenektir. Daha fazla bilgi için, yazının en altındaki referans linklerini de ziyaret edebilirsiniz.


Önemli


Aşağıdaki örnekte, access token'i elde etmek için kullandığım isteğin URI kısmında client_id ve client_secret bilgilerini sadece göstermek amacıyla açıkça teşhir ettim. Gerçek hayattaki uygulamalarınızda bunu yapmamalısınız. Onun yerine, her ikisini de base64_encode fonksiyonu ile kodlayıp, isteğin kafasına Authorization olarak ekleyin.


$clientId = 'i-am-client-id';
$clientSecret = 'i-am-client-secret';

$base64 = base64_encode($clientId.':'.$clientSecret);

$header = 'Basic '.$base64;

Sonuç olarak isteğinizde Authorization: Basic aS1hbS1jbGllbnQtaWQ6aS1hbS1jbGllbnQtc2VjcmV0 şeklinde kullanmanız gerekir. Bununla birlikte, URI kısmından username, password ve grant_type girdilerinide kaldırıp, application/x-www-form-urlencoded ile kodlanmak üzere, istek parametresi olarak kullanmanız gerekir. Final isteğiniz aşağıdaki gibi olmalı.


curl -X POST
-H 'Authorization: Basic aS1hbS1jbGllbnQtaWQ6aS1hbS1jbGllbnQtc2VjcmV0'
-H 'content-type: application/x-www-form-urlencoded'
-d 'grant_type=password&username=inanzzz&password=123123'
http://oauth-server.dev/app_dev.php/oauth/v2/token

Gerçekler



Composer.json


Composer ile "guzzlehttp/guzzle": "6.1.1" paketini yükleyin.


Parameters.yml


Aşağıdaki URI içinde geçen gizli bilgiler API administrator tarafından verilir.


# oauth-client/app/config/parameters.yml
parameters:
oauth_api_access_token_cache_namespace: OAUTH2_ACCESS_TOKEN
oauth_api_base_url: http://oauth-server.dev/app_dev.php
oauth_api_uri_version: /1
oauth_api_token_uri: /oauth/v2/token?client_id=1_fqnumqc8gvkss8soo44g4g0sw0s0okkk8og84k8ggckwsk4gc&client_secret=1m5d8yl0wk00wogsskoooo4k4o0wgw8k00cw8k00s4g8w8gkw0&grant_type=password&username=inanzzz&password=123123

Controllers.yml


# oauth-client/src/Application/ClientBundle/Resources/config/controllers.yml
services:
application_client.controller.team:
class: Application\ClientBundle\Controller\TeamController
arguments:
- %oauth_api_access_token_cache_namespace%
- %oauth_api_base_url%
- %oauth_api_uri_version%
- %oauth_api_token_uri%

TeamController.php


Bu örnek her istek için yeni bir access_token yaratır ki buda sistemin yavaş çalışmasına neden olur. Sorunu çözmek için access_token'i veya refresh_token'i cache de tutun ve sadece süresi bitince yeniden yaratın. Ayrıca, aşağıdaki kodları mümkün olduğunca service, model, factory, helper gibi classlara bölün.


namespace Application\ClientBundle\Controller;

use Exception;
use GuzzleHttp\Client;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

/**
* @Route("team", service="application_client.controller.team")
*/
class TeamController extends Controller
{
private $oauthApiAccessTokenCacheNamespace;
private $oauthApiBaseUrl;
private $oauthApiUriVersion;
private $oauthApiTokenUri;

public function __construct(
$oauthApiAccessTokenCacheNamespace,
$oauthApiBaseUrl,
$oauthApiUriVersion,
$oauthApiTokenUri
) {
$this->oauthApiAccessTokenCacheNamespace = $oauthApiAccessTokenCacheNamespace;
$this->oauthApiBaseUrl = $oauthApiBaseUrl;
$this->oauthApiUriVersion = $oauthApiUriVersion;
$this->oauthApiTokenUri = $oauthApiTokenUri;
}

/**
* @param string $name
*
* @Method({"GET"})
* @Route("/{name}")
*
* @return Response
*/
public function getTeamAction($name)
{
$accessToken = $this->getAccessToken();
$response= $this->call(
'GET',
$this->oauthApiUriVersion.'/server/team/'.$name,
$accessToken
);

return new Response($response->getBody().' with ACCESS TOKEN: '.$accessToken);
}

/**
* @param Request $request
*
* @Method({"POST"})
* @Route("")
*
* @return Response
*/
public function createTeamAction(Request $request)
{
$accessToken = $this->getAccessToken();
$response= $this->call(
'POST',
$this->oauthApiUriVersion.'/server/team',
$accessToken,
$request->getContent()
);

return new Response($response->getBody().' with ACCESS TOKEN: '.$accessToken);
}

/**
* @param Request $request
*
* @Method({"POST"})
* @Route("/club")
*
* @return Response
*/
public function createClubAction(Request $request)
{
$accessToken = $this->getAccessToken();
$response= $this->call(
'POST',
$this->oauthApiUriVersion.'/server/club',
$accessToken,
$request->getContent()
);

return new Response($response->getBody().' with ACCESS TOKEN: '.$accessToken);
}

private function getAccessToken()
{
$response = $this->call('GET', $this->oauthApiTokenUri);
$responseParts = json_decode($response->getBody(), true);

return $responseParts['access_token'];
}

private function call($method, $uri, $auth = null, $postData = null)
{
$client = new Client();

try {
return $client->request(
$method,
$this->oauthApiBaseUrl.$uri,
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer '.$auth
],
'body' => $postData
]
);
} catch (Exception $e) {
$message = $e->getCode() == 403 ? 'Missing role.' : $e->getMessage();

throw new AccessDeniedHttpException($message);
}

}
}

Server side methodları


# oauth-server/src/Application/ServerBundle/Controller/ServerController.php
/**
* @param string $name
*
* @Method({"GET"})
* @Route("/team/{name}")
*
* @return Response
*/
public function getTeamAction($name)
{
return new Response(sprintf('GET your team [%s] from Server', $name));
}

/**
* @param Request $request
*
* @Security("has_role('ROLE_ADMIN')")
* @Method({"POST"})
* @Route("/team")
*
* @return Response
*/
public function createTeamAction(Request $request)
{
$postData = json_decode($request->getContent(), true);

return new Response(sprintf('POST your team [%s] to Server', $postData['name']));
}

/**
* @param Request $request
*
* @Security("has_role('ROLE_SUPER_ADMIN')")
* @Method({"POST"})
* @Route("/club")
*
* @return Response
*/
public function createClubAction(Request $request)
{
$postData = json_decode($request->getContent(), true);

return new Response(sprintf('POST your club [%s] to Server', $postData['name']));
}

User rolları


API sahibi bizim user'imizi bu şekilde yaratmış. Her ne kadar yukarıda bir method olsa da, maalesef bize ROLE_SUPER_USER rolünü vermemiş.


MacBook-Pro:oauth-server inanzzz$ php app/console create:oauth:user --username=inanzzz --password=123123 --email=myemail@mydomain.com --role=ROLE_USER --role=ROLE_ADMIN
OAuth user has been created...
Username: inanzzz
Password: 123123
Roles: ["ROLE_USER","ROLE_ADMIN"]

Testler


# Request
GET http://oauth-client.dev/app_dev.php/team/inanzzz

# Response
GET your team [inanzzz] from Server with ACCESS TOKEN: YjQ0ZjVhMDE4MmRhMDIyYWQyMzhhODM4M2YzMGRmMzc0ODI2ZWU4NWFiMmJhZGUyOTQ0OTA3Y2MyNDhkMzYyMw

# Request
POST http://oauth-client.dev/app_dev.php/team
{
"name": "inanzzz"
}

# Response
POST your team [inanzzz] to Server with ACCESS TOKEN: ZTllODdhZTRlY2VmYzdhYmU4ZmI5MjUxMDQ1MjI0YjMzZjAxN2E3YzQxZmUwNjljMDMyZjg1OTZhODUwMGI0ZA

Bu örneğin çalışmama nedeni, yukarıda gördüğümüz gibi bize ROLE_SUPER_ADMIN rolünün verilmemesidir.


# Request
POST http://oauth-client.dev/app_dev.php/team/club
{
"name": "inanzzz"
}

# Response
403 Forbidden - AccessDeniedHttpException
Missing role.

Referanslar


Daha fazla bilgi için, aşağıdaki linkleri kontrol edebilirsiniz.