Skip to content

Commit

Permalink
fix: Reuse original token state instead of force authenticated
Browse files Browse the repository at this point in the history
  • Loading branch information
Nattfarinn committed Sep 18, 2023
1 parent 936d287 commit 71dee3d
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ public function onInteractiveLogin(BaseInteractiveLoginEvent $event)
$providerKey,
$token->getRoleNames()
);
$interactiveToken->setToken($token);
$interactiveToken->setAttributes($token->getAttributes());
$this->tokenStorage->setToken($interactiveToken);
}
Expand Down
63 changes: 45 additions & 18 deletions src/lib/MVC/Symfony/Security/InteractiveLoginToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,52 +6,79 @@
*/
namespace Ibexa\Core\MVC\Symfony\Security;

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;

/**
* This token is used when a user has been matched by a foreign user provider.
* It is injected in SecurityContext to replace the original token as this one holds a new user.
*/
class InteractiveLoginToken extends UsernamePasswordToken
{
/** @var string */
private $originalTokenType;
private ?TokenInterface $originalToken = null;

private string $originalTokenType;

public function __construct(UserInterface $user, $originalTokenType, $credentials, $providerKey, array $roles = [])
{
parent::__construct($user, $credentials, $providerKey, $roles);

$this->originalTokenType = $originalTokenType;
}

/**
* @return string
*/
public function getOriginalTokenType()
public function getOriginalTokenType(): string
{
return $this->originalTokenType;
}

/**
* @return array{
* 0: string,
* 1: mixed,
* 2: null|\Symfony\Component\Security\Core\Authentication\Token\TokenInterface
* } $data
*/
public function __serialize(): array
{
return [$this->originalTokenType, parent::__serialize()];
return [
$this->originalTokenType,
parent::__serialize(),
$this->originalToken,
];
}

/**
* @param array{
* 0: string,
* 1: mixed,
* 2?: \Symfony\Component\Security\Core\Authentication\Token\TokenInterface
* } $data
*/
public function __unserialize(array $data): void
{
if (count($data) < 3) {
[$this->originalTokenType, $parentData] = $data;
} else {
[$this->originalTokenType, $parentData, $this->originalToken] = $data;
}

parent::__unserialize($parentData);
}

public function setToken(TokenInterface $token): void
{
$this->originalToken = $token;
}

public function __unserialize($serialized): void
public function getOriginalToken(): TokenInterface
{
[$this->originalTokenType, $parentStr] = $serialized;
parent::__unserialize($parentStr);
return $this->originalToken;
}

public function isAuthenticated(): bool
{
if (PostAuthenticationGuardToken::class === $this->originalTokenType) {
/**
* This token is meant to be used after authentication success, so it is always authenticated
*
* @see https://github.com/symfony/security-guard/blob/72c53142533462fc6fda4a429c2a21c2b944a8cc/Token/PostAuthenticationGuardToken.php#L50-L51
*/
return true;
if ($this->originalToken instanceof TokenInterface) {
return $this->originalToken->isAuthenticated();
}

return parent::isAuthenticated();
Expand Down

0 comments on commit 71dee3d

Please sign in to comment.