oauth2-azure
oauth2-azure copied to clipboard
Getting a resource owner fails with refreshed access token (missing data)
I need to implement access token refreshing in a Symfony project. While trying to retrieve the resource owner in passing the refreshed access token, an exception is raised from the Azure provider:
Argument 1 passed to TheNetworg\OAuth2\Client\Provider\Azure::createResourceOwner() must be of the type array, null given, called in /application/vendor/thenetworg/oauth2-azure/src/Provider/Azure.php on line 65
Here is the implementation done in an event subscriber:
namespace App\Security\Azure;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use TheNetworg\OAuth2\Client\Provider\Azure;
class ResponseSubscriber implements EventSubscriberInterface
{
/**
* @var \Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface
*/
private $tokenStorage;
/**
* @var \TheNetworg\OAuth2\Client\Provider\Azure
*/
private $azureProvider;
public function __construct(TokenStorageInterface $tokenStorage, Azure $azureProvider)
{
$this->tokenStorage = $tokenStorage;
$this->azureProvider = $azureProvider;
}
public static function getSubscribedEvents(): array
{
return [
KernelEvents::RESPONSE => [
['refreshOAuthToken'],
],
];
}
public function refreshOAuthToken(FilterResponseEvent $event): void
{
// ...
$user = $token->getUser(); // $token is retrieved from the $tokenStorage property
if ($user instanceof User) {
$currentAccessToken = $user->getAccessToken();
if (true === $currentAccessToken->hasExpired()) {
/** @var \TheNetworg\OAuth2\Client\Token\AccessToken $accessToken */
$accessToken = $this->azureProvider->getAccessToken(
'refresh_token', [
'refresh_token' => $currentAccessToken->getRefreshToken(),
]
);
$resourceOwner = $this->azureProvider->getResourceOwner($accessToken);
// ...
}
}
}
}
The new access token is not "hydrated" as the previous one. It lacks of the data which are expected in the provider:
public function getResourceOwner(\League\OAuth2\Client\Token\AccessToken $token)
{
$data = $token->getIdTokenClaims(); // <=== $data is null
return $this->createResourceOwner($data, $token);
}
Here's a screenshot of the access tokens (second dump shows the refreshed one which lacks of data):
It looks like a bug to me. But perhaps something is happening behind the hood I don't get?
Right, so the identity is only being obtained from the id_token, but not from access_token due to the way the AccessToken class is initiated... This is a good catch!
I think this will need a slight change, in how the id_token is passed into the AccessToken class - so that we can pass it externally in case of refresh...
Oh I see, thank you. Moving the logic defined in the constructor into a separate class may help. This would enable to pass the options array after class instantiation.
Hi how can this be solved: the issue with the access token being incomplete. i don't seem to get it to work