Skip to content

Commit

Permalink
No oauth scope but we can achive the same with different grant types …
Browse files Browse the repository at this point in the history
…and a little bit of overriding !
  • Loading branch information
ngodfraind committed Mar 2, 2016
1 parent 2f47a22 commit 03f4e10
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 1 deletion.
2 changes: 2 additions & 0 deletions Controller/API/User/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public function connectedUserAction()
$tokenStorage = $this->container->get('security.token_storage');
$token = $tokenStorage->getToken();

var_dump($token->getRoles());

if ($token) {
$user = $token->getUser();
$context = new SerializationContext();
Expand Down
6 changes: 6 additions & 0 deletions DependencyInjection/Compiler/DynamicConfigPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,11 @@ public function process(ContainerBuilder $container)

//notification
$container->setAlias('icap.notification.orm.entity_manager', 'claroline.persistence.object_manager');

//oauth

$container
->getDefinition('fos_oauth_server.security.authentication.provider')
->setClass('Claroline\CoreBundle\Library\Security\Provider\OAuthProvider');
}
}
2 changes: 1 addition & 1 deletion Library/Security/Authentication/ClarolineApiListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public function handleCookie(GetResponseEvent $event)

/**
* Refreshes the user by reloading it from the user provider.
* This method was copied from always the same, copied from Symfony\Component\Security\Http\Firewall\ContextListener
* This method was copied from Symfony\Component\Security\Http\Firewall\ContextListener
*
* @param TokenInterface $token
*
Expand Down
151 changes: 151 additions & 0 deletions Library/Security/Provider/OAuthProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

/*
* This file is part of the FOSOAuthServerBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Claroline\CoreBundle\Library\Security\Provider;

use FOS\OAuthServerBundle\Security\Authentication\Token\OAuthToken;
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\AccountStatusException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use OAuth2\OAuth2;
use OAuth2\OAuth2ServerException;
use OAuth2\OAuth2AuthenticateException;

/**
* OAuthProvider class.
* Copied from FOS\OAuthServerBundle\Security\Authentication\Provider
* class is defined in ClarolineCoreBundle/Resources/config/service.yml
*
* @author Arnaud Le Blanc <[email protected]>
*/
class OAuthProvider implements AuthenticationProviderInterface
{
/**
* @var UserProviderInterface
*/
protected $userProvider;
/**
* @var OAuth2
*/
protected $serverService;
/**
* @var UserCheckerInterface
*/
protected $userChecker;

/**
* @param UserProviderInterface $userProvider The user provider.
* @param OAuth2 $serverService The OAuth2 server service.
* @param UserCheckerInterface $userChecker The Symfony User Checker for Pre and Post auth checks
*/
public function __construct(UserProviderInterface $userProvider, OAuth2 $serverService, UserCheckerInterface $userChecker)
{
$this->userProvider = $userProvider;
$this->serverService = $serverService;
$this->userChecker = $userChecker;
}

/**
* {@inheritdoc}
*/
public function authenticate(TokenInterface $token)
{
if (!$this->supports($token)) {
return;
}

try {
$tokenString = $token->getToken();

if ($accessToken = $this->serverService->verifyAccessToken($tokenString)) {
$scope = $accessToken->getScope();
$user = $accessToken->getUser();

if (null !== $user) {
try {
$this->userChecker->checkPreAuth($user);
} catch (AccountStatusException $e) {
throw new OAuth2AuthenticateException(OAuth2::HTTP_UNAUTHORIZED,
OAuth2::TOKEN_TYPE_BEARER,
$this->serverService->getVariable(OAuth2::CONFIG_WWW_REALM),
'access_denied',
$e->getMessage()
);
}

$token->setUser($user);
}

$roles = (null !== $user) ? $user->getRoles() : array();

/*
* This is the only modification from the base class.
* We only add scopes if we're not connected as user.
* Otherwise, if we support the scope admin, everyone will be admin if no scope are requested because fos-oauth2-lib
* doesn't support different scope by clients (https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/issues/201)
* This way, we can bypass this by creating 2 clients: 1 wich grant the password (and refresh) types
* (and will require a user authentication)
* One that grant pretty much all the rest.
*/
if (!$user) {
if (!empty($scope)) {
foreach (explode(' ', $scope) as $role) {
$roles[] = 'ROLE_'.strtoupper($role);
}
}
}

$roles = array_unique($roles, SORT_REGULAR);

$token = new OAuthToken($roles);
$token->setAuthenticated(true);
$token->setToken($tokenString);

if (null !== $user) {
try {
$this->userChecker->checkPostAuth($user);
} catch (AccountStatusException $e) {
throw new OAuth2AuthenticateException(OAuth2::HTTP_UNAUTHORIZED,
OAuth2::TOKEN_TYPE_BEARER,
$this->serverService->getVariable(OAuth2::CONFIG_WWW_REALM),
'access_denied',
$e->getMessage()
);
}

$token->setUser($user);
}

return $token;
}
} catch (OAuth2ServerException $e) {
if (!method_exists('Symfony\Component\Security\Core\Exception\AuthenticationException', 'setToken')) {
// Symfony 2.1
throw new AuthenticationException('OAuth2 authentication failed', null, 0, $e);
}

throw new AuthenticationException('OAuth2 authentication failed', 0, $e);
}

throw new AuthenticationException('OAuth2 authentication failed');
}

/**
* {@inheritdoc}
*/
public function supports(TokenInterface $token)
{
return $token instanceof OAuthToken;
}
}

0 comments on commit 03f4e10

Please sign in to comment.