Created
December 6, 2015 00:29
-
-
Save AlmogBaku/3164020daee67ec800dd to your computer and use it in GitHub Desktop.
Patched OAuth Server to allow `password` grant without secret
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Created by PhpStorm. | |
* User: AlmogBaku | |
* Date: 04/12/2015 | |
* Time: 3:13 PM | |
*/ | |
namespace Rimoto\ApiBundle\Security; | |
use OAuth2\OAuth2; | |
use OAuth2\OAuth2ServerException; | |
use Symfony\Component\HttpFoundation\Request; | |
use Symfony\Component\HttpFoundation\Response; | |
class PatchedOAuth2 extends OAuth2 | |
{ | |
/** | |
* Grant or deny a requested access token. | |
* | |
* This would be called from the "/token" endpoint as defined in the spec. | |
* Obviously, you can call your endpoint whatever you want. | |
* Draft specifies that the authorization parameters should be retrieved from POST, but you can override to whatever method you like. | |
* | |
* @param Request $request (optional) The request | |
* | |
* @return Response | |
* @throws OAuth2ServerException | |
* | |
* @see http://tools.ietf.org/html/draft-ietf-oauth-v2-20#section-4 | |
* @see http://tools.ietf.org/html/draft-ietf-oauth-v2-21#section-10.6 | |
* @see http://tools.ietf.org/html/draft-ietf-oauth-v2-21#section-4.1.3 | |
* | |
* @ingroup oauth2_section_4 | |
*/ | |
public function grantAccessToken(Request $request = null) | |
{ | |
$filters = array( | |
"grant_type" => array( | |
"filter" => FILTER_VALIDATE_REGEXP, | |
"options" => array("regexp" => self::GRANT_TYPE_REGEXP), | |
"flags" => FILTER_REQUIRE_SCALAR | |
), | |
"scope" => array("flags" => FILTER_REQUIRE_SCALAR), | |
"code" => array("flags" => FILTER_REQUIRE_SCALAR), | |
"redirect_uri" => array("filter" => FILTER_SANITIZE_URL), | |
"username" => array("flags" => FILTER_REQUIRE_SCALAR), | |
"password" => array("flags" => FILTER_REQUIRE_SCALAR), | |
"refresh_token" => array("flags" => FILTER_REQUIRE_SCALAR), | |
); | |
if ($request === null) { | |
$request = Request::createFromGlobals(); | |
} | |
// Input data by default can be either POST or GET | |
if ($request->getMethod() === 'POST') { | |
$inputData = $request->request->all(); | |
} else { | |
$inputData = $request->query->all(); | |
} | |
// Basic authorization header | |
$authHeaders = $this->getAuthorizationHeader($request); | |
// Filter input data | |
$input = filter_var_array($inputData, $filters); | |
// Grant Type must be specified. | |
if (!$input["grant_type"]) { | |
throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_REQUEST, 'Invalid grant_type parameter or parameter missing'); | |
} | |
// Authorize the client | |
$clientCredentials = $this->getClientCredentials($inputData, $authHeaders); | |
$client = $this->storage->getClient($clientCredentials[0]); | |
if (!$client) { | |
throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_CLIENT, 'The client credentials are invalid'); | |
} | |
if (($this->storage->checkClientCredentials($client, $clientCredentials[1]) === false) && ($input["grant_type"]!=self::GRANT_TYPE_USER_CREDENTIALS)) { | |
throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_CLIENT, 'The client credentials are invalid'); | |
} | |
if (!$this->storage->checkRestrictedGrantType($client, $input["grant_type"])) { | |
throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_UNAUTHORIZED_CLIENT, 'The grant type is unauthorized for this client_id'); | |
} | |
// Do the granting | |
switch ($input["grant_type"]) { | |
case self::GRANT_TYPE_AUTH_CODE: | |
// returns array('data' => data, 'scope' => scope) | |
$stored = $this->grantAccessTokenAuthCode($client, $input); | |
break; | |
case self::GRANT_TYPE_USER_CREDENTIALS: | |
// returns: true || array('scope' => scope) | |
$stored = $this->grantAccessTokenUserCredentials($client, $input); | |
break; | |
case self::GRANT_TYPE_CLIENT_CREDENTIALS: | |
// returns: true || array('scope' => scope) | |
$stored = $this->grantAccessTokenClientCredentials($client, $input, $clientCredentials); | |
break; | |
case self::GRANT_TYPE_REFRESH_TOKEN: | |
// returns array('data' => data, 'scope' => scope) | |
$stored = $this->grantAccessTokenRefreshToken($client, $input); | |
break; | |
default: | |
if (filter_var($input["grant_type"], FILTER_VALIDATE_URL)) { | |
// returns: true || array('scope' => scope) | |
$stored = $this->grantAccessTokenExtension($client, $inputData, $authHeaders); | |
} else { | |
throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_REQUEST, 'Invalid grant_type parameter or parameter missing'); | |
} | |
} | |
if (!is_array($stored)) { | |
$stored = array(); | |
} | |
// if no scope provided to check against $input['scope'] then application defaults are set | |
// if no data is provided than null is set | |
$stored += array('scope' => $this->getVariable(self::CONFIG_SUPPORTED_SCOPES, null), 'data' => null, | |
'access_token_lifetime' => $this->getVariable(self::CONFIG_ACCESS_LIFETIME), | |
'issue_refresh_token' => true, 'refresh_token_lifetime' => $this->getVariable(self::CONFIG_REFRESH_LIFETIME)); | |
$scope = $stored['scope']; | |
if ($input["scope"]) { | |
// Check scope, if provided | |
if (!isset($stored["scope"]) || !$this->checkScope($input["scope"], $stored["scope"])) { | |
throw new OAuth2ServerException(self::HTTP_BAD_REQUEST, self::ERROR_INVALID_SCOPE, 'An unsupported scope was requested.'); | |
} | |
$scope = $input["scope"]; | |
} | |
$token = $this->createAccessToken($client, $stored['data'], $scope, $stored['access_token_lifetime'], $stored['issue_refresh_token'], $stored['refresh_token_lifetime']); | |
return new Response(json_encode($token), 200, $this->getJsonHeaders()); | |
} | |
/** | |
* Returns HTTP headers for JSON. | |
* | |
* @see http://tools.ietf.org/html/draft-ietf-oauth-v2-20#section-5.1 | |
* @see http://tools.ietf.org/html/draft-ietf-oauth-v2-20#section-5.2 | |
* | |
* @return array | |
* | |
* @ingroup oauth2_section_5 | |
*/ | |
protected function getJsonHeaders() | |
{ | |
return array( | |
'Content-Type' => 'application/json', | |
'Cache-Control' => 'no-store', | |
'Pragma' => 'no-cache', | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
parameters: | |
fos_oauth_server.server.class: Rimoto\ApiBundle\Security\PatchedOAuth2 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Why rewrite getJsonHeaders ?