Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

apply psr7 for client credential token/resource routine #774

Open
wants to merge 1 commit into
base: psr-7
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/OAuth2/ClientAssertionType/HttpBasic.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,18 @@ public function getClientCredentials(RequestInterface $request, &$errors = null)
);
}

if ($authorizationHeader = $request->getServerParams()["HTTP_AUTHORIZATION"]) {
$exploded = explode(':', base64_decode(substr($authorizationHeader, 6)));
if (count($exploded) != 2) {
return null;
}

$result = [];
list($result['client_id'], $result['client_secret']) = $exploded;
return $result;

}

if ($this->config['allow_credentials_in_request_body']) {
$body = json_decode((string) $request->getBody(), true);
// Using POST for HttpBasic authorization is not recommended, but is supported by specification
Expand Down
38 changes: 33 additions & 5 deletions src/OAuth2/Controller/ResourceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

namespace OAuth2\Controller;

use OAuth2\ResponseException;
use OAuth2\TokenType\TokenTypeInterface;
use OAuth2\Storage\AccessTokenInterface;
use OAuth2\ScopeInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;
use OAuth2\Scope;

/**
Expand Down Expand Up @@ -37,7 +37,7 @@ public function __construct(TokenTypeInterface $tokenType, AccessTokenInterface
$this->scopeUtil = $scopeUtil;
}

public function verifyResourceRequest(RequestInterface $request, ResponseInterface $response, $scope = null)
public function verifyResourceRequest(RequestInterface $request, ResponseInterface $response, StreamInterface $stream, $scope = null)
{
try {
$token = $this->getAccessTokenData($request, $response);
Expand Down Expand Up @@ -70,15 +70,19 @@ public function verifyResourceRequest(RequestInterface $request, ResponseInterfa
}
}

$stream->write($e->getMessage());

return $response
->withStatusCode($e->getStatusCode() ?: 401)
->withHeader('WWW-Authenticate' => $authHeader);
->withStatus($e->getStatusCode() ?: 401)
->withHeader('WWW-Authenticate', $authHeader)
->withHeader('Content-Type', 'application/json')
->withBody($stream);
}

// allow retrieval of the token
$this->token = $token;

return (bool) $token;
return $response;
}

public function getAccessTokenData(RequestInterface $request, ResponseInterface $response)
Expand Down Expand Up @@ -110,3 +114,27 @@ public function getToken()
return $this->token;
}
}

class ResponseException extends \LogicException {

public function __construct($short_code, $description){
$this->shortCode = $short_code;
$this->description = $description;
$this->statusCode = 401;
parent::__construct(json_encode(['code'=>$short_code, 'error_description' => $description]), $this->statusCode);

}

public function getDescription(){
return $this->description;
}

public function getShortCode(){
return $this->shortCode;
}

public function getStatusCode(){
return $this->statusCode;
}

}
3 changes: 2 additions & 1 deletion src/OAuth2/Controller/ResourceControllerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;

/**
* This controller is called when a "resource" is requested.
Expand All @@ -20,7 +21,7 @@
*/
interface ResourceControllerInterface
{
public function verifyResourceRequest(RequestInterface $request, ResponseInterface $response, $scope = null);
public function verifyResourceRequest(RequestInterface $request, ResponseInterface $response, StreamInterface $stream, $scope = null);

public function getAccessTokenData(RequestInterface $request, ResponseInterface $response);
}
37 changes: 27 additions & 10 deletions src/OAuth2/Controller/TokenController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use OAuth2\Storage\ClientInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Zend\Diactoros\Stream;
use Psr\Http\Message\StreamInterface;

/**
* @see OAuth2\Controller\TokenControllerInterface
Expand Down Expand Up @@ -45,29 +45,33 @@ public function __construct(AccessTokenInterface $accessToken, ClientInterface $
$this->scopeUtil = $scopeUtil;
}

public function handleTokenRequest(RequestInterface $request, ResponseInterface $response)
public function handleTokenRequest(RequestInterface $request, ResponseInterface $response, StreamInterface $stream)
{
$errors = null;
$body = new Stream('php://temp', 'rw');
if($stream->getContents()!="") {
throw new \LogicException("Stream has to be empty");
}
if ($token = $this->grantAccessToken($request, $errors)) {
// @see http://tools.ietf.org/html/rfc6749#section-5.1
// server MUST disable caching in headers when tokens are involved
$body->write(json_encode($token));
$stream->write(json_encode($token));
return $response
->withStatus(200)
->withHeader('Cache-Control', 'no-store')
->withHeader('Content-Type', 'application/json')
->withHeader('Pragma', 'no-cache')
->withBody($body);
->withBody($stream);
}

$body->write(json_encode(array_filter(array(
'error' => $error['code'],
'error_description' => $error['description'],
'error_uri' => $error['uri'],
$stream->write(json_encode(array_filter(array(
'error' => $errors['code'],
'error_description' => $errors['description'],
'error_uri' => $errors['uri'] ?? null,
))));
return $response
->withStatus($errors['code'] == 'invalid_method' ? 405 : 400)
->withBody($body);
->withHeader('Content-Type', 'application/json')
->withBody($stream);
}

/**
Expand Down Expand Up @@ -99,6 +103,7 @@ public function grantAccessToken(RequestInterface $request, &$errors = null)
return false;
}


$body = json_decode((string) $request->getBody(), true);

/**
Expand Down Expand Up @@ -128,6 +133,7 @@ public function grantAccessToken(RequestInterface $request, &$errors = null)

$grantType = $this->grantTypes[$grantTypeIdentifier];


/**
* Retrieve the client information from the request
* ClientAssertionTypes allow for grant types which also assert the client data
Expand All @@ -149,8 +155,17 @@ public function grantAccessToken(RequestInterface $request, &$errors = null)
*/
$grantType->validateRequest($request, $response);


if ($grantType instanceof ClientAssertionTypeInterface) {
$clientId = $grantType->getClientId();
if(empty($clientId)) {
$errors = array(
'code' => 'invalid_client',
'description' => 'client ID doesn\'t exists',
);

return false;
}
} else {
// validate the Client ID (if applicable)
if (!is_null($storedClientId = $grantType->getClientId()) && $storedClientId != $clientId) {
Expand All @@ -163,6 +178,8 @@ public function grantAccessToken(RequestInterface $request, &$errors = null)
}
}



/**
* Validate the client can use the requested grant type
*/
Expand Down
4 changes: 3 additions & 1 deletion src/OAuth2/Controller/TokenControllerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface;


/**
* This controller is called when a token is being requested.
Expand All @@ -26,7 +28,7 @@ interface TokenControllerInterface
* OAuth2\ResponseInterface - An instance of OAuth2\ResponseInterface to contain the response data
*
*/
public function handleTokenRequest(RequestInterface $request, ResponseInterface $response);
public function handleTokenRequest(RequestInterface $request, ResponseInterface $response, StreamInterface $stream);

public function grantAccessToken(RequestInterface $request, &$errors = null);
}
14 changes: 5 additions & 9 deletions src/OAuth2/Server.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@
use OAuth2\Storage\JwtAccessTokenInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use Zend\Diactoros\Response;
use Zend\Diactoros\ServerRequestFactory;
use Psr\Http\Message\StreamInterface;

