Passed
Pull Request — master (#1316)
by
unknown
33:27
created

IdTokenResponse   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 77
Duplicated Lines 0 %

Importance

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

3 Methods

Rating   Name   Duplication   Size   Complexity  
A isOpenIDRequest() 0 10 4
A getExtraParams() 0 39 5
A __construct() 0 7 2
1
<?php
2
3
namespace League\OAuth2\Server\ResponseTypes;
4
5
use Psr\Http\Message\ServerRequestInterface;
6
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
7
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
8
use Lcobucci\JWT\Token\Builder;
9
use Lcobucci\JWT\Signer\Rsa\Sha256;
10
use Lcobucci\JWT\Encoding\ChainedFormatter;
11
use Lcobucci\JWT\Encoding\JoseEncoder;
12
use Lcobucci\JWT\Signer\Key\InMemory;
13
use League\Event\EmitterAwareTrait;
14
use League\OAuth2\Server\ClaimExtractor;
15
use League\OAuth2\Server\Entities\ClaimSetInterface;
16
use League\OAuth2\Server\Entities\ScopeEntityInterface;
17
use League\OAuth2\Server\IdTokenClaimsCreated;
18
use League\OAuth2\Server\IdTokenIssued;
19
use League\OAuth2\Server\Repositories\ClaimSetRepositoryInterface;
20
use League\OAuth2\Server\RequestEvent;
21
22
/**
23
 * OpenidConfigurationResponse
24
 * 
25
 * @link https://github.com/steverhoades/oauth2-openid-connect-server
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
        if(!$extractor) {
39
            $this->extractor = new ClaimExtractor();
40
        }
41
    }
42
43
    /**
44
     * @param AccessTokenEntityInterface $accessToken
45
     * @return array
46
     */
47
    protected function getExtraParams(AccessTokenEntityInterface $accessToken): array
48
    {
49
        // Onyly add id_token to openid scopes
50
        if (!self::isOpenIDRequest($accessToken->getScopes())) {
51
            return [];
52
        }
53
54
        $claimSet = $this->claimRepository->getClaimSetEntry($accessToken);
55
56
        $builder = (new Builder(new JoseEncoder(), ChainedFormatter::withUnixTimestampDates()))
57
            ->permittedFor($accessToken->getClient()->getIdentifier())
58
            ->issuedBy(sprintf("%s://%s", 
59
                $this->request->getUri()->getScheme(), $this->request->getUri()->getHost()))
60
            ->issuedAt(new \DateTimeImmutable())
61
            ->expiresAt($accessToken->getExpiryDateTime())
62
            ->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

62
            ->relatedTo(/** @scrutinizer ignore-type */ $accessToken->getUserIdentifier());
Loading history...
63
64
        if ($claimSet instanceof ClaimSetInterface) {
0 ignored issues
show
introduced by
$claimSet is always a sub-type of League\OAuth2\Server\Entities\ClaimSetInterface.
Loading history...
65
            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

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