IdTokenManager   A
last analyzed

Complexity

Total Complexity 16

Size/Duplication

Total Lines 120
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 120
rs 10
c 0
b 0
f 0
wmc 16

6 Methods

Rating   Name   Duplication   Size   Complexity  
B issueIdToken() 0 68 8
A getCodeHash() 0 3 1
A getHash() 0 19 4
A getAccessTokenHash() 0 3 1
A __construct() 0 3 1
A decode() 0 5 1
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: Alexandre
5
 * Date: 14/03/2018
6
 * Time: 21:48
7
 */
8
9
namespace OAuth2\Extensions\OpenID;
10
11
use Jose\Component\Core\JWKSet;
12
use Jose\Component\KeyManagement\JWKFactory;
13
use OAuth2\Credentials\AccessTokenInterface;
14
use OAuth2\Extensions\OpenID\Credentials\AuthorizationCodeInterface;
15
use OAuth2\Extensions\OpenID\Roles\Clients\ClientMetadataInterface;
16
use OAuth2\Helper;
17
use OAuth2\IdToken;
18
use OAuth2\IdTokenInterface;
19
use OAuth2\Roles\ClientInterface;
20
use OAuth2\Roles\ClientTypes\RegisteredClient;
21
22
23
class IdTokenManager
24
{
25
    const KEY = 'AZE'; // Keys storage ? manager ?
26
27
    /**
28
     * @var Config
29
     */
30
    private $config;
31
32
    public function __construct(Config $config)
33
    {
34
        $this->config = $config;
35
    }
36
37
    public function decode(string $idToken): IdTokenInterface
38
    {
39
        $claims = $this->jwt->decode($idToken, self::KEY, 'HS256');
0 ignored issues
show
Bug Best Practice introduced by
The property jwt does not exist on OAuth2\Extensions\OpenID\IdTokenManager. Did you maybe forget to declare it?
Loading history...
40
        $idToken = new IdToken((array)$claims);
41
        return $idToken;
42
    }
43
44
    public function issueIdToken(RegisteredClient $client,
45
                                 string $resourceOwnerIdentifier,
46
                                 array $additionalClaims = []): string
47
    {
48
        $metadata = $client->getMetadata();
49
50
        $idToken = array_merge([
51
            'iss' => $this->config->getIssuerIdentifier(),
52
            'sub' => $resourceOwnerIdentifier,
53
            'aud' => $client->getIdentifier(),
54
            'exp' => time() + $this->config->getIdTokenLifetime(),
55
            'iat' => time()
56
        ], $additionalClaims);
57
58
        $alg = 'RS256';
59
        if ($metadata instanceof ClientMetadataInterface) {
60
            $alg = $metadata->getIdTokenSignedResponseAlg() ?: 'RS256';
61
        }
62
63
        $keys=[];
64
        $jwks = $metadata->getJwks();
65
66
        if (!empty($jwks)) {
67
            $jwks = JWKFactory::createFromValues($jwks);
68
            if ($jwks instanceof JWKSet) {
69
                foreach ($jwks->all() as $key) {
70
                    $keys[] = $key;
71
                }
72
            } else {
73
                $keys[] = $jwks;
74
            }
75
        }
76
77
        $jwku = $metadata->getJwksUri();
78
        if (!is_null($jwku)) {
79
            foreach (JWKFactory::createFromJKU($jwku) as $key) {
0 ignored issues
show
Bug introduced by
The method createFromJKU() does not exist on Jose\Component\KeyManagement\JWKFactory. Did you maybe mean createFromKey()? ( Ignorable by Annotation )

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

79
            foreach (JWKFactory::/** @scrutinizer ignore-call */ createFromJKU($jwku) as $key) {

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...
80
                $keys[] = $key;
81
            }
82
        }
83
        $jwkSet = new JWKSet($keys);
84
85
        $key = $jwkSet->selectKey('sig', $alg);
0 ignored issues
show
Bug introduced by
$alg of type string is incompatible with the type null|Jose\Component\Core\Algorithm expected by parameter $algorithm of Jose\Component\Core\JWKSet::selectKey(). ( Ignorable by Annotation )

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

85
        $key = $jwkSet->selectKey('sig', /** @scrutinizer ignore-type */ $alg);
Loading history...
86
87
88
//var_dump($idToken);die;
0 ignored issues
show
Unused Code Comprehensibility introduced by
86% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
89
        $jws = JWSFactory::createJWS($idToken);
0 ignored issues
show
Bug introduced by
The type OAuth2\Extensions\OpenID\JWSFactory 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...
90
        $jws = $jws->addSignatureInformation($key,
91
            [
92
                'alg' => $alg,
93
                'kid' => $key->get('kid')
94
            ]
95
        );
96
        $signer = Signer::createSigner([$alg]);
0 ignored issues
show
Bug introduced by
The type OAuth2\Extensions\OpenID\Signer 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...
97
98
        // Then we sign
99
        $signer->sign($jws);
100
101
//        var_dump($jws->toCompactJSON(0));die;
0 ignored issues
show
Unused Code Comprehensibility introduced by
66% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
102
//        echo '<pre>';
103
//        print_r($jws->getClaims());
104
//        print_r($jws->toCompactJSON(0));
105
//        echo '</pre>';die;
106
107
//        var_dump($jws->toJSON());
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
108
//        die;
109
//        $idToken = JWT::encode($idToken, $key, $alg);
110
111
        return $jws->toCompactJSON(0);
112
    }
113
114
    public function getCodeHash(ClientInterface $client, AuthorizationCodeInterface $authorizationCode)
115
    {
116
        return $this->getHash($client, $authorizationCode->getCode());
117
    }
118
119
    public function getAccessTokenHash(ClientInterface $client, AccessTokenInterface $accessToken)
120
    {
121
        return $this->getHash($client, $accessToken->getToken());
122
    }
123
124
    public function getHash(ClientInterface $client, $target)
125
    {
126
        $alg = 'RS256';
127
        $metadata = $client->getMetadata();
128
        if ($metadata instanceof ClientMetadataInterface) {
129
            $alg = $metadata->getIdTokenSignedResponseAlg() ?: 'RS256';
130
        }
131
132
        $macAlgorithm = substr($alg, -3);
133
134
        if (!in_array($macAlgorithm, [256, 384, 512])) {
135
            throw new \UnexpectedValueException('Client metadata Id token signed response alg value is unexpected. 
136
            It must end with "256", "384" or "513"');
137
        }
138
        $macAlgorithm = 'sha' . $macAlgorithm;
139
140
        $hash = hash($macAlgorithm, $target, true);
141
        $hash = substr($hash, 0, strlen($hash) / 2);
142
        return Helper::base64url_encode($hash);
143
    }
144
}