Completed
Push — develop ( a4838f...d9bf78 )
by Abdelrahman
01:37
created

RefreshTokenGrant::respondToAccessTokenRequest()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 41
rs 9.264
c 0
b 0
f 0
cc 4
nc 5
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Rinvex\OAuth\Grants;
6
7
use DateInterval;
8
use League\OAuth2\Server\RequestEvent;
9
use Psr\Http\Message\ServerRequestInterface;
10
use League\OAuth2\Server\Exception\OAuthServerException;
11
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface;
12
use League\OAuth2\Server\Grant\RefreshTokenGrant as BaseRefreshTokenGrant;
13
14
class RefreshTokenGrant extends BaseRefreshTokenGrant
15
{
16
    /**
17
     * Respond to an access token request.
18
     *
19
     * @param ServerRequestInterface $request
20
     * @param ResponseTypeInterface  $responseType
21
     * @param DateInterval           $accessTokenTTL
22
     *
23
     * @throws OAuthServerException
24
     *
25
     * @return ResponseTypeInterface
26
     */
27
    public function respondToAccessTokenRequest(ServerRequestInterface $request, ResponseTypeInterface $responseType, DateInterval $accessTokenTTL)
28
    {
29
        // Validate request
30
        $client = $this->validateClient($request);
31
        $oldRefreshToken = $this->validateOldRefreshToken($request, $client->getIdentifier());
32
        $this->validateUser($oldRefreshToken);
33
        $scopes = $this->validateScopes(
34
            $this->getRequestParameter(
35
                'scope',
36
                $request,
37
                implode(self::SCOPE_DELIMITER_STRING, $oldRefreshToken['scopes'])
38
            )
39
        );
40
41
        // The OAuth spec says that a refreshed access token can have the original scopes or fewer so ensure
42
        // the request doesn't include any new scopes
43
        foreach ($scopes as $scope) {
44
            if (in_array($scope->getIdentifier(), $oldRefreshToken['scopes'], true) === false) {
45
                throw OAuthServerException::invalidScope($scope->getIdentifier());
46
            }
47
        }
48
49
        // Expire old tokens
50
        $this->accessTokenRepository->revokeAccessToken($oldRefreshToken['access_token_id']);
51
        $this->refreshTokenRepository->revokeRefreshToken($oldRefreshToken['refresh_token_id']);
52
53
        // Issue and persist new access token
54
        $accessToken = $this->issueAccessToken($accessTokenTTL, $client, $oldRefreshToken['user_id'], $scopes);
55
        $this->getEmitter()->emit(new RequestEvent(RequestEvent::ACCESS_TOKEN_ISSUED, $request));
56
        $responseType->setAccessToken($accessToken);
0 ignored issues
show
Bug introduced by
It seems like $accessToken defined by $this->issueAccessToken(...en['user_id'], $scopes) on line 54 can be null; however, League\OAuth2\Server\Res...rface::setAccessToken() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
57
58
        // Issue and persist new refresh token if given
59
        $refreshToken = $this->issueRefreshToken($accessToken);
0 ignored issues
show
Bug introduced by
It seems like $accessToken defined by $this->issueAccessToken(...en['user_id'], $scopes) on line 54 can be null; however, League\OAuth2\Server\Gra...nt::issueRefreshToken() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
60
61
        if ($refreshToken !== null) {
62
            $this->getEmitter()->emit(new RequestEvent(RequestEvent::REFRESH_TOKEN_ISSUED, $request));
63
            $responseType->setRefreshToken($refreshToken);
64
        }
65
66
        return $responseType;
67
    }
68
69
    /**
70
     * Validate the authorization code user.
71
     *
72
     * @param array $oldRefreshToken
73
     *
74
     * @throws \League\OAuth2\Server\Exception\OAuthServerException
75
     */
76
    protected function validateUser($oldRefreshToken)
77
    {
78
        [$userType, $userId] = explode(':', $oldRefreshToken['user_id']);
0 ignored issues
show
Bug introduced by
The variable $userType does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
Bug introduced by
The variable $userId does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
79
80
        if ($userType !== request()->user()->getMorphClass() || $userId !== request()->user()->getRouteKey()) {
81
            throw OAuthServerException::invalidRequest('user_id', 'Refresh token was not issued to this user');
82
        }
83
    }
84
}
85