Passed
Pull Request — master (#1316)
by
unknown
62:36 queued 27:34
created

IdTokenResponse   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 87
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 35
c 2
b 0
f 0
dl 0
loc 87
rs 10
wmc 11

3 Methods

Rating   Name   Duplication   Size   Complexity  
A isOpenIDRequest() 0 11 4
A getExtraParams() 0 46 5
A __construct() 0 8 2
1
<?php
2
3
namespace League\OAuth2\Server\ResponseTypes;
4
5
use Lcobucci\JWT\Encoding\ChainedFormatter;
6
use Lcobucci\JWT\Encoding\JoseEncoder;
7
use Lcobucci\JWT\Signer\Key\InMemory;
8
use Lcobucci\JWT\Signer\Rsa\Sha256;
9
use Lcobucci\JWT\Token\Builder;
10
use League\Event\EmitterAwareTrait;
11
use League\OAuth2\Server\ClaimExtractor;
12
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
13
use League\OAuth2\Server\Entities\ClaimSetInterface;
14
use League\OAuth2\Server\Entities\ScopeEntityInterface;
15
use League\OAuth2\Server\IdTokenClaimsCreated;
16
use League\OAuth2\Server\IdTokenIssued;
17
use League\OAuth2\Server\Repositories\ClaimSetRepositoryInterface;
18
use League\OAuth2\Server\RequestEvent;
19
use Psr\Http\Message\ServerRequestInterface;
20
21
/**
22
 * OpenidConfigurationResponse
23
 *
24
 * @link https://github.com/steverhoades/oauth2-openid-connect-server
25
 *
26
 * @author Steve Rhoades <[email protected]>
27
 * @author Marc Riemer <[email protected]>
28
 */
29
class IdTokenResponse extends BearerTokenResponse
30
{
31
    use EmitterAwareTrait;
32
33
    public function __construct(
34
        protected ServerRequestInterface $request,
35
        protected ClaimSetRepositoryInterface $claimRepository,
36
        protected ?ClaimExtractor $extractor = null
37
    )
38
    {
39
        if (!$extractor) {
40
            $this->extractor = new ClaimExtractor();
41
        }
42
    }
43
44
    /**
45
     * @param AccessTokenEntityInterface $accessToken
46
     *
47
     * @return array
48
     */
49
    protected function getExtraParams(AccessTokenEntityInterface $accessToken): array
50
    {
51
        // Onyly add id_token to openid scopes
52
        if (!self::isOpenIDRequest($accessToken->getScopes())) {
53
            return [];
54
        }
55
56
        $claimSet = $this->claimRepository->getClaimSetEntry($accessToken);
57
58
        $builder = (new Builder(new JoseEncoder(), ChainedFormatter::withUnixTimestampDates()))
59
            ->permittedFor($accessToken->getClient()->getIdentifier())
60
            ->issuedBy(\sprintf(
61
                '%s://%s',
62
                $this->request->getUri()->getScheme(),
63
                $this->request->getUri()->getHost()
64
            ))
65
            ->issuedAt(new \DateTimeImmutable())
66
            ->expiresAt($accessToken->getExpiryDateTime())
67
            ->relatedTo($accessToken->getUserIdentifier());
0 ignored issues
show
Bug introduced by
It seems like $accessToken->getUserIdentifier() can also be of type null; however, parameter $subject of Lcobucci\JWT\Token\Builder::relatedTo() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

67
            ->relatedTo(/** @scrutinizer ignore-type */ $accessToken->getUserIdentifier());
Loading history...
68
69
        if ($claimSet instanceof ClaimSetInterface) {
0 ignored issues
show
introduced by
$claimSet is always a sub-type of League\OAuth2\Server\Entities\ClaimSetInterface.
Loading history...
70
            foreach ($this->extractor->extract($accessToken->getScopes(), $claimSet->getClaims()) as $claimName => $claimValue) {
0 ignored issues
show
Bug introduced by
The method extract() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

70
            foreach ($this->extractor->/** @scrutinizer ignore-call */ extract($accessToken->getScopes(), $claimSet->getClaims()) as $claimName => $claimValue) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
71
                $builder->withClaim($claimName, $claimValue);
72
            }
73
        }
74
75
        // https://openid.net/specs/openid-connect-core-1_0.html#NonceNotes
76
        if (\array_key_exists($nonce = 'nonce', $this->request->getParsedBody())) {
77
            $builder->withClaim($nonce, $this->request->getParsedBody()[$nonce]);
78
        }
79
80
        $this->getEmitter()->emit(
81
            new IdTokenClaimsCreated(RequestEvent::ID_TOKEN_CLAIMS_CREATED, $this->request, $builder)
82
        );
83
84
        $token = $builder->getToken(
85
            new Sha256(),
86
            InMemory::file($this->privateKey->getKeyPath(), (string) $this->privateKey->getPassPhrase())
87
        );
88
89
        $this->getEmitter()->emit(
90
            new IdTokenIssued(RequestEvent::ID_TOKEN_ISSUED, $this->request, $token)
91
        );
92
93
        return [
94
            'id_token' => $token->toString(),
95
        ];
96
    }
97
98
    /**
99
     * Return true If this is an OpenID request
100
     *
101
     * @param ScopeEntityInterface[] $scopes
102
     *
103
     * @return bool
104
     */
105
    private static function isOpenIDRequest($scopes): bool
106
    {
107
        foreach ($scopes as $scope) {
108
            if ($scope instanceof ScopeEntityInterface) {
109
                if ($scope->getIdentifier() === 'openid') {
110
                    return true;
111
                }
112
            }
113
        }
114
115
        return false;
116
    }
117
}
118