11/01/2016 - SYMFONY
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.
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
refresh_token
içerir.access_token
"user" bilgilerini içerir bu nedenle, API tarafında "user" bilgilerine ulaşmak mümkün olur.access_token
ve refresh_token
almak için mevcut olan refresh_token
yeni istek ile gönderilir.access_token
içinde bulundurduğu için ideal seçenektir ve ayrıca Authorization Code grant type gibi authentication işleminden sonra redirect işlemi yapmaz.Composer ile "guzzlehttp/guzzle": "6.1.1"
paketini yükleyin.
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
# 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%
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);
}
}
}
# 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']));
}
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"]
# 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.
Daha fazla bilgi için, aşağıdaki linkleri kontrol edebilirsiniz.