-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add introspection implementation #925
Open
StevePorter92
wants to merge
31
commits into
thephpleague:master
Choose a base branch
from
StevePorter92:feature/add-introspection-implementation-code-review
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
9446f0e
Add introspection implementation
fetzi 1ad5514
Apply styleci fixes
fetzi 651ee9b
Apply styleci fixes
fetzi 225553f
Fix phpstan errors
fetzi 880b4bd
Apply styleci fixes
fetzi 487241b
Refactor introspection response to not use exceptions to control the …
eba79d7
refactor response to be more inline with other package reponses
fece711
Merge branch 'master' of github.com:steveporter92/oauth2-server into …
caf15b9
update code style
d143c46
update code style
f00b07e
fix type hints for tests
595cace
fix code style and unit tests and rename introspection params function
33eef79
add validate request method
e4b49c6
add test for extra params
baa74fb
code style fixes
8bf9c36
code style for test
4af0d2a
add more introspection tests
b00e6fa
add introspect example
4805243
remove blank linbe
5eeb624
add missing brackets to new class
b0e6eff
update phpdoc to reflect the function
7def7a8
add missing doc
99cb04a
fix return type
9175628
add missing full stop
d088a3f
create bearer token validator
1737752
add bearer token introspection response
af2cde2
add introspection validator interface
2a1a8b9
refactor introspection response
4611bed
update introspector to use introspection validator interface
2745059
fix code style
66f9843
update phpdoc
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<?php | ||
|
||
use League\OAuth2\Server\AuthorizationServer; | ||
use League\OAuth2\Server\Exception\OAuthServerException; | ||
use OAuth2ServerExamples\Repositories\AccessTokenRepository; | ||
use OAuth2ServerExamples\Repositories\ClientRepository; | ||
use OAuth2ServerExamples\Repositories\ScopeRepository; | ||
use Psr\Http\Message\ResponseInterface; | ||
use Psr\Http\Message\ServerRequestInterface; | ||
use Slim\App; | ||
|
||
include __DIR__ . '/../vendor/autoload.php'; | ||
|
||
$app = new App([ | ||
// Add the authorization server to the DI container | ||
AuthorizationServer::class => function () { | ||
|
||
// Setup the authorization server | ||
$server = new AuthorizationServer( | ||
new ClientRepository(), // instance of ClientRepositoryInterface | ||
new AccessTokenRepository(), // instance of AccessTokenRepositoryInterface | ||
new ScopeRepository(), // instance of ScopeRepositoryInterface | ||
'file://' . __DIR__ . '/../private.key', // path to private key | ||
'lxZFUEsBCJ2Yb14IF2ygAHI5N4+ZAUXXaSeeJm6+twsUmIen' // encryption key | ||
); | ||
|
||
return $server; | ||
}, | ||
]); | ||
|
||
$app->post( | ||
'/introspect', | ||
function (ServerRequestInterface $request, ResponseInterface $response) use ($app) { | ||
|
||
/* @var \League\OAuth2\Server\AuthorizationServer $server */ | ||
$server = $app->getContainer()->get(AuthorizationServer::class); | ||
|
||
try { | ||
// Validate the given introspect request | ||
$server->validateIntrospectionRequest($request); | ||
|
||
// Try to respond to the introspection request | ||
return $server->respondToIntrospectionRequest($request, $response); | ||
} catch (OAuthServerException $exception) { | ||
|
||
// All instances of OAuthServerException can be converted to a PSR-7 response | ||
return $exception->generateHttpResponse($response); | ||
} catch (\Exception $exception) { | ||
|
||
// Catch unexpected exceptions | ||
$body = $response->getBody(); | ||
$body->write($exception->getMessage()); | ||
|
||
return $response->withStatus(500)->withBody($body); | ||
} | ||
} | ||
); | ||
|
||
$app->run(); |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
<?php | ||
|
||
namespace League\OAuth2\Server\IntrospectionValidators; | ||
|
||
use InvalidArgumentException; | ||
use Lcobucci\JWT\Parser; | ||
use Lcobucci\JWT\Signer\Keychain; | ||
use Lcobucci\JWT\Signer\Rsa\Sha256; | ||
use Lcobucci\JWT\Token; | ||
use Lcobucci\JWT\ValidationData; | ||
use League\OAuth2\Server\CryptKey; | ||
use League\OAuth2\Server\Repositories\AccessTokenRepositoryInterface; | ||
use Psr\Http\Message\ServerRequestInterface; | ||
|
||
class BearerTokenValidator implements IntrospectionValidatorInterface | ||
{ | ||
/** | ||
* @var AccessTokenRepositoryInterface | ||
*/ | ||
private $accessTokenRepository; | ||
|
||
/** | ||
* @var \League\OAuth2\Server\CryptKey | ||
*/ | ||
protected $privateKey; | ||
|
||
/** | ||
* @param AccessTokenRepositoryInterface $accessTokenRepository | ||
*/ | ||
public function __construct(AccessTokenRepositoryInterface $accessTokenRepository) | ||
{ | ||
$this->accessTokenRepository = $accessTokenRepository; | ||
} | ||
|
||
/** | ||
* Set the private key. | ||
* | ||
* @param \League\OAuth2\Server\CryptKey $key | ||
*/ | ||
public function setPrivateKey(CryptKey $key) | ||
{ | ||
$this->privateKey = $key; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function validateIntrospection(ServerRequestInterface $request) | ||
{ | ||
try { | ||
$token = $this->getTokenFromRequest($request); | ||
} catch (InvalidArgumentException $e) { | ||
return false; | ||
} | ||
|
||
if ( | ||
$this->isTokenRevoked($token) || | ||
$this->isTokenExpired($token) || | ||
$this->isTokenUnverified($token) | ||
) { | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* Gets the token from the request body. | ||
* | ||
* @param ServerRequestInterface $request | ||
* | ||
* @return Token | ||
*/ | ||
public function getTokenFromRequest(ServerRequestInterface $request) | ||
{ | ||
$jwt = $request->getParsedBody()['token'] ?? null; | ||
|
||
return (new Parser()) | ||
->parse($jwt); | ||
} | ||
|
||
/** | ||
* Checks whether the token is unverified. | ||
* | ||
* @param Token $token | ||
* | ||
* @return bool | ||
*/ | ||
private function isTokenUnverified(Token $token) | ||
{ | ||
$keychain = new Keychain(); | ||
|
||
$key = $keychain->getPrivateKey( | ||
$this->privateKey->getKeyPath(), | ||
$this->privateKey->getPassPhrase() | ||
); | ||
|
||
return $token->verify(new Sha256(), $key->getContent()) === false; | ||
} | ||
|
||
/** | ||
* Ensure access token hasn't expired. | ||
* | ||
* @param Token $token | ||
* | ||
* @return bool | ||
*/ | ||
private function isTokenExpired(Token $token) | ||
{ | ||
$data = new ValidationData(time()); | ||
|
||
return !$token->validate($data); | ||
} | ||
|
||
/** | ||
* Check if the given token is revoked. | ||
* | ||
* @param Token $token | ||
* | ||
* @return bool | ||
*/ | ||
private function isTokenRevoked(Token $token) | ||
{ | ||
return $this->accessTokenRepository->isAccessTokenRevoked($token->getClaim('jti')); | ||
} | ||
} |
17 changes: 17 additions & 0 deletions
17
src/IntrospectionValidators/IntrospectionValidatorInterface.php
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?php | ||
|
||
namespace League\OAuth2\Server\IntrospectionValidators; | ||
|
||
use Psr\Http\Message\ServerRequestInterface; | ||
|
||
interface IntrospectionValidatorInterface | ||
{ | ||
/** | ||
* Determine wether the introspection request is valid. | ||
* | ||
* @param ServerRequestInterface $request | ||
* | ||
* @return bool | ||
*/ | ||
public function validateIntrospection(ServerRequestInterface $request); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The BearerTokenValidator has no validation-key set, unless you also call here
But that also requires that the public-key is also added to the private-key file, as Lcobucci\JWT\Signer\Rsa::doVerify($expected, $payload, Key $key) calls open_ssl_publickey($key->getContent())!
With that change I was able to verify/introspect access_keys generated by my server.
I'm currently implementing an OpenID Connect / OAuth2 server for EGroupware