Compare commits

...

14 Commits
5.0.1 ... 5.0.2

Author SHA1 Message Date
Alex Bilbie
14b6761c0f Changelog update 2016-04-19 10:28:20 +01:00
Alex Bilbie
7c61922f07 Merge pull request #551 from ivyhjk/patch-1
wrong comment "month"
2016-04-19 09:53:17 +01:00
ivyhjk
20535ad95b wrong comment "month" 2016-04-18 18:08:27 -03:00
Alex Bilbie
e885114714 Improved examples 2016-04-18 12:23:21 +01:00
Alex Bilbie
f80d0d39a4 Updated .scrutenizer.yml 2016-04-18 12:23:13 +01:00
Alex Bilbie
7bfd5b7d0d Added abstract methods for required methods 2016-04-18 12:22:15 +01:00
Alex Bilbie
143a2e32f7 Client may return an array of redirect URIs 2016-04-18 12:21:42 +01:00
Alex Bilbie
8f418cff08 Added missing state parameter in redirect response 2016-04-18 12:19:54 +01:00
Alex Bilbie
fcec1f3442 Cody tidy 2016-04-18 12:19:36 +01:00
Alex Bilbie
46e7eef14e Client could potentially return an array of redirect URIs 2016-04-18 12:12:36 +01:00
Alex Bilbie
51f44fdf17 Code tidy 2016-04-18 12:12:06 +01:00
Alex Bilbie
f8b2e80ef3 Removed unnecessary parameter usage 2016-04-18 12:10:57 +01:00
Alex Bilbie
7045785d89 Spelling fix 2016-04-18 08:41:00 +01:00
Alex Bilbie
301ddc53c7 Updated changelog 2016-04-18 08:40:34 +01:00
9 changed files with 146 additions and 112 deletions

View File

