From ead963bcba0a3436fde7395c6957134c1cdcc4e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vedran=20Miho=C4=8Dinec?= Date: Tue, 25 Feb 2020 20:46:29 +0100 Subject: [PATCH 1/4] Add documentation for authorization code grant --- README.md | 1 + docs/authorization-code-grant.md | 124 +++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 docs/authorization-code-grant.md diff --git a/README.md b/README.md index 64357f0b..f386df37 100644 --- a/README.md +++ b/README.md @@ -148,6 +148,7 @@ security: * [Basic setup](docs/basic-setup.md) * [Controlling token scopes](docs/controlling-token-scopes.md) +* [Authorization code grant](docs/authorization-code-grant.md) * [Password grant handling](docs/password-grant-handling.md) ## Development diff --git a/docs/authorization-code-grant.md b/docs/authorization-code-grant.md new file mode 100644 index 00000000..57b8e3a5 --- /dev/null +++ b/docs/authorization-code-grant.md @@ -0,0 +1,124 @@ +# Authorization code grant + +Authorization code grant has two steps + +1. Acquiring authorization code +2. Getting token from authorization code + +## Requirements + +To use authorization code grant `enable_auth_code_grant` parameter inside `authorization_server` must be set to `true` (it is set to `true` by default). + +### Example: config.yml + +```yaml +trikoder_oauth2: + authorization_server: + enable_auth_code_grant: true +``` + +After authorization code grant is enabled, token and authorization endpoints must be set. +It can be done by including `Resources/config/routes.xml` which will provide `/authorize` or `/token` endpoints or manually by setting + +1. Controller `Trikoder\Bundle\OAuth2Bundle\Controller\AuthorizationController::indexAction` with `GET` method for authorization endpoint +2. Controller `Trikoder\Bundle\OAuth2Bundle\Controller\TokenController::indexAction` with `POST` method for token endpoint + +### Example: custom setup + +```yaml +oauth2_authorization_code: + controller: Trikoder\Bundle\OAuth2Bundle\Controller\AuthorizationController::indexAction + path: /oauth2-authorization-code + +oauth2_token: + controller: Trikoder\Bundle\OAuth2Bundle\Controller\TokenController::indexAction + path: /api/token +``` + +After assigning routes, listener for `trikoder.oauth2.authorization_request_resolve` must be configured. + +`\Trikoder\Bundle\OAuth2Bundle\Event\AuthorizationRequestResolveEvent` (whose name is `trikoder.oauth2.authorization_request_resolve`) consist of three important methods which have to be used + +1. `setUser(?UserInterface $user)` and `resolveAuthorization(bool $authorizationResolution)` when user is already logged in when accessing authorization endpoint +2. `setResponse(ResponseInterface $response)` when user needs to log in before authorization server can issue authorization code + +### Example: (services.yml and php class) + +```yaml + BestNamespace\OAuthLogin\Listener\AuthorizationCodeListener: + tags: + - { name: kernel.event_listener, event: 'trikoder.oauth2.authorization_request_resolve', method: onAuthorizationRequestResolve } +``` + +```php +security = $security; + $this->urlGenerator = $urlGenerator; + $this->requestStack = $requestStack; + } + + public function onAuthorizationRequestResolve(AuthorizationRequestResolveEvent $event) + { + if (null !== ($user = $this->security->getUser())) { + $event->setUser($user); + $event->resolveAuthorization(true); + } else { + $event->setResponse( + new Response( + 302, + [ + 'Location' => $this->urlGenerator->generate( + 'login', + [ + 'returnUrl' => $this->requestStack->getMasterRequest()->getUri(), + ] + ), + ] + ) + ); + } + } +} +``` + +After listener is configured new client can be registered. + +### Example: cli + +``` +bin/console trikoder:oauth2:create-client best_client not_so_secret --redirect-uri "https://www.bestclient.com/" --grant-type "authorization_code" --scope "user.view" +``` + +This example assumes scope `user.view` is already registered scope inside `trikoder_oauth2` configuration + +### Example: config.yml + +```yaml +trikoder_oauth2: + scopes: + - 'user.view' +``` + +After client is registered he can communicate with your server using authorization code grant. From a400fc4ee46951a2139131323d2727b4ebee9934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vedran=20Miho=C4=8Dinec?= Date: Mon, 2 Mar 2020 10:44:15 +0100 Subject: [PATCH 2/4] Apply suggestions from code review Co-Authored-By: Hideki Okajima --- docs/authorization-code-grant.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/authorization-code-grant.md b/docs/authorization-code-grant.md index 57b8e3a5..68d147f5 100644 --- a/docs/authorization-code-grant.md +++ b/docs/authorization-code-grant.md @@ -2,7 +2,7 @@ Authorization code grant has two steps -1. Acquiring authorization code +1. Getting authorization code 2. Getting token from authorization code ## Requirements @@ -12,6 +12,8 @@ To use authorization code grant `enable_auth_code_grant` parameter inside `autho ### Example: config.yml ```yaml +# /packages/trikoder_oauth2.yaml + trikoder_oauth2: authorization_server: enable_auth_code_grant: true @@ -26,6 +28,8 @@ It can be done by including `Resources/config/routes.xml` which will provide `/a ### Example: custom setup ```yaml +# /routes/trikoder_oauth2.yaml + oauth2_authorization_code: controller: Trikoder\Bundle\OAuth2Bundle\Controller\AuthorizationController::indexAction path: /oauth2-authorization-code @@ -83,7 +87,7 @@ final class AuthorizationCodeListener { if (null !== ($user = $this->security->getUser())) { $event->setUser($user); - $event->resolveAuthorization(true); + $event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_APPROVED); } else { $event->setResponse( new Response( @@ -116,6 +120,8 @@ This example assumes scope `user.view` is already registered scope inside `triko ### Example: config.yml ```yaml +# /packages/trikoder_oauth2.yaml + trikoder_oauth2: scopes: - 'user.view' From b79eeca1e00c4bd169972f5f7d0b5b64adfae429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vedran=20Miho=C4=8Dinec?= Date: Mon, 2 Mar 2020 11:02:21 +0100 Subject: [PATCH 3/4] Add listener notice and improve example --- docs/authorization-code-grant.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/docs/authorization-code-grant.md b/docs/authorization-code-grant.md index 68d147f5..81073cb3 100644 --- a/docs/authorization-code-grant.md +++ b/docs/authorization-code-grant.md @@ -9,7 +9,7 @@ Authorization code grant has two steps To use authorization code grant `enable_auth_code_grant` parameter inside `authorization_server` must be set to `true` (it is set to `true` by default). -### Example: config.yml +### Example: config ```yaml # /packages/trikoder_oauth2.yaml @@ -46,7 +46,9 @@ After assigning routes, listener for `trikoder.oauth2.authorization_request_reso 1. `setUser(?UserInterface $user)` and `resolveAuthorization(bool $authorizationResolution)` when user is already logged in when accessing authorization endpoint 2. `setResponse(ResponseInterface $response)` when user needs to log in before authorization server can issue authorization code -### Example: (services.yml and php class) +`\Trikoder\Bundle\OAuth2Bundle\EventListener\AuthorizationRequestUserResolvingListener` with priority value `1024` calls `setUser(?UserInterface $user)` if user is logged in, so make sure your listener has lower priority than it. + +### Example: services.yml and php class ```yaml BestNamespace\OAuthLogin\Listener\AuthorizationCodeListener: @@ -64,29 +66,24 @@ namespace BestNamespace\OAuthLogin\Listener; use Nyholm\Psr7\Response; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Security\Core\Security; use Trikoder\Bundle\OAuth2Bundle\Event\AuthorizationRequestResolveEvent; final class AuthorizationCodeListener { - private $security; private $urlGenerator; private $requestStack; public function __construct( - Security $security, UrlGeneratorInterface $urlGenerator, RequestStack $requestStack ) { - $this->security = $security; $this->urlGenerator = $urlGenerator; $this->requestStack = $requestStack; } public function onAuthorizationRequestResolve(AuthorizationRequestResolveEvent $event) { - if (null !== ($user = $this->security->getUser())) { - $event->setUser($user); + if (null !== $event->getUser()) { $event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_APPROVED); } else { $event->setResponse( @@ -117,7 +114,7 @@ bin/console trikoder:oauth2:create-client best_client not_so_secret --redirect-u This example assumes scope `user.view` is already registered scope inside `trikoder_oauth2` configuration -### Example: config.yml +### Example: config ```yaml # /packages/trikoder_oauth2.yaml From 854faf9474dded26b69473237143d5ef7a333102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vedran=20Miho=C4=8Dinec?= Date: Tue, 30 Mar 2021 13:18:33 +0200 Subject: [PATCH 4/4] Update documentation for authorization code grant --- docs/authorization-code-grant.md | 34 ++++++++++++++------------------ 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/docs/authorization-code-grant.md b/docs/authorization-code-grant.md index 81073cb3..36718715 100644 --- a/docs/authorization-code-grant.md +++ b/docs/authorization-code-grant.md @@ -7,7 +7,7 @@ Authorization code grant has two steps ## Requirements -To use authorization code grant `enable_auth_code_grant` parameter inside `authorization_server` must be set to `true` (it is set to `true` by default). +To use authorization code grant `trikoder_oauth2.authorization_server.grant_types.authorization_code.enable` must be set to `true` (it is set to `true` by default). ### Example: config @@ -16,7 +16,9 @@ To use authorization code grant `enable_auth_code_grant` parameter inside `autho trikoder_oauth2: authorization_server: - enable_auth_code_grant: true + grant_types: + authorization_code: + enable: true ``` After authorization code grant is enabled, token and authorization endpoints must be set. @@ -81,25 +83,19 @@ final class AuthorizationCodeListener $this->requestStack = $requestStack; } - public function onAuthorizationRequestResolve(AuthorizationRequestResolveEvent $event) + public function onAuthorizationRequestResolve(AuthorizationRequestResolveEvent $event): void { - if (null !== $event->getUser()) { - $event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_APPROVED); - } else { - $event->setResponse( - new Response( - 302, - [ - 'Location' => $this->urlGenerator->generate( - 'login', - [ - 'returnUrl' => $this->requestStack->getMasterRequest()->getUri(), - ] - ), - ] - ) - ); + if (null === $event->getUser()) { + $event->setResponse(new Response(302, [ + 'Location' => $this->urlGenerator->generate('login', [ + 'returnUrl' => $this->requestStack->getMasterRequest()->getUri(), + ]), + ])); + + return; } + + $event->resolveAuthorization(AuthorizationRequestResolveEvent::AUTHORIZATION_APPROVED); } } ```