Passed
Push — master ( 920042...c195a0 )
by Steve
07:10 queued 03:08
created

IdTokenResponse   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 96
Duplicated Lines 0 %

Test Coverage

Coverage 9.3%

Importance

Changes 5
Bugs 0 Features 1
Metric Value
wmc 11
eloc 39
c 5
b 0
f 1
dl 0
loc 96
ccs 4
cts 43
cp 0.093
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getBuilder() 0 18 2
A isOpenIDRequest() 0 13 3
A getExtraParams() 0 32 5
1
<?php
2
/**
3
 * @author Steve Rhoades <[email protected]>
4
 * @license http://opensource.org/licenses/MIT MIT
5
 */
6
namespace OpenIDConnectServer;
7
8
use Lcobucci\JWT\Signer\Key\LocalFileReference;
9
use OpenIDConnectServer\Repositories\IdentityProviderInterface;
10
use OpenIDConnectServer\Entities\ClaimSetInterface;
11
use League\OAuth2\Server\Entities\UserEntityInterface;
12
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
13
use League\OAuth2\Server\Entities\ScopeEntityInterface;
14
use League\OAuth2\Server\ResponseTypes\BearerTokenResponse;
15
use Lcobucci\JWT\Signer\Rsa\Sha256;
16
17
class IdTokenResponse extends BearerTokenResponse
18
{
19
    /**
20
     * @var IdentityProviderInterface
21
     */
22
    protected $identityProvider;
23
24
    /**
25
     * @var ClaimExtractor
26
     */
27
    protected $claimExtractor;
28
29 1
    public function __construct(
30
        IdentityProviderInterface $identityProvider,
31
        ClaimExtractor $claimExtractor
32
    ) {
33 1
        $this->identityProvider = $identityProvider;
34 1
        $this->claimExtractor   = $claimExtractor;
35 1
    }
36
37
    protected function getBuilder(AccessTokenEntityInterface $accessToken, UserEntityInterface $userEntity)
38
    {
39
        if (class_exists("Lcobucci\JWT\Token\Builder")) {
40
            $claimsFormatter = \Lcobucci\JWT\Encoding\ChainedFormatter::withUnixTimestampDates();
0 ignored issues
show
Bug introduced by
The type Lcobucci\JWT\Encoding\ChainedFormatter 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...
41
            $builder = new \Lcobucci\JWT\Token\Builder(new \Lcobucci\JWT\Encoding\JoseEncoder(), $claimsFormatter);
0 ignored issues
show
Bug introduced by
The type Lcobucci\JWT\Encoding\JoseEncoder 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...
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...
42
        } else {
43
            $builder = new \Lcobucci\JWT\Builder();
44
        }
45
46
        // Add required id_token claims
47
        $builder
48
            ->permittedFor($accessToken->getClient()->getIdentifier())
0 ignored issues
show
Bug introduced by
$accessToken->getClient()->getIdentifier() of type string is incompatible with the type Lcobucci\JWT\list expected by parameter $audiences of Lcobucci\JWT\Builder::permittedFor(). ( Ignorable by Annotation )

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

48
            ->permittedFor(/** @scrutinizer ignore-type */ $accessToken->getClient()->getIdentifier())
Loading history...
49
            ->issuedBy('https://' . $_SERVER['HTTP_HOST'])
50
            ->issuedAt(new \DateTimeImmutable())
51
            ->expiresAt($accessToken->getExpiryDateTime())
52
            ->relatedTo($userEntity->getIdentifier());
53
54
        return $builder;
55
    }
56
57
    /**
58
     * @param AccessTokenEntityInterface $accessToken
59
     * @return array
60
     */
61
    protected function getExtraParams(AccessTokenEntityInterface $accessToken)
62
    {
63
        if (false === $this->isOpenIDRequest($accessToken->getScopes())) {
64
            return [];
65
        }
66
67
        /** @var UserEntityInterface $userEntity */
68
        $userEntity = $this->identityProvider->getUserEntityByIdentifier($accessToken->getUserIdentifier());
69
70
        if (false === is_a($userEntity, UserEntityInterface::class)) {
71
            throw new \RuntimeException('UserEntity must implement UserEntityInterface');
72
        } else if (false === is_a($userEntity, ClaimSetInterface::class)) {
73
            throw new \RuntimeException('UserEntity must implement ClaimSetInterface');
74
        }
75
76
        // Add required id_token claims
77
        $builder = $this->getBuilder($accessToken, $userEntity);
78
79
        // Need a claim factory here to reduce the number of claims by provided scope.
80
        $claims = $this->claimExtractor->extract($accessToken->getScopes(), $userEntity->getClaims());
81
82
        foreach ($claims as $claimName => $claimValue) {
83
            $builder = $builder->withClaim($claimName, $claimValue);
84
        }
85
86
        $token = $builder->getToken(
87
            new Sha256(),
88
            LocalFileReference::file($this->privateKey->getKeyPath(), (string) $this->privateKey->getPassPhrase())
89
        );
90
91
        return [
92
            'id_token' => $token->toString()
93
        ];
94
    }
95
96
    /**
97
     * @param ScopeEntityInterface[] $scopes
98
     * @return bool
99
     */
100
    private function isOpenIDRequest($scopes)
101
    {
102
        // Verify scope and make sure openid exists.
103
        $valid  = false;
104
105
        foreach ($scopes as $scope) {
106
            if ($scope->getIdentifier() === 'openid') {
107
                $valid = true;
108
                break;
109
            }
110
        }
111
112
        return $valid;
113
    }
114
115
}
116