mirror of
https://github.com/elyby/oauth2-server.git
synced 2025-01-03 18:51:53 +05:30
Numerous bug fixes
This commit is contained in:
parent
9b97778618
commit
0115c41eea
@ -1,10 +1,10 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||||
use League\OAuth2\Server\Grant\PasswordGrant;
|
|
||||||
use League\OAuth2\Server\Server;
|
use League\OAuth2\Server\Server;
|
||||||
|
|
||||||
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
|
||||||
|
use OAuth2ServerExamples\Repositories\AuthCodeRepository;
|
||||||
use OAuth2ServerExamples\Repositories\ClientRepository;
|
use OAuth2ServerExamples\Repositories\ClientRepository;
|
||||||
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
|
use OAuth2ServerExamples\Repositories\RefreshTokenRepository;
|
||||||
use OAuth2ServerExamples\Repositories\ScopeRepository;
|
use OAuth2ServerExamples\Repositories\ScopeRepository;
|
||||||
@ -16,32 +16,54 @@ use Slim\Http\Response;
|
|||||||
|
|
||||||
include(__DIR__ . '/../vendor/autoload.php');
|
include(__DIR__ . '/../vendor/autoload.php');
|
||||||
|
|
||||||
// Setup the authorization server
|
|
||||||
$server = new Server('file://' . __DIR__ . '/../private.key');
|
|
||||||
|
|
||||||
// Init our repositories
|
|
||||||
$userRepository = new UserRepository();
|
|
||||||
$clientRepository = new ClientRepository();
|
|
||||||
$scopeRepository = new ScopeRepository();
|
|
||||||
$accessTokenRepository = new AccessTokenRepository();
|
|
||||||
$refreshTokenRepository = new RefreshTokenRepository();
|
|
||||||
|
|
||||||
// Enable the client credentials grant on the server
|
|
||||||
$passwordGrant = new PasswordGrant(
|
|
||||||
$userRepository,
|
|
||||||
$clientRepository,
|
|
||||||
$scopeRepository,
|
|
||||||
$accessTokenRepository,
|
|
||||||
$refreshTokenRepository
|
|
||||||
);
|
|
||||||
$server->enableGrantType($passwordGrant);
|
|
||||||
|
|
||||||
// App
|
// App
|
||||||
$app = new App([Server::class => $server]);
|
$app = new App([
|
||||||
|
Server::class => function () {
|
||||||
|
|
||||||
$app->any('/authorise', function (Request $request, Response $response) {
|
// Init our repositories
|
||||||
if (strtoupper($request->getMethod()) === 'GET') {
|
$clientRepository = new ClientRepository();
|
||||||
$response = $response->withHeader('Set-Cookie', $authCodeGrant->storeOriginalRequestParams)
|
$scopeRepository = new ScopeRepository();
|
||||||
|
$accessTokenRepository = new AccessTokenRepository();
|
||||||
|
$userRepository = new UserRepository();
|
||||||
|
$refreshTokenRepository = new RefreshTokenRepository();
|
||||||
|
$authCodeRepository = new AuthCodeRepository();
|
||||||
|
|
||||||
|
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
|
||||||
|
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
|
||||||
|
|
||||||
|
// Setup the authorization server
|
||||||
|
$server = new Server(
|
||||||
|
$clientRepository,
|
||||||
|
$accessTokenRepository,
|
||||||
|
$scopeRepository,
|
||||||
|
$privateKeyPath,
|
||||||
|
$publicKeyPath
|
||||||
|
);
|
||||||
|
|
||||||
|
// Enable the password grant on the server with a token TTL of 1 hour
|
||||||
|
$server->enableGrantType(
|
||||||
|
new \League\OAuth2\Server\Grant\AuthCodeGrant(
|
||||||
|
$authCodeRepository,
|
||||||
|
$refreshTokenRepository,
|
||||||
|
$userRepository,
|
||||||
|
new \DateInterval('PT10M')
|
||||||
|
),
|
||||||
|
new \DateInterval('PT1H')
|
||||||
|
);
|
||||||
|
|
||||||
|
return $server;
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
$app->any('/authorize', function (Request $request, Response $response) {
|
||||||
|
/** @var Server $server */
|
||||||
|
$server = $this->get(Server::class);
|
||||||
|
try {
|
||||||
|
return $server->respondToRequest($request, $response);
|
||||||
|
} catch (OAuthServerException $e) {
|
||||||
|
return $e->generateHttpResponse($response);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
return $response->withStatus(500)->write($e->getMessage());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -49,9 +71,9 @@ $app->post('/access_token', function (Request $request, Response $response) {
|
|||||||
/** @var Server $server */
|
/** @var Server $server */
|
||||||
$server = $this->get(Server::class);
|
$server = $this->get(Server::class);
|
||||||
try {
|
try {
|
||||||
return $server->respondToRequest($request);
|
return $server->respondToRequest($request, $response);
|
||||||
} catch (OAuthServerException $e) {
|
} catch (OAuthServerException $e) {
|
||||||
return $e->generateHttpResponse();
|
return $e->generateHttpResponse($response);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return $response->withStatus(500)->write($e->getMessage());
|
return $response->withStatus(500)->write($e->getMessage());
|
||||||
}
|
}
|
||||||
|
42
examples/src/Repositories/AuthCodeRepository.php
Normal file
42
examples/src/Repositories/AuthCodeRepository.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace OAuth2ServerExamples\Repositories;
|
||||||
|
|
||||||
|
use League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface;
|
||||||
|
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
|
||||||
|
|
||||||
|
class AuthCodeRepository implements AuthCodeRepositoryInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persists a new auth code to permanent storage
|
||||||
|
*
|
||||||
|
* @param \League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface $authCodeEntity
|
||||||
|
*/
|
||||||
|
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity)
|
||||||
|
{
|
||||||
|
// TODO: Implement persistNewAuthCode() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revoke an auth code
|
||||||
|
*
|
||||||
|
* @param string $codeId
|
||||||
|
*/
|
||||||
|
public function revokeAuthCode($codeId)
|
||||||
|
{
|
||||||
|
// TODO: Implement revokeAuthCode() method.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the auth code has been revoked
|
||||||
|
*
|
||||||
|
* @param string $codeId
|
||||||
|
*
|
||||||
|
* @return bool Return true if this code has been revoked
|
||||||
|
*/
|
||||||
|
public function isAuthCodeRevoked($codeId)
|
||||||
|
{
|
||||||
|
// TODO: Implement isAuthCodeRevoked() method.
|
||||||
|
}
|
||||||
|
}
|
@ -3,10 +3,10 @@
|
|||||||
namespace League\OAuth2\Server\Grant;
|
namespace League\OAuth2\Server\Grant;
|
||||||
|
|
||||||
use DateInterval;
|
use DateInterval;
|
||||||
use League\OAuth2\Server\Entities\ClientEntity;
|
|
||||||
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
|
use League\OAuth2\Server\Entities\Interfaces\UserEntityInterface;
|
||||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||||
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
|
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
|
||||||
|
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||||
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
|
use League\OAuth2\Server\Repositories\UserRepositoryInterface;
|
||||||
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
|
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
|
||||||
use League\OAuth2\Server\Utils\KeyCrypt;
|
use League\OAuth2\Server\Utils\KeyCrypt;
|
||||||
@ -41,8 +41,14 @@ class AuthCodeGrant extends AbstractGrant
|
|||||||
*/
|
*/
|
||||||
private $pathToAuthorizeTemplate;
|
private $pathToAuthorizeTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface
|
||||||
|
*/
|
||||||
|
private $refreshTokenRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface $authCodeRepository
|
* @param \League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface $authCodeRepository
|
||||||
|
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository
|
||||||
* @param \League\OAuth2\Server\Repositories\UserRepositoryInterface $userRepository
|
* @param \League\OAuth2\Server\Repositories\UserRepositoryInterface $userRepository
|
||||||
* @param \DateInterval $authCodeTTL
|
* @param \DateInterval $authCodeTTL
|
||||||
* @param string|null $pathToLoginTemplate
|
* @param string|null $pathToLoginTemplate
|
||||||
@ -50,12 +56,14 @@ class AuthCodeGrant extends AbstractGrant
|
|||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
AuthCodeRepositoryInterface $authCodeRepository,
|
AuthCodeRepositoryInterface $authCodeRepository,
|
||||||
|
RefreshTokenRepositoryInterface $refreshTokenRepository,
|
||||||
UserRepositoryInterface $userRepository,
|
UserRepositoryInterface $userRepository,
|
||||||
\DateInterval $authCodeTTL,
|
\DateInterval $authCodeTTL,
|
||||||
$pathToLoginTemplate = null,
|
$pathToLoginTemplate = null,
|
||||||
$pathToAuthorizeTemplate = null
|
$pathToAuthorizeTemplate = null
|
||||||
) {
|
) {
|
||||||
$this->authCodeRepository = $authCodeRepository;
|
$this->authCodeRepository = $authCodeRepository;
|
||||||
|
$this->refreshTokenRepository = $refreshTokenRepository;
|
||||||
$this->userRepository = $userRepository;
|
$this->userRepository = $userRepository;
|
||||||
$this->authCodeTTL = $authCodeTTL;
|
$this->authCodeTTL = $authCodeTTL;
|
||||||
$this->pathToLoginTemplate = $pathToLoginTemplate;
|
$this->pathToLoginTemplate = $pathToLoginTemplate;
|
||||||
@ -242,6 +250,7 @@ class AuthCodeGrant extends AbstractGrant
|
|||||||
* @param \DateInterval $accessTokenTTL
|
* @param \DateInterval $accessTokenTTL
|
||||||
*
|
*
|
||||||
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
|
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface
|
||||||
|
* @throws \League\OAuth2\Server\Exception\OAuthServerException
|
||||||
*/
|
*/
|
||||||
protected function respondToAccessTokenRequest(
|
protected function respondToAccessTokenRequest(
|
||||||
ServerRequestInterface $request,
|
ServerRequestInterface $request,
|
||||||
@ -250,37 +259,44 @@ class AuthCodeGrant extends AbstractGrant
|
|||||||
) {
|
) {
|
||||||
// Validate request
|
// Validate request
|
||||||
$client = $this->validateClient($request);
|
$client = $this->validateClient($request);
|
||||||
$scopes = $this->validateScopes($request, $client);
|
$encryptedAuthCode = $this->getRequestParameter('code', $request, null);
|
||||||
$encryptedAuthcode = $this->getRequestParameter('code', $request, null);
|
|
||||||
|
|
||||||
if ($encryptedAuthcode === null) {
|
if ($encryptedAuthCode === null) {
|
||||||
throw OAuthServerException::invalidRequest('code');
|
throw OAuthServerException::invalidRequest('code');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the authorization code
|
// Validate the authorization code
|
||||||
try {
|
try {
|
||||||
$authCodePayload = json_decode(KeyCrypt::decrypt($encryptedAuthcode, $this->pathToPrivateKey));
|
$authCodePayload = json_decode(KeyCrypt::decrypt($encryptedAuthCode, $this->pathToPrivateKey));
|
||||||
if (time() > $authCodePayload->expire_time) {
|
if (time() > $authCodePayload->expire_time) {
|
||||||
throw OAuthServerException::invalidRequest('code', 'Authorization code has expired');
|
throw OAuthServerException::invalidRequest('code', 'Authorization code has expired');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->authCodeRepository->isAuthCodeRevoked($authCodePayload->auth_code_id) === true) {
|
||||||
|
throw OAuthServerException::invalidRequest('code', 'Authorization code has been revoked');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($authCodePayload->client_id !== $client->getIdentifier()) {
|
||||||
|
throw OAuthServerException::invalidRequest('code', 'Authorization code was not issued to this client');
|
||||||
|
}
|
||||||
} catch (\LogicException $e) {
|
} catch (\LogicException $e) {
|
||||||
throw OAuthServerException::invalidRequest('code');
|
throw OAuthServerException::invalidRequest('code');
|
||||||
}
|
}
|
||||||
|
|
||||||
$client = new ClientEntity();
|
// Issue and persist access + refresh tokens
|
||||||
$client->setIdentifier($authCodePayload->client_id);
|
|
||||||
|
|
||||||
// Issue and persist access token
|
|
||||||
$accessToken = $this->issueAccessToken(
|
$accessToken = $this->issueAccessToken(
|
||||||
$accessTokenTTL,
|
$accessTokenTTL,
|
||||||
$client,
|
$client,
|
||||||
$authCodePayload->user_id,
|
$authCodePayload->user_id,
|
||||||
$authCodePayload->scopes
|
$authCodePayload->scopes
|
||||||
);
|
);
|
||||||
|
$refreshToken = $this->issueRefreshToken($accessToken);
|
||||||
$this->accessTokenRepository->persistNewAccessToken($accessToken);
|
$this->accessTokenRepository->persistNewAccessToken($accessToken);
|
||||||
|
$this->refreshTokenRepository->persistNewRefreshToken($refreshToken);
|
||||||
|
|
||||||
// Inject access token into response type
|
// Inject tokens into response type
|
||||||
$responseType->setAccessToken($accessToken);
|
$responseType->setAccessToken($accessToken);
|
||||||
|
$responseType->setRefreshToken($refreshToken);
|
||||||
|
|
||||||
return $responseType;
|
return $responseType;
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,9 @@ interface AuthCodeRepositoryInterface extends RepositoryInterface
|
|||||||
/**
|
/**
|
||||||
* Persists a new auth code to permanent storage
|
* Persists a new auth code to permanent storage
|
||||||
*
|
*
|
||||||
* @param \League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface $authCodeEntityInterface
|
* @param \League\OAuth2\Server\Entities\Interfaces\AuthCodeEntityInterface $authCodeEntity
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntityInterface);
|
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Revoke an auth code
|
* Revoke an auth code
|
||||||
|
Loading…
Reference in New Issue
Block a user