Passed
Push — master ( e88490...575397 )
by Alexandre
04:15
created

IdTokenManager::issueIdToken()   C

Complexity

Conditions 8
Paths 12

Size

Total Lines 67
Code Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 67
rs 6.6523
c 0
b 0
f 0
cc 8
eloc 32
nc 12
nop 3

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
12
use Firebase\JWT\JWT;
13
use Jose\Factory\JWKFactory;
14
use Jose\Factory\JWSFactory;
15
use Jose\Object\JWKSet;
16
use Jose\Signer;
17
use OAuth2\Credentials\AccessTokenInterface;
18
use OAuth2\Extensions\OpenID\Credentials\AuthorizationCodeInterface;
19
use OAuth2\Extensions\OpenID\Roles\Clients\ClientMetadataInterface;
20
use OAuth2\Helper;
21
use OAuth2\IdToken;
22
use OAuth2\IdTokenInterface;
23
use OAuth2\Roles\ClientInterface;
24
use OAuth2\Roles\ResourceOwnerInterface;
25
26
class IdTokenManager
27
{
28
    const KEY = 'AZE'; // Keys storage ? manager ?
29
30
    /**
31
     * @var JWT
32
     */
33
    private $jwt;
34
    /**
35
     * @var Config
36
     */
37
    private $config;
38
39
    public function __construct(Config $config, JWT $jwt)
40
    {
41
        $this->jwt = $jwt;
42
        $this->config = $config;
43
    }
44
45
    public function decode(string $idToken): IdTokenInterface
46
    {
47
        $claims = $this->jwt->decode($idToken, self::KEY, 'HS256');
0 ignored issues
show
Bug introduced by
'HS256' of type string is incompatible with the type array expected by parameter $allowed_algs of Firebase\JWT\JWT::decode(). ( Ignorable by Annotation )

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

47
        $claims = $this->jwt->decode($idToken, self::KEY, /** @scrutinizer ignore-type */ 'HS256');
Loading history...
48
        $idToken = new IdToken((array)$claims);
49
        return $idToken;
50
    }
51
52
    public function issueIdToken(ClientInterface $client,
53
                                 ResourceOwnerInterface $resourceOwner,
54
                                 array $additionalClaims = []): string
55
    {
56
        $metadata = $client->getMetadata();
57
58
        $idToken = array_merge([
59
            'iss' => $this->config->getIssuerIdentifier(),
60
            'sub' => $resourceOwner->getIdentifier(),
61
            'aud' => $client->getIdentifier(),
62
            'exp' => time() + $this->config->getIdTokenLifetime(),
63
            'iat' => time()
64
        ], $additionalClaims);
65
66
        $alg = 'RS256';
67
        if ($metadata instanceof ClientMetadataInterface) {
68
            $alg = $metadata->getIdTokenSignedResponseAlg() ?: 'RS256';
69
        }
70
71
        $jwkSet = new JWKSet();
72
        $jwks = $metadata->getJwks();
73
74
        if (!empty($jwks)) {
75
            $jwks = JWKFactory::createFromValues($jwks);
76
            if ($jwks instanceof JWKSet) {
77
                foreach ($jwks->getKeys() as $key) {
78
                    $jwkSet->addKey($key);
79
                }
80
            } else {
81
                $jwkSet->addKey($jwks);
82
            }
83
        }
84
85
        $jwku = $metadata->getJwksUri();
86
        if (!is_null($jwku)) {
87
            foreach (JWKFactory::createFromJKU($jwku) as $key) {
88
                $jwkSet->addKey($key);
89
            }
90
        }
91
92
        $key = $jwkSet->selectKey('sig', $alg);
93
94
95
//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...
96
        $jws = JWSFactory::createJWS($idToken);
97
        $jws = $jws->addSignatureInformation($key,
98
            [
99
                'alg' => $alg,
100
                'kid' => $key->get('kid')
101
            ]
102
        );
103
        $signer = Signer::createSigner([$alg]);
104
105
        // Then we sign
106
        $signer->sign($jws);
107
108
//        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...
109
//        echo '<pre>';
110
//        print_r($jws->getClaims());
111
//        print_r($jws->toCompactJSON(0));
112
//        echo '</pre>';die;
113
114
//        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...
115
//        die;
116
//        $idToken = JWT::encode($idToken, $key, $alg);
117
118
        return $jws->toCompactJSON(0);
119
    }
120
121
    public function getCodeHash(ClientInterface $client, AuthorizationCodeInterface $authorizationCode)
122
    {
123
        return $this->getHash($client, $authorizationCode->getCode());
124
    }
125
126
    public function getAccessTokenHash(ClientInterface $client, AccessTokenInterface $accessToken)
127
    {
128
        return $this->getHash($client, $accessToken->getToken());
129
    }
130
131
    public function getHash(ClientInterface $client, $target)
132
    {
133
        $alg = 'RS256';
134
        $metadata = $client->getMetadata();
135
        if ($metadata instanceof ClientMetadataInterface) {
136
            $alg = $metadata->getIdTokenSignedResponseAlg() ?: 'RS256';
137
        }
138
139
        $macAlgorithm = substr($alg, -3);
140
141
        if (!in_array($macAlgorithm, [256, 384, 512])) {
142
            throw new \UnexpectedValueException('Client metadata Id token signed response alg value is unexpected. 
143
            It must end with "256", "384" or "513"');
144
        }
145
        $macAlgorithm = 'sha' . $macAlgorithm;
146
147
        $hash = hash($macAlgorithm, $target, true);
148
        $hash = substr($hash, 0, strlen($hash) / 2);
149
        return Helper::base64url_encode($hash);
150
    }
151
}