Completed
Push — master ( 6593bf...678353 )
by Florent
02:22
created

Verifier::verify()   D

Complexity

Conditions 10
Paths 17

Size

Total Lines 31
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 5
Bugs 2 Features 1
Metric Value
c 5
b 2
f 1
dl 0
loc 31
rs 4.8197
cc 10
eloc 18
nc 17
nop 3

How to fix   Complexity   

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
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2014-2015 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 Jose\Algorithm\JWAManagerInterface;
15
use Jose\Algorithm\Signature\SignatureInterface;
16
use Jose\Behaviour\HasCheckerManager;
17
use Jose\Behaviour\HasCompressionManager;
18
use Jose\Behaviour\HasJWAManager;
19
use Jose\Behaviour\HasKeyChecker;
20
use Jose\Behaviour\HasPayloadConverter;
21
use Jose\Checker\CheckerManagerInterface;
22
use Jose\Compression\CompressionManagerInterface;
23
use Jose\Object\JWKSetInterface;
24
use Jose\Object\JWSInterface;
25
use Jose\Payload\PayloadConverterManagerInterface;
26
27
/**
28
 */
29
final class Verifier implements VerifierInterface
30
{
31
    use HasKeyChecker;
32
    use HasJWAManager;
33
    use HasCheckerManager;
34
    use HasPayloadConverter;
35
    use HasCompressionManager;
36
37
    /**
38
     * Loader constructor.
39
     *
40
     * @param \Jose\Algorithm\JWAManagerInterface            $jwa_manager
41
     * @param \Jose\Payload\PayloadConverterManagerInterface $payload_converter_manager
42
     * @param \Jose\Compression\CompressionManagerInterface  $compression_manager
43
     * @param \Jose\Checker\CheckerManagerInterface          $checker_manager
44
     */
45
    public function __construct(
46
        JWAManagerInterface $jwa_manager,
47
        PayloadConverterManagerInterface $payload_converter_manager,
48
        CompressionManagerInterface $compression_manager,
49
        CheckerManagerInterface $checker_manager)
50
    {
51
        $this->setJWAManager($jwa_manager);
52
        $this->setPayloadConverter($payload_converter_manager);
53
        $this->setCompressionManager($compression_manager);
54
        $this->setCheckerManager($checker_manager);
55
    }
56
57
    /**
58
     * {@inheritdoc}
59
     *
60
     * @throws \InvalidArgumentException
61
     */
62
    public function verify(JWSInterface $jws, JWKSetInterface $jwk_set, $detached_payload = null)
63
    {
64
        if (null !== $detached_payload && !empty($jws->getPayload())) {
65
            throw new \InvalidArgumentException('A detached payload is set, but the JWS already has a payload');
66
        }
67
        $input = $jws->getEncodedProtectedHeaders().'.'.(null === $detached_payload ? $jws->getEncodedPayload() : $detached_payload);
68
69
        if (0 === count($jwk_set)) {
70
            return false;
71
        }
72
        foreach ($jwk_set->getKeys() as $jwk) {
73
            $algorithm = $this->getAlgorithm($jws->getHeaders());
74
            if (!$this->checkKeyUsage($jwk, 'verification')) {
75
                continue;
76
            }
77
            if (!$this->checkKeyAlgorithm($jwk, $algorithm->getAlgorithmName())) {
78
                continue;
79
            }
80
            try {
81
                if (true === $algorithm->verify($jwk, $input, $jws->getSignature())) {
82
                    $this->getCheckerManager()->checkJWT($jws);
83
84
                    return true;
85
                }
86
            } catch (\Exception $e) {
87
                //We do nothing, we continue with other keys
88
            }
89
        }
90
91
        return false;
92
    }
93
94
    /**
95
     * @param array $header
96
     *
97
     * @return \Jose\Algorithm\Signature\SignatureInterface|null
98
     */
99
    private function getAlgorithm(array $header)
100
    {
101
        if (!array_key_exists('alg', $header)) {
102
            throw new \InvalidArgumentException("No 'alg' parameter set in the header or the key.");
103
        }
104
        $alg = $header['alg'];
105
106
        $algorithm = $this->getJWAManager()->getAlgorithm($alg);
107
        if (!$algorithm instanceof SignatureInterface) {
108
            throw new \RuntimeException("The algorithm '$alg' is not supported or does not implement SignatureInterface.");
109
        }
110
111
        return $algorithm;
112
    }
113
}
114