In this Article we will continue our journey with api development of the use of Oauth2 as Authorization Protocol.
Our Previous Api development articles are below:
Understand OAuth2:
The OAuth 2.0 authorization framework enables a third-party application to obtain limited access to an HTTP service, the name of a resource owner.
here are a few links that I found useful:
- knpuniversity screencast
- Oauth.net
- rfc6749 Proposed Standard of OAuth2
OAuth2 with Symfony::
Symfony offers FOSOAuthServerBundle, which can be used for server-side implementation of OAuth2.
instructions can be found here.
Authorize and token routes “@FOSOAuthServerBundle/Resources/config/routing/authorize.xml” & “@FOSOAuthServerBundle/Resources/config/routing/token.xml”, defined in the routing.yml will be used for access token generation.
An OAuth Server has 3 end points. Each endpoint performs a distinct function in the OAuth process.
Authorize Endpoint – The user is redirected here by the client to authorize the request.
the Token Endpoint – The client makes a request to this endpoint to obtain an Access Token. This is the same as token URL defined in routing.yml.
the Source Endpoint(s) – The client provides a valid access token for the requests of a resource(s) on this endpoint, such as and/or users.json.
Grant in OAuth2:
OAuth2 provides several different Grant types. These Grant Types allow you to expose multiple ways for a customer to generate an Access Token.
1. The Authorization Code:
The authorization code grant type is used when the client wants to request access to protected resources on behalf of another user (i.e. a 3rd party). Read more about the authorization code
Example Request
Authorization codes are retrieved using the Authorize Controller. The client sends the user to the OAuth server Authorize URL.
Step 1: First of all, redirect the user to the Authorize URL:
1 |
/authorize?response_type=code&client_id=ClientId&redirect_uri=https://redirecturi.com/processToken |
A successful request will automatically pass the client the authorization code in the URL (the supplied redirect_uri URL) as
1 |
https://redirecturi.com/processToken?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz |
Step 2: after a token can be requested using the authorization code token url,
1 |
$ curl -u ClientId:ClientSecret https://api.mysite.com/token -d 'grant_type=authorization_code&code=xyz" |
A successful token request will return a standard access token in JSON format:
1 |
{"access_token":"asa9329bc56c777d4df84e9c0d3b6535","expires_in":3600,"token_type":"bearer"} |
2. Password (Resource owner Grant)
Resource Owner of the username and password provided in the request, and a token is awarded after a successful authentication.
1 |
$ curl -u clientId:clientSecret "https://www.demo.com/token" -d 'grant_type=password&username=demouser&password=pass' |
Successful Authentication will result in an access token,
1 |
{"access_token":"as804f13b9asv1312cc346b7d25177f463edd","expires_in":3600,"token_type":"bearer","scope":null} |
3. The client Credentials Grant
The client uses the credentials to retrieve an access token directly to access to resources in the context of the client’s control
1 |
$ curl -u clientId:clientSecret "https://www.demo.com/token" -d 'grant_type=client_credentials' {"access_token":"6f05ad622a3d32a5a81aee5d73a5826adb8cbf63","expires_in":3600,"token_type":"bearer","scope":null} |
Note: Access token generated by the client credentials grant can be used only for the reading of the source. since such an access token is not authenticated by a user.
4. Refresh Token Grant
Access token(s) has a limited life span. so, we must refresh token expires the refresh token access tokens.
1 |
$ curl -u clientId:clientSecret "https://www.demo.com/token" -d 'grant_type=refresh_token&refresh_token=c54adab1d99d10bnf8sbe3b77ec32a2e402ef7e3' |
Result on a successful request:
1 |
{"access_token":"0e9d02499fe06762ecaafb9cfbb506676631dcfd","expires_in":3600,"token_type":"bearer","scope":null} |
the Request to a resource endpoint:
If you have any questions Protected resource endpoint in secure api firewall (fos_oauth: true) without an access token. then it will result in,
1 2 3 4 |
{ "error": "error_access_denied", "error_description": "OAuth2 authentication required" } |
to request a secure resource, add Authorization header in request
1 |
$ curl -X -H "Authorization: Bearer 974A0ACDF2F5CADDB57A53B23BABDEB57889ASS4A0ACDF2F5C893B57553B23BABDEB5" "http://www.demo.com/resource.json" |
return data from symfony controller:
In the corresponding controller for the resource.json data back
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?php use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\HttpFoundation\Response; // ... class DemoController extends FOSRestController { public function getDemosAction() { $user = $this->get('security.context)->getToken()->getUser(); // Do something with the fully authenticated user. // $json = []; $response = new Response(json_encode($json)); $response->head->set('Content-Type', 'application/json'); return $response; } } |
Tips:
- Return suitable status code along with the response.
- Instead of relying on HTTP status code as integer in your code, use constants from Response class.
- If you are using json response, then use JsonResponse Class instead of Response Class.
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<?php use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\JsonResponse; // ... class DemoController extends FOSRestController { // ... public function getDemosAction() { $user = $this->get('security.context)->getToken()->getUser(); // Do something with the fully authenticated user. // $json = []; return new JsonResponse($json, Response::HTTP_OK); } } |
More:
Now, you have the platform for the development of Api. so go on and develop.
Since the Api is platform-independent, so it can be used by any suitable Api Client.