Skip to content

Commit

Permalink
Symfony 5.3 new authenticator system compliant
Browse files Browse the repository at this point in the history
  • Loading branch information
borisDigitalinsure committed Jul 17, 2021
1 parent fe553a2 commit 565d05f
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 33 deletions.
30 changes: 30 additions & 0 deletions Model/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,34 @@ public function getAllowedGrantTypes()
{
return $this->allowedGrantTypes;
}

public function getRoles()
{
return [ 'ROLE_USER' ];
}

public function getPassword()
{
return $this->getSecret();
}

public function getSalt()
{
// Will use auto salt system
}

public function eraseCredentials()
{
// nothind to erase
}

public function getUsername()
{
return $this->getRandomId();
}

public function getUserIdentifier(): string
{
return $this->getRandomId();
}
}
13 changes: 13 additions & 0 deletions Security/Authenticator/OAuth2Passport.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php


namespace FOS\OAuthServerBundle\Security\Authenticator;


use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportTrait;

class OAuth2Passport implements PassportInterface
{
use PassportTrait;
}
48 changes: 16 additions & 32 deletions Security/Authenticator/Oauth2Authenticator.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

namespace FOS\OAuthServerBundle\Security\Authenticator;

use FOS\OAuthServerBundle\Model\AccessToken;
use FOS\OAuthServerBundle\Security\Authentication\Token\OAuthToken;
use FOS\OAuthServerBundle\Security\Authenticator\Passport\Badge\AccessTokenBadge;
use OAuth2\OAuth2;
use OAuth2\OAuth2AuthenticateException;
use OAuth2\OAuth2ServerException;
Expand All @@ -15,8 +17,6 @@
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Http\Authenticator\AbstractAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CustomCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\Authenticator\Passport\SelfValidatingPassport;

Expand All @@ -32,7 +32,7 @@ class Oauth2Authenticator extends AbstractAuthenticator
*/
protected $serverService;

public function __construct(OAuth2 $serverService, UserCheckerInterface $userChecker)
public function __construct(OAuth2 $serverService, UserCheckerInterface $userChecker )
{
$this->serverService = $serverService;
$this->userChecker = $userChecker;
Expand All @@ -51,20 +51,14 @@ public function supports(Request $request): ?bool
*/
public function authenticate(Request $request): PassportInterface
{
return new SelfValidatingPassport(
new UserBadge('admin-workflow')
);

// die( 'test public function authenticate(Request $request): PassportInterface' );
try {
$tokenString = str_replace('Bearer ', '', $request->headers->get('Authorization'));

// TODO: this is nasty, create a proper interface here
/** @var OAuthToken&TokenInterface&\OAuth2\Model\IOAuth2AccessToken $accessToken */
/** @var AccessToken $accessToken */
$accessToken = $this->serverService->verifyAccessToken($tokenString);

$scope = $accessToken->getScope();
$user = $accessToken->getUser();
$client = $accessToken->getClient();

if (null !== $user) {
try {
Expand All @@ -81,6 +75,7 @@ public function authenticate(Request $request): PassportInterface
}

$roles = (null !== $user) ? $user->getRoles() : [];
$scope = $accessToken->getScope();

if (! empty($scope)) {
foreach (explode(' ', $scope) as $role) {
Expand All @@ -90,39 +85,30 @@ public function authenticate(Request $request): PassportInterface

$roles = array_unique($roles, SORT_REGULAR);

if (null !== $user) {
try {
$this->userChecker->checkPostAuth($user);
return new SelfValidatingPassport(new UserBadge($user->getUserIdentifier()));
} catch (AccountStatusException $e) {
throw new OAuth2AuthenticateException(
Response::HTTP_UNAUTHORIZED,
OAuth2::TOKEN_TYPE_BEARER,
$this->serverService->getVariable(OAuth2::CONFIG_WWW_REALM),
'access_denied',
$e->getMessage()
);
}
}
return new SelfValidatingPassport(new UserBadge($tokenString));
$accessTokenBadge = new AccessTokenBadge( $accessToken, $roles );

return new SelfValidatingPassport( new UserBadge( $client->getUserIdentifier() ), [ $accessTokenBadge ] );

This comment has been minimized.

Copy link
@ksiatka

ksiatka Jan 20, 2023

I belive here should be used $user->getUserIdentifier() which is username or email, and then the UserBadge can be resolved at the end with User entity. Instead $client->getUserIdentifier() returns randomId which doesn't have to represent the username/email but... randomId, and as a result at the end non user is found by the randomId.

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

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

public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
{
return parent::createAuthenticatedToken($passport, $firewallName); // TODO: Change the autogenerated stub
/** @var AccessTokenBadge $accessTokenBadge */
$accessTokenBadge = $passport->getBadge( AccessTokenBadge::class );
$token = new OAuthToken( $accessTokenBadge->getRoles() );
$token->setAuthenticated(true);
$token->setToken( $accessTokenBadge->getAccessToken()->getToken() );

return $token;
}

/**
* @inheritDoc
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
die('test');
return null;
}

Expand All @@ -131,8 +117,6 @@ public function onAuthenticationSuccess(Request $request, TokenInterface $token,
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception): ?Response
{
dump($exception);
die();
$data = [
// you may want to customize or obfuscate the message first
'message' => strtr($exception->getMessageKey(), $exception->getMessageData())
Expand Down
56 changes: 56 additions & 0 deletions Security/Authenticator/Passport/Badge/AccessTokenBadge.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php


namespace FOS\OAuthServerBundle\Security\Authenticator\Passport\Badge;


use FOS\OAuthServerBundle\Model\AccessToken;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\BadgeInterface;

class AccessTokenBadge implements BadgeInterface
{
/**
* @var AccessToken
*/
private $AccessToken;

/**
* @var array
*/
private $roles;

/**
* AccessTokenBadge constructor.
* @param AccessToken $AccessToken
* @param array $roles
*/
public function __construct( AccessToken $AccessToken, array $roles )
{
$this->AccessToken = $AccessToken;
$this->roles = $roles;
}

/**
* @inheritDoc
*/
public function isResolved(): bool
{
return ! empty ( $this->roles );
}

/**
* @return AccessToken
*/
public function getAccessToken(): AccessToken
{
return $this->AccessToken;
}

/**
* @return array
*/
public function getRoles(): array
{
return $this->roles;
}
}
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
],
"require": {
"php": "^7.2.5|^8.0",
"friendsofsymfony/oauth2-php": "~1.1",
"klapaudius/oauth2-php": "~1.4",
"symfony/dependency-injection": "~5.3",
"symfony/framework-bundle": "~5.3",
"symfony/security-bundle": "~5.3",
Expand Down

0 comments on commit 565d05f

Please sign in to comment.