Failed Conditions
Push — v7 ( 318c5f...2b71c7 )
by Florent
03:43
created

src/JWTLoader.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2014-2016 Spomky-Labs
7
 *
8
 * This software may be modified and distributed under the terms
9
 * of the MIT license.  See the LICENSE file for details.
10
 */
11
12
namespace Jose;
13
14
use Assert\Assertion;
15
use Jose\Checker\CheckerManager;
16
use Jose\Object\JWEInterface;
17
use Jose\Object\JWKSetInterface;
18
use Jose\Object\JWSInterface;
19
use Jose\Object\JWTInterface;
20
21
final class JWTLoader
22
{
23
    /**
24
     * @var Loader
25
     */
26
    private $loader;
27
28
    /**
29
     * @var CheckerManager
30
     */
31
    private $checker_manager;
32
33
    /**
34
     * @var Decrypter|null
35
     */
36
    private $decrypter = null;
37
38
    /**
39
     * @var Verifier
40
     */
41
    private $verifier;
42
43
    /**
44
     * JWTLoader constructor.
45
     *
46
     * @param CheckerManager $checker_manager
47
     * @param Verifier       $verifier
48
     */
49
    public function __construct(CheckerManager $checker_manager, Verifier $verifier)
50
    {
51
        $this->checker_manager = $checker_manager;
52
        $this->verifier = $verifier;
53
        $this->loader = new Loader();
54
    }
55
56
    /**
57
     * @param Decrypter $decrypter
58
     */
59
    public function enableDecryptionSupport(Decrypter $decrypter)
60
    {
61
        $this->decrypter = $decrypter;
62
    }
63
64
    /**
65
     * @return string[]
66
     */
67
    public function getSupportedSignatureAlgorithms(): array
68
    {
69
        return $this->verifier->getSupportedSignatureAlgorithms();
70
    }
71
72
    /**
73
     * @return bool
74
     */
75
    public function isDecryptionSupportEnabled(): bool
76
    {
77
        return null !== $this->decrypter;
78
    }
79
80
    /**
81
     * @return string[]
82
     */
83
    public function getSupportedKeyEncryptionAlgorithms(): array
84
    {
85
        return false === $this->isDecryptionSupportEnabled() ? [] : $this->decrypter->getSupportedKeyEncryptionAlgorithms();
86
    }
87
88
    /**
89
     * @return string[]
90
     */
91
    public function getSupportedContentEncryptionAlgorithms(): array
92
    {
93
        return false === $this->isDecryptionSupportEnabled() ? [] : $this->decrypter->getSupportedContentEncryptionAlgorithms();
94
    }
95
96
    /**
97
     * @return string[]
98
     */
99
    public function getSupportedCompressionMethods(): array
100
    {
101
        return false === $this->isDecryptionSupportEnabled() ? [] : $this->decrypter->getSupportedCompressionMethods();
102
    }
103
104
    /**
105
     * @param string               $assertion
106
     * @param JWKSetInterface|null $encryption_key_set
107
     * @param bool                 $is_encryption_required
108
     *
109
     * @return JWTInterface
110
     */
111
    public function load(string $assertion, ?JWKSetInterface $encryption_key_set = null, bool $is_encryption_required = false): JWTInterface
112
    {
113
        Assertion::string($assertion);
114
        Assertion::boolean($is_encryption_required);
115
        $jwt = $this->loader->load($assertion);
116
        if ($jwt instanceof JWEInterface) {
117
            Assertion::notNull($encryption_key_set, 'Encryption key set is not available.');
118
            Assertion::true($this->isDecryptionSupportEnabled(), 'Encryption support is not enabled.');
119
            Assertion::inArray($jwt->getSharedProtectedHeader('alg'), $this->getSupportedKeyEncryptionAlgorithms(), sprintf('The key encryption algorithm "%s" is not allowed.', $jwt->getSharedProtectedHeader('alg')));
120
            Assertion::inArray($jwt->getSharedProtectedHeader('enc'), $this->getSupportedContentEncryptionAlgorithms(), sprintf('The content encryption algorithm "%s" is not allowed or not supported.', $jwt->getSharedProtectedHeader('enc')));
121
            $jwt = $this->decryptAssertion($jwt, $encryption_key_set);
122
        } elseif (true === $is_encryption_required) {
123
            throw new \InvalidArgumentException('The assertion must be encrypted.');
124
        }
125
126
        return $jwt;
127
    }
128
129
    /**
130
     * @param JWSInterface    $jws
131
     * @param JWKSetInterface $signature_key_set
132
     * @param string|null     $detached_payload
133
     *
134
     * @return int
135
     */
136
    public function verify(JWSInterface $jws, JWKSetInterface $signature_key_set, ?string $detached_payload = null): int
137
    {
138
        Assertion::inArray($jws->getSignature(0)->getProtectedHeader('alg'), $this->getSupportedSignatureAlgorithms(), sprintf('The signature algorithm "%s" is not supported or not allowed.', $jws->getSignature(0)->getProtectedHeader('alg')));
139
140
        $index = null;
141
        $this->verifier->verifyWithKeySet($jws, $signature_key_set, $detached_payload, $index);
0 ignored issues
show
It seems like $detached_payload defined by parameter $detached_payload on line 136 can also be of type string; however, Jose\Verifier::verifyWithKeySet() does only seem to accept null, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
142
        Assertion::notNull($index, 'JWS signature(s) verification failed.');
143
        $this->checker_manager->checkJWS($jws, $index);
144
145
        return $index;
146
    }
147
148
    /**
149
     * @param JWEInterface    $jwe
150
     * @param JWKSetInterface $encryption_key_set
151
     *
152
     * @return JWSInterface
153
     */
154
    private function decryptAssertion(JWEInterface $jwe, JWKSetInterface $encryption_key_set): JWSInterface
155
    {
156
        $this->decrypter->decryptUsingKeySet($jwe, $encryption_key_set);
157
158
        $jws = $this->loader->load($jwe->getPayload());
159
        Assertion::isInstanceOf($jws, JWSInterface::class, 'The encrypted assertion does not contain a JWS.');
160
161
        return $jws;
162
    }
163
}
164