Passed
Pull Request — master (#33)
by
unknown
10:49
created

IdTokenResponse::getBuilder()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 13
c 3
b 0
f 0
dl 0
loc 21
ccs 0
cts 14
cp 0
rs 9.8333
cc 3
nc 4
nop 2
crap 12
1
<?php
2
/**
3
 * @author Steve Rhoades <[email protected]>
4
 * @license http://opensource.org/licenses/MIT MIT
5
 */
6
7
namespace OpenIDConnectServer;
8
9
use DateTimeImmutable;
10
use Lcobucci\JWT\Configuration;
11
use Lcobucci\JWT\Signer\Key\InMemory;
12
use Lcobucci\JWT\Signer\Key\LocalFileReference;
13
use Lcobucci\JWT\Signer\Rsa\Sha256;
14
use Lcobucci\JWT\Token\Builder;
0 ignored issues
show
Bug introduced by
The type Lcobucci\JWT\Token\Builder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
16
use League\OAuth2\Server\Entities\ScopeEntityInterface;
17
use League\OAuth2\Server\Entities\UserEntityInterface;
18
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
19
use OpenIDConnectServer\Entities\ClaimSetInterface;
20
use OpenIDConnectServer\Repositories\IdentityProviderInterface;
21
22
class IdTokenResponse extends BearerTokenResponse
23
{
24
    /**
25
     * @var IdentityProviderInterface
26
     */
27
    protected $identityProvider;
28
29
    /**
30
     * @var ClaimExtractor
31
     */
32
    protected $claimExtractor;
33
34
    /**
35
     * @var Configuration
36
     */
37
    private $jwtConfiguration;
38
39
    /**
40
     * @var callable|null
41
     */
42
    private $tokenModifier = null;
43
44 1
    public function __construct(
45
        IdentityProviderInterface $identityProvider,
46
        ClaimExtractor $claimExtractor
47
    ) {
48 1
        $this->identityProvider = $identityProvider;
49 1
        $this->claimExtractor = $claimExtractor;
50 1
    }
51
52
    /**
53
     * Generate a JWT from the access token
54
     *
55
     * @return Token
0 ignored issues
show
Bug introduced by
The type OpenIDConnectServer\Token was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
56
     */
57
    private function getBuilder(AccessTokenEntityInterface $accessToken, UserEntityInterface $userEntity)
58
    {
59
        $this->initJwtConfiguration();
60
61
        $token = $this->jwtConfiguration->builder()
62
            ->permittedFor($accessToken->getClient()->getIdentifier())
63
            ->canOnlyBeUsedAfter(new DateTimeImmutable())
64
            ->issuedAt(new DateTimeImmutable())
65
            ->expiresAt($accessToken->getExpiryDateTime())
66
            ->issuedBy('https://' . $_SERVER['HTTP_HOST'])
67
            ->relatedTo((string) $userEntity->getIdentifier());
68
69
        if (null !== ($modifier = $this->getIdTokenModifier())) {
70
            $token = call_user_func($modifier, $token);
71
        }
72
73
        if ($token instanceof Builder === false) {
74
            throw new \RuntimeException('The id token modifier must return an instance of Lcobucci\JWT\Builder');
75
        }
76
77
        return $token;
78
    }
79
80
    /**
81
     * @param AccessTokenEntityInterface $accessToken
82
     * @return array
83
     */
84
    protected function getExtraParams(AccessTokenEntityInterface $accessToken)
85
    {
86
        if (false === $this->isOpenIDRequest($accessToken->getScopes())) {
87
            return [];
88
        }
89
90
        /** @var UserEntityInterface $userEntity */
91
        $userEntity = $this->identityProvider->getUserEntityByIdentifier($accessToken->getUserIdentifier());
92
93
        if (false === is_a($userEntity, UserEntityInterface::class)) {
94
            throw new \RuntimeException('UserEntity must implement UserEntityInterface');
95
        } elseif (false === is_a($userEntity, ClaimSetInterface::class)) {
96
            throw new \RuntimeException('UserEntity must implement ClaimSetInterface');
97
        }
98
99
        // Add required id_token claims
100
        $builder = $this->getBuilder($accessToken, $userEntity);
101
102
        // Need a claim factory here to reduce the number of claims by provided scope.
103
        $claims = $this->claimExtractor->extract($accessToken->getScopes(), $userEntity->getClaims());
0 ignored issues
show
Bug introduced by
The method getClaims() does not exist on League\OAuth2\Server\Entities\UserEntityInterface. It seems like you code against a sub-type of League\OAuth2\Server\Entities\UserEntityInterface such as OpenIDConnectServer\Test\Stubs\UserEntity. ( Ignorable by Annotation )

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

103
        $claims = $this->claimExtractor->extract($accessToken->getScopes(), $userEntity->/** @scrutinizer ignore-call */ getClaims());
Loading history...
104
105
        foreach ($claims as $claimName => $claimValue) {
106
            $builder = $builder->withClaim($claimName, $claimValue);
107
        }
108
109
        $token = $builder->getToken($this->jwtConfiguration->signer(), $this->jwtConfiguration->signingKey());
110
111
        return [
112
            'id_token' => $token->toString()
113
        ];
114
    }
115
116
    /**
117
     * @param ScopeEntityInterface[] $scopes
118
     * @return bool
119
     */
120
    private function isOpenIDRequest($scopes)
121
    {
122
        // Verify scope and make sure openid exists.
123
        $valid = false;
124
125
        foreach ($scopes as $scope) {
126
            if ($scope->getIdentifier() === 'openid') {
127
                $valid = true;
128
                break;
129
            }
130
        }
131
132
        return $valid;
133
    }
134
135
    /**
136
     * @see League\OAuth2\Server\Entities\Traits\AccessTokenTrait
137
     */
138
    private function initJwtConfiguration()
139
    {
140
        $this->jwtConfiguration = Configuration::forAsymmetricSigner(
141
            new Sha256(),
142
            LocalFileReference::file($this->privateKey->getKeyPath(), $this->privateKey->getPassPhrase() ?? ''),
143
            InMemory::plainText('')
144
        );
145
    }
146
147
    /**
148
     * @return callable|null
149
     */
150
    public function getIdTokenModifier()
151
    {
152
        return $this->tokenModifier;
153
    }
154
155
    /**
156
     * @param callable $tokenModifier
157
     */
158
    public function setIdTokenModifier(callable $tokenModifier)
159
    {
160
        $this->tokenModifier = $tokenModifier;
161
    }
162
}
163