diff --git a/auth-server-refresh-token.md b/auth-server-refresh-token.md index 157cf3a8..12438104 100755 --- a/auth-server-refresh-token.md +++ b/auth-server-refresh-token.md @@ -1,26 +1,81 @@ --- layout: default -title: Authorization server with refresh token grant +title: Refresh token grant permalink: /authorization-server/refresh-token-grant/ --- -# Authorization server with refresh token grant +# Refresh token grant + +Access tokens eventually expire; however some grants respond with a refresh token which enables the client to refresh the access token. + +## Flow + +The client sends a POST request with following body parameters to the authorization server: + +* `grant_type` with the value `refresh_token` +* `client_id` with the the client's ID +* `client_secret` with the client's secret +* `scope` with a space-delimited list of requested scope permissions. This is optional; if not sent the original scopes will be used, otherwise you can request a reduced set of scopes. + +The authorization server will respond with a JSON object containing the following properties: + +* `token_type` with the value `Bearer` +* `expires_in` with an integer representing the TTL of the access token +* `access_token` a new JWT signed with the authorization server's private key +* `refresh_token` an encrypted payload that can be used to refresh the access token when it expires ## Setup -Wherever you intialise your objects, initialize a new instance of the authorization server and bind the storage interfaces and authorization code grant: +Wherever you initialize your objects, initialize a new instance of the authorization server and bind the storage interfaces and authorization code grant: -~~~ php -$server = new \League\OAuth2\Server\AuthorizationServer; +{% highlight php %} +// Init our repositories +$clientRepository = new ClientRepository(); +$accessTokenRepository = new AccessTokenRepository(); +$scopeRepository = new ScopeRepository(); +$refreshTokenRepository = new RefreshTokenRepository(); -$server->setSessionStorage(new Storage\SessionStorage); -$server->setAccessTokenStorage(new Storage\AccessTokenStorage); -$server->setClientStorage(new Storage\ClientStorage); -$server->setScopeStorage(new Storage\ScopeStorage); -$server->setRefreshTokenStorage(new Storage\RefreshTokenStorage); +// Path to public and private keys +$privateKeyPath = 'file://path/to/private.key'; +$publicKeyPath = 'file://path/to/public.key'; + +// Setup the authorization server +$server = new \League\OAuth2\Server\Server( + $clientRepository, + $accessTokenRepository, + $scopeRepository, + $privateKeyPath, + $publicKeyPath +); -$refreshTokenGrant = new \League\OAuth2\Server\Grant\RefreshTokenGrant(); -$server->addGrantType($refreshTokenGrant); -~~~ +// Enable the refresh token grant on the server with a token TTL of 1 hour +$server->enableGrantType( + new \League\OAuth2\Server\Grant\RefreshTokenGrant($refreshTokenRepository), + new \DateInterval('PT1H') +); +{% endhighlight %} -When the refresh token grant is enabled, a refresh token will automatically be created with access tokens issued requested using the [authorization code](/authorization-server/auth-code-grant/) or [resource owner password credentials](/authorization-server/resource-owner-password-credentials-grant/) grants. +## Implementation + +The client will request an access token so create an `/access_token` endpoint. + +{% highlight php %} +$app->post('/access_token', function (ServerRequestInterface $request, ResponseInterface $response) use ($app) { + + /* @var \League\OAuth2\Server\Server $server */ + $server = $app->getContainer()->get(Server::class); + + // Try to respond to the request + try { + return $server->respondToRequest($request, $response); + + } catch (\League\OAuth2\Server\Exception\OAuthServerException $exception) { + return $exception->generateHttpResponse($response); + + } catch (\Exception $exception) { + $body = new Stream('php://temp', 'r+'); + $body->write($exception->getMessage()); + return $response->withStatus(500)->withBody($body); + } +}); +{% endhighlight %}