oauth2-bundle icon indicating copy to clipboard operation
oauth2-bundle copied to clipboard

[Question] Is it possible to issue tokens programmatically?

Open Stefanobosio opened this issue 5 years ago • 4 comments

I need to generate a new token inside a custom Authenticator without passing throught the /oauth2/token endpoint, but something more like I do in custome grants with the issueToken() method.

Is there something I can use inside an autenticator to return a new JWT given an user and a client ID?

Thank you

Stefanobosio avatar Mar 31 '21 11:03 Stefanobosio

Hi, you can see how the token is created here: \League\OAuth2\Server\Grant\PasswordGrant::respondToAccessTokenRequest, maybe this will help you

ostiwe avatar Aug 28 '21 12:08 ostiwe

Hello Ostiwe, thank you. I already found that method and I'm using that both in Grant Flows and in Controllers. What I don't like with this approach is that respondToAccessTokenRequest depends on ServerRequestInterface $request, while I was hoping to create the JWT programmatically without depending on the request (even because getting a Request as incoming parameter in order to create a signed JWT makes no sense to me).

Stefanobosio avatar Sep 04 '21 12:09 Stefanobosio

Yep, it's a pity that there is no way to simply create a token, without unnecessary dependencies

ostiwe avatar Sep 04 '21 12:09 ostiwe

I did this today, not with this bundle but with the League and League bundle for symfony but I'll drop my class here just in case it helps.

<?php

namespace App\Entity;


use DateInterval;
use DateTimeImmutable;
use League\Bundle\OAuth2ServerBundle\Entity\Scope;
use League\OAuth2\Server\Entities\ClientEntityInterface;
use League\OAuth2\Server\Exception\UniqueTokenIdentifierConstraintViolationException;
use League\OAuth2\Server\Grant\AuthCodeGrant;

class FakeToken extends AuthCodeGrant
{
    public $accessTokenRepository;
    public $privateKey;
    private $scope;
    private $authCodeTTL;
    private $userIdentifer;
    private ClientEntityInterface $client;

    /**
     * @param $accessTokenRepository
     * @param $privateKey
     */
    public function __construct(
        ClientEntityInterface $client,
        DateInterval $authCodeTTL,
        $accessTokenRepository,
        $privateKey,
        $userIdentifer,
        $scope,
    ) {
        $this->client = $client;
        $this->accessTokenRepository = $accessTokenRepository;
        $this->privateKey = $privateKey;
        $myScope = (new Scope());
        $myScope->setIdentifier($scope);
        $this->scope = $myScope;
        $this->authCodeTTL = $authCodeTTL;
        $this->userIdentifer = $userIdentifer;
    }

    public function issueMyAccessToken(
    ) {
        $maxGenerationAttempts = self::MAX_RANDOM_TOKEN_GENERATION_ATTEMPTS;

        $accessToken = $this->accessTokenRepository->getNewToken($this->client, [$this->scope], $this->userIdentifer);
        $accessToken->setExpiryDateTime((new DateTimeImmutable())->add($this->authCodeTTL));
        $accessToken->setPrivateKey($this->privateKey);

        while ($maxGenerationAttempts-- > 0) {
            $accessToken->setIdentifier($this->generateUniqueIdentifier());
            try {
                $this->accessTokenRepository->persistNewAccessToken($accessToken);

                return $accessToken;
            } catch (UniqueTokenIdentifierConstraintViolationException $e) {
                if ($maxGenerationAttempts === 0) {
                    throw $e;
                }
            }
        }
    }
}

and then I call it with

$key = str_replace('%kernel.project_dir%', $kernel->getProjectDir(), $_ENV['OAUTH_PRIVATE_KEY']);
 $g = (new FakeToken(
            $clientRepository->getClientEntity('YOUR CLIENT ID'),
            new DateInterval('P1M'),
            $accessTokenRepository,
            new CryptKey($key, $_ENV['OAUTH_PASSPHRASE']),
            'YOUR USER IDENTIFIER',
            'YOUR SCOPE',
        ))->issueMyAccessToken();

result was a token, which when cast to a string gives you a useable token ScreenShot-2023-08-06-12 01 49

PhilETaylor avatar Aug 06 '23 11:08 PhilETaylor