Passed
Push — master ( 898cc7...450add )
by Thomas Mauro
03:07
created

TokenDecrypter::__construct()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 3
cp 0
crap 6
rs 10
c 1
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace TMV\OpenIdClient\Token;
6
7
use Jose\Component\Core\AlgorithmManager;
8
use Jose\Component\Core\JWKSet;
9
use Jose\Component\Encryption\Compression\CompressionMethodManager;
10
use Jose\Component\Encryption\Compression\Deflate;
11
use Jose\Component\Encryption\JWEDecrypter;
12
use Jose\Component\Encryption\JWELoader;
13
use Jose\Component\Encryption\Serializer\CompactSerializer;
14
use Jose\Component\Encryption\Serializer\JWESerializerManager;
15
use function TMV\OpenIdClient\base64url_decode;
16
use TMV\OpenIdClient\ClientInterface;
17
use TMV\OpenIdClient\Exception\RuntimeException;
18
use function TMV\OpenIdClient\jose_secret_key;
19
20
class TokenDecrypter implements TokenDecrypterInterface
21
{
22
    /** @var AlgorithmManager */
23
    private $algorithmManager;
24
25
    /**
26
     * TokenDecrypter constructor.
27
     *
28
     * @param AlgorithmManager $algorithmManager
29
     */
30
    public function __construct(?AlgorithmManager $algorithmManager = null)
31
    {
32
        $this->algorithmManager = $algorithmManager ?: new AlgorithmManager([]);
33
    }
34
35
    public function decryptToken(ClientInterface $client, string $token, string $use = 'id_token'): string
36
    {
37
        $metadata = $client->getMetadata();
38
        $expectedAlg = $metadata->get($use . '_encrypted_response_alg');
39
        $expectedEnc = $metadata->get($use . '_encrypted_response_enc');
40
41
        if (! $expectedAlg) {
42
            return $token;
43
        }
44
45
        $header = \json_decode(base64url_decode(\explode('.', $token)[0] ?? '{}'), true);
46
47
        if ($expectedAlg !== ($header['alg'] ?? '')) {
48
            throw new RuntimeException(\sprintf('Unexpected JWE alg received, expected %s, got: %s', $expectedAlg, $header['alg'] ?? ''));
49
        }
50
51
        if ($expectedEnc !== ($header['enc'] ?? '')) {
52
            throw new RuntimeException(\sprintf('Unexpected JWE enc received, expected %s, got: %s', $expectedEnc, $header['enc'] ?? ''));
53
        }
54
55
        $serializer = new CompactSerializer();
56
        $jweLoader = new JWELoader(
57
            new JWESerializerManager([$serializer]),
58
            new JWEDecrypter($this->algorithmManager, $this->algorithmManager, new CompressionMethodManager([new Deflate()])),
59
            null
60
        );
61
62
        if (\preg_match('/^(?:RSA|ECDH)/', $expectedAlg)) {
63
            $jwks = $client->getJWKS();
64
        } else {
65
            $jwk = jose_secret_key($metadata->getClientSecret() ?: '', $expectedAlg === 'dir' ? $expectedEnc : $expectedAlg);
66
            $jwks = new JWKSet([$jwk]);
67
        }
68
69
        return $serializer->serialize($jweLoader->loadAndDecryptWithKeySet($token, $jwks, $recipient));
70
    }
71
}
72