/**
* Server class for OAuth2
Expand Down Expand Up @@ -254,9 +253,9 @@ public function handleUserInfoRequest(RequestInterface $request, ResponseInterfa
*
* @ingroup oauth2_section_4
*/
public function handleTokenRequest(RequestInterface $request, ResponseInterface $response = null)
public function handleTokenRequest(RequestInterface $request, ResponseInterface $response, StreamInterface $stream)
{
return $this->getTokenController()->handleTokenRequest($request, $response ?: new Response());
return $this->getTokenController()->handleTokenRequest($request, $response, $stream);
}

public function grantAccessToken(RequestInterface $request, &$errors = null)
Expand Down Expand Up @@ -336,12 +335,9 @@ public function validateAuthorizeRequest(RequestInterface $request, &$errors = n
return $this->getAuthorizeController()->validateAuthorizeRequest($request, $errors);
}

public function verifyResourceRequest(RequestInterface $request, ResponseInterface $response = null, $scope = null)
public function verifyResourceRequest(RequestInterface $request, ResponseInterface $response, StreamInterface $stream, $scope = null) : ResponseInterface
{
$this->response = is_null($response) ? new Response() : $response;
$value = $this->getResourceController()->verifyResourceRequest($request, $this->response, $scope);

return $value;
return $this->getResourceController()->verifyResourceRequest($request, $response, $stream, $scope);
}