@@ -2,7 +2,6 @@ filter:
excluded_paths:
- tests/*
- vendor/*
- examples/*
checks:
php:
code_rating: true

View File

@@ -1,6 +1,15 @@
# Changelog
## 5.0.0 (release 2016-04-17)
## 5.0.2 (released 2016-04-18)
* `state` parameter is now correctly returned after implicit grant authorization
* Small code and docblock improvements
## 5.0.1 (released 2016-04-18)
* Fixes an issue (#550) whereby it was unclear whether or not to validate a client's secret during a request.
## 5.0.0 (released 2016-04-17)
Version 5 is a complete code rewrite.

View File

@@ -1,11 +1,4 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
use League\OAuth2\Server\ResourceServer;
use OAuth2ServerExamples\Repositories\AccessTokenRepository;
@@ -16,63 +9,65 @@ use Slim\App;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'displayErrorDetails' => true,
],
// Add the resource server to the DI container
ResourceServer::class => function () {
// Setup the authorization server
$server = new ResourceServer(
new AccessTokenRepository(),
'file://' . __DIR__ . '/../public.key'
new AccessTokenRepository(), // instance of AccessTokenRepositoryInterface
'file://' . __DIR__ . '/../public.key' // the authorization server's public key
);
return $server;
},
]);
// Add the resource server middleware which will intercept and validate requests
$app->add(
new \League\OAuth2\Server\Middleware\ResourceServerMiddleware(
$app->getContainer()->get(ResourceServer::class)
)
);
$app->get('/users', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
// An example endpoint secured with OAuth 2.0
$app->get(
'/users',
function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
$users = [
[
'id' => 123,
'name' => 'Alex',
'email' => 'alex@thephpleague.com',
],
[
'id' => 124,
'name' => 'Frank',
'email' => 'frank@thephpleague.com',
],
[
'id' => 125,
'name' => 'Phil',
'email' => 'phil@thephpleague.com',
],
];
$users = [
[
'id' => 123,
'name' => 'Alex',
'email' => 'alex@thephpleague.com',
],
[
'id' => 124,
'name' => 'Frank',
'email' => 'frank@thephpleague.com',
],
[
'id' => 125,
'name' => 'Phil',
'email' => 'phil@thephpleague.com',
],
];
// If the access token doesn't have the `basic` scope hide users' names
if (in_array('basic', $request->getAttribute('oauth_scopes')) === false) {
for ($i = 0; $i < count($users); $i++) {
unset($users[$i]['name']);
// If the access token doesn't have the `basic` scope hide users' names
if (in_array('basic', $request->getAttribute('oauth_scopes')) === false) {
for ($i = 0; $i < count($users); $i++) {
unset($users[$i]['name']);
}
}
}
// If the access token doesn't have the `emal` scope hide users' email addresses
if (in_array('email', $request->getAttribute('oauth_scopes')) === false) {
for ($i = 0; $i < count($users); $i++) {
unset($users[$i]['email']);
// If the access token doesn't have the `email` scope hide users' email addresses
if (in_array('email', $request->getAttribute('oauth_scopes')) === false) {
for ($i = 0; $i < count($users); $i++) {
unset($users[$i]['email']);
}
}
$response->getBody()->write(json_encode($users));
return $response->withStatus(200);
}
);
$response->getBody()->write(json_encode($users));
return $response->withStatus(200);
});
$app->run();
$app->run();

View File

@@ -29,7 +29,7 @@ $app = new App([
],
AuthorizationServer::class => function () {
// Init our repositories
$clientRepository = new ClientReptository();
$clientRepository = new ClientRepository();
$scopeRepository = new ScopeRepository();
$accessTokenRepository = new AccessTokenRepository();
$authCodeRepository = new AuthCodeRepository();

View File

@@ -1,11 +1,4 @@
<?php
/**
* @author Alex Bilbie <hello@alexbilbie.com>
* @copyright Copyright (c) Alex Bilbie
* @license http://mit-license.org/
*
* @link https://github.com/thephpleague/oauth2-server
*/
use League\OAuth2\Server\AuthorizationServer;
use League\OAuth2\Server\Exception\OAuthServerException;
@@ -18,58 +11,64 @@ use OAuth2ServerExamples\Repositories\UserRepository;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\App;
use Zend\Diactoros\Stream;
include __DIR__ . '/../vendor/autoload.php';
$app = new App([
'settings' => [
'displayErrorDetails' => true,
],
// Add the authorization server to the DI container
AuthorizationServer::class => function () {
// Init our repositories
$clientRepository = new ClientRepository();
$accessTokenRepository = new AccessTokenRepository();
$scopeRepository = new ScopeRepository();
$userRepository = new UserRepository();
$refreshTokenRepository = new RefreshTokenRepository();
$privateKeyPath = 'file://' . __DIR__ . '/../private.key';
$publicKeyPath = 'file://' . __DIR__ . '/../public.key';
// Setup the authorization server
$server = new AuthorizationServer(
$clientRepository,
$accessTokenRepository,
$scopeRepository,
$privateKeyPath,
$publicKeyPath
new ClientRepository(), // instance of ClientRepositoryInterface
new AccessTokenRepository(), // instance of AccessTokenRepositoryInterface
new ScopeRepository(), // instance of ScopeRepositoryInterface
'file://'.__DIR__.'/../private.key', // path to private key
'file://'.__DIR__.'/../public.key' // path to public key
);
$grant = new PasswordGrant(
new UserRepository(), // instance of UserRepositoryInterface
new RefreshTokenRepository() // instance of RefreshTokenRepositoryInterface
);
$grant->setRefreshTokenTTL(new \DateInterval('P1M')); // refresh tokens will expire after 1 month
// Enable the password grant on the server with a token TTL of 1 hour
$server->enableGrantType(
new PasswordGrant($userRepository, $refreshTokenRepository),
new \DateInterval('PT1H')
$grant,
new \DateInterval('PT1H') // access tokens will expire after 1 hour
);
return $server;
},
]);
$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
/* @var \League\OAuth2\Server\AuthorizationServer $server */
$server = $app->getContainer()->get(AuthorizationServer::class);
$app->post(
'/access_token',
function (ServerRequestInterface $request, ResponseInterface $response) use ($app) {
try {
return $server->respondToAccessTokenRequest($request, $response);
} catch (OAuthServerException $exception) {
return $exception->generateHttpResponse($response);
} catch (\Exception $exception) {
$body = new Stream('php://temp', 'r+');
$body->write($exception->getMessage());
/* @var \League\OAuth2\Server\AuthorizationServer $server */
$server = $app->getContainer()->get(AuthorizationServer::class);
return $response->withStatus(500)->withBody($body);
try {
// Try to respond to the access token request
return $server->respondToAccessTokenRequest($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();

View File

@@ -204,7 +204,7 @@ class AuthorizationServer implements EmitterAwareInterface
protected function getResponseType()
{
if (!$this->responseType instanceof ResponseTypeInterface) {
$this->responseType = new BearerTokenResponse($this->accessTokenRepository);
$this->responseType = new BearerTokenResponse();
}
$this->responseType->setPrivateKey($this->privateKey);

View File

@@ -13,6 +13,8 @@ use Lcobucci\JWT\Builder;
use Lcobucci\JWT\Signer\Key;
use Lcobucci\JWT\Signer\Rsa\Sha256;
use League\OAuth2\Server\CryptKey;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Entities\ScopeEntityInterface;
trait AccessTokenTrait
{
@@ -36,4 +38,24 @@ trait AccessTokenTrait
->sign(new Sha256(), new Key($privateKey->getKeyPath(), $privateKey->getPassPhrase()))
->getToken();
}
/**
* @return ClientEntityInterface
*/
abstract public function getClient();
/**
* @return \DateTime
*/
abstract public function getExpiryDateTime();
/**
* @return string|int
*/
abstract public function getUserIdentifier();
/**
* @return ScopeEntityInterface[]
*/
abstract public function getScopes();
}

View File

@@ -108,7 +108,12 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
}
// Finalize the requested scopes
$scopes = $this->scopeRepository->finalizeScopes($scopes, $this->getIdentifier(), $client, $authCodePayload->user_id);
$scopes = $this->scopeRepository->finalizeScopes(
$scopes,
$this->getIdentifier(),
$client,
$authCodePayload->user_id
);
} catch (\LogicException $e) {
throw OAuthServerException::invalidRequest('code', 'Cannot decrypt the authorization code');
}
@@ -194,7 +199,9 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
$scopes = $this->validateScopes(
$this->getQueryStringParameter('scope', $request),
$client->getRedirectUri()
is_array($client->getRedirectUri())
? $client->getRedirectUri()[0]
: $client->getRedirectUri()
);
$stateParameter = $this->getQueryStringParameter('state', $request);
@@ -234,25 +241,25 @@ class AuthCodeGrant extends AbstractAuthorizeGrant
$authorizationRequest->getScopes()
);
$redirectPayload['code'] = $this->encrypt(
json_encode(
[
'client_id' => $authCode->getClient()->getIdentifier(),
'redirect_uri' => $authCode->getRedirectUri(),
'auth_code_id' => $authCode->getIdentifier(),
'scopes' => $authCode->getScopes(),
'user_id' => $authCode->getUserIdentifier(),
'expire_time' => (new \DateTime())->add($this->authCodeTTL)->format('U'),
]
)
);
$redirectPayload['state'] = $authorizationRequest->getState();
$response = new RedirectResponse();
$response->setRedirectUri(
$this->makeRedirectUri(
$finalRedirectUri,
$redirectPayload
[
'code' => $this->encrypt(
json_encode(
[
'client_id' => $authCode->getClient()->getIdentifier(),
'redirect_uri' => $authCode->getRedirectUri(),
'auth_code_id' => $authCode->getIdentifier(),
'scopes' => $authCode->getScopes(),
'user_id' => $authCode->getUserIdentifier(),
'expire_time' => (new \DateTime())->add($this->authCodeTTL)->format('U'),
]
)
),
'state' => $authorizationRequest->getState(),
]
)
);

View File

@@ -146,7 +146,9 @@ class ImplicitGrant extends AbstractAuthorizeGrant
$scopes = $this->validateScopes(
$this->getQueryStringParameter('scope', $request),
$client->getRedirectUri()
is_array($client->getRedirectUri())
? $client->getRedirectUri()[0]
: $client->getRedirectUri()
);
$stateParameter = $this->getQueryStringParameter('state', $request);
@@ -185,15 +187,16 @@ class ImplicitGrant extends AbstractAuthorizeGrant
$authorizationRequest->getScopes()
);
$redirectPayload['access_token'] = (string) $accessToken->convertToJWT($this->privateKey);
$redirectPayload['token_type'] = 'bearer';
$redirectPayload['expires_in'] = $accessToken->getExpiryDateTime()->getTimestamp() - (new \DateTime())->getTimestamp();
$response = new RedirectResponse();
$response->setRedirectUri(
$this->makeRedirectUri(
$finalRedirectUri,
$redirectPayload,
[
'access_token' => (string) $accessToken->convertToJWT($this->privateKey),
'token_type' => 'bearer',
'expires_in' => $accessToken->getExpiryDateTime()->getTimestamp() - (new \DateTime())->getTimestamp(),
'state' => $authorizationRequest->getState(),
],
'#'
)
);