From 0b4cb42456dd63d7e0d6e8e954754059d7f8561f Mon Sep 17 00:00:00 2001 From: Fred Cox Date: Tue, 8 Aug 2017 16:19:15 +0300 Subject: [PATCH 1/2] Load users in Symfony resource provider Allows the token to contain not just the username but the actual user object, using a user provider Also the token will have roles from the user --- .../Provider/ResourceProvider.php | 22 ++++++++++++++++--- .../Core/Authentication/Token/AccessToken.php | 6 ++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/ResourceProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/ResourceProvider.php index 6872f7da..595ab044 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/ResourceProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/ResourceProvider.php @@ -16,6 +16,8 @@ use AuthBucket\OAuth2\Symfony\Component\Security\Core\Authentication\Token\AccessToken; use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; +use Symfony\Component\Security\Core\User\UserProviderInterface; /** * ResourceProvider implements OAuth2 resource endpoint authentication. @@ -29,19 +31,22 @@ class ResourceProvider implements AuthenticationProviderInterface protected $resourceType; protected $scopeRequired; protected $options; + protected $userProvider; public function __construct( $providerKey, ResourceTypeHandlerFactoryInterface $resourceTypeHandlerFactory, $resourceType = 'model', array $scopeRequired = [], - array $options = [] + array $options = [], + UserProviderInterface $userProvider = null ) { $this->providerKey = $providerKey; $this->resourceTypeHandlerFactory = $resourceTypeHandlerFactory; $this->resourceType = $resourceType; $this->scopeRequired = $scopeRequired; $this->options = $options; + $this->userProvider = $userProvider; } public function authenticate(TokenInterface $token) @@ -68,6 +73,17 @@ public function authenticate(TokenInterface $token) } } + $user = null; + $roles = $token->getRoles(); + if ($this->userProvider) { + try { + $user = $this->userProvider->loadUserByUsername($accessToken->getUsername()); + $roles = array_merge($roles, $user->getRoles()); + } catch (UsernameNotFoundException $e) { + // No user with this username, but there is a valid access token, so thats all good + } + } + $tokenAuthenticated = new AccessToken( $this->providerKey, $accessToken->getAccessToken(), @@ -76,9 +92,9 @@ public function authenticate(TokenInterface $token) $accessToken->getUsername(), $accessToken->getExpires(), $accessToken->getScope(), - $token->getRoles() + $roles, + $user ? $user : $accessToken->getUsername() ); - $tokenAuthenticated->setUser($accessToken->getUsername()); return $tokenAuthenticated; } diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/AccessToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/AccessToken.php index f7da8f75..d425a3f1 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/AccessToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/AccessToken.php @@ -36,7 +36,8 @@ public function __construct( $username = '', $expires = '', array $scope = [], - array $roles = [] + array $roles = [], + $user = null ) { parent::__construct($roles); @@ -48,6 +49,9 @@ public function __construct( $this->username = $username; $this->expires = $expires; $this->scope = $scope; + if (null !== $user) { + $this->setUser($user); + } parent::setAuthenticated(count($roles) > 0); } From f64dcad3c3455184497b50a886b002f7d83862e0 Mon Sep 17 00:00:00 2001 From: Fred Cox Date: Thu, 17 Aug 2017 17:19:41 +0300 Subject: [PATCH 2/2] Add authorized scopes as roles This makes it easy to require certain scopes for specific actions rather than having to do it at the firewall level --- .../Security/Core/Authentication/Provider/ResourceProvider.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/ResourceProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/ResourceProvider.php index 595ab044..7669f96a 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/ResourceProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/ResourceProvider.php @@ -83,6 +83,9 @@ public function authenticate(TokenInterface $token) // No user with this username, but there is a valid access token, so thats all good } } + $roles = array_merge($roles, array_map(function($scope) { + return 'ROLE_SCOPE_' . strtoupper($scope); + }, $scope)); $tokenAuthenticated = new AccessToken( $this->providerKey,