public function getAccessTokenData(RequestInterface $request, ResponseInterface $response = null)
Expand Down
17 changes: 9 additions & 8 deletions src/OAuth2/TokenType/Bearer.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace OAuth2\TokenType;

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;

/**
Expand Down Expand Up @@ -30,12 +31,12 @@ public function getTokenType()
*
* @see https://github.com/bshaffer/oauth2-server-php/issues/349#issuecomment-37993588
*/
public function requestHasToken(RequestInterface $request)
public function requestHasToken(ServerRequestInterface $request)
{
$headers = $request->headers('AUTHORIZATION');
$header = $request->getHeader('AUTHORIZATION');

// check the header, then the querystring, then the request body
return !empty($headers) || (bool) ($request->request($this->config['token_param_name'])) || (bool) ($request->query($this->config['token_param_name']));
return !empty($header) || (bool) ($request->getAttribute($this->config['token_param_name'])) || (bool) ($request->getQueryParams()[$this->config['token_param_name']]);
}

/**
Expand All @@ -60,17 +61,17 @@ public function requestHasToken(RequestInterface $request)
* @see http://code.google.com/p/android/issues/detail?id=6684
*
*/
public function getAccessTokenParameter(RequestInterface $request, ResponseInterface $response)
public function getAccessTokenParameter(ServerRequestInterface $request, ResponseInterface $response)
{
$headers = $request->headers('AUTHORIZATION');
$headers = $request->getHeader('AUTHORIZATION');

/**
* Ensure more than one method is not used for including an
* access token
*
* @see http://tools.ietf.org/html/rfc6750#section-3.1
*/
$methodsUsed = !empty($headers) + (bool) ($request->query($this->config['token_param_name'])) + (bool) ($request->request($this->config['token_param_name']));
$methodsUsed = !empty($headers) + (bool) ($request->getQueryParams()[$this->config['token_param_name']]) + (bool) ($request->getAttribute($this->config['token_param_name']));
if ($methodsUsed > 1) {
$response->setError(400, 'invalid_request', 'Only one method may be used to authenticate at a time (Auth header, GET or POST)');

Expand Down Expand Up @@ -100,7 +101,7 @@ public function getAccessTokenParameter(RequestInterface $request, ResponseInter
return $matches[1];
}

if ($request->request($this->config['token_param_name'])) {
if ($request->getAttribute($this->config['token_param_name'])) {
// // POST: Get the token from POST data
if (!in_array(strtolower($request->server('REQUEST_METHOD')), array('post', 'put'))) {
$response->setError(400, 'invalid_request', 'When putting the token in the body, the method must be POST or PUT', '#section-2.2');
Expand All @@ -125,6 +126,6 @@ public function getAccessTokenParameter(RequestInterface $request, ResponseInter
}

// GET method
return $request->query($this->config['token_param_name']);
return $request->getQueryParams()[$this->config['token_param_name']];
}
}
4 changes: 2 additions & 2 deletions src/OAuth2/TokenType/TokenTypeInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace OAuth2\TokenType;

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Message\ResponseInterface;

interface TokenTypeInterface
Expand All @@ -17,5 +17,5 @@ public function getTokenType();
/**
* Retrieves the token string from the request object
*/
public function getAccessTokenParameter(RequestInterface $request, ResponseInterface $response);
public function getAccessTokenParameter(ServerRequestInterface $request, ResponseInterface $response);
}