Completed
Push — master ( 40b29f...7210ec )
by Florent
31:16 queued 19:22
created

Verifier::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 13
rs 9.4286
cc 1
eloc 11
nc 1
nop 5
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\HasJWKFinderManager;
20
use Jose\Behaviour\HasKeyChecker;
21
use Jose\Behaviour\HasPayloadConverter;
22
use Jose\Checker\CheckerManagerInterface;
23
use Jose\Compression\CompressionManagerInterface;
24
use Jose\Finder\JWKFinderManagerInterface;
25
use Jose\Object\JWKInterface;
26
use Jose\Object\JWKSet;
27
use Jose\Object\JWKSetInterface;
28
use Jose\Object\JWSInterface;
29
use Jose\Object\JWTInterface;
30
use Jose\Payload\PayloadConverterManagerInterface;
31
32
/**
33
 */
34
final class Verifier implements VerifierInterface
35
{
36
    use HasKeyChecker;
37
    use HasJWAManager;
38
    use HasJWKFinderManager;
39
    use HasCheckerManager;
40
    use HasPayloadConverter;
41
    use HasCompressionManager;
42
43
    /**
44
     * Loader constructor.
45
     *
46
     * @param \Jose\Algorithm\JWAManagerInterface                      $jwa_manager
47
     * @param \Jose\Finder\JWKFinderManagerInterface                $jwk_finder_manager
48
     * @param \Jose\Payload\PayloadConverterManagerInterface $payload_converter_manager
49
     * @param \Jose\Compression\CompressionManagerInterface  $compression_manager
50
     * @param \Jose\Checker\CheckerManagerInterface          $checker_manager
51
     */
52
    public function __construct(
53
        JWAManagerInterface $jwa_manager,
54
        JWKFinderManagerInterface $jwk_finder_manager,
55
        PayloadConverterManagerInterface $payload_converter_manager,
56
        CompressionManagerInterface $compression_manager,
57
        CheckerManagerInterface $checker_manager)
58
    {
59
        $this->setJWAManager($jwa_manager);
60
        $this->setJWKFinderManager($jwk_finder_manager);
61
        $this->setPayloadConverter($payload_converter_manager);
62
        $this->setCompressionManager($compression_manager);
63
        $this->setCheckerManager($checker_manager);
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     *
69
     * @throws \InvalidArgumentException
70
     */
71
    public function verifySignature(JWSInterface $jws, JWKSetInterface $jwk_set = null, $detached_payload = null)
72
    {
73
        if (null !== $detached_payload && !empty($jws->getPayload())) {
74
            throw new \InvalidArgumentException('A detached payload is set, but the JWS already has a payload');
75
        }
76
        $complete_header = $jws->getHeaders();
77
        if (null === $jwk_set) {
78
            $jwk_set = $this->getKeysFromCompleteHeader(
79
                $complete_header,
80
                JWKFinderManagerInterface::KEY_TYPE_PUBLIC | JWKFinderManagerInterface::KEY_TYPE_SYMMETRIC | JWKFinderManagerInterface::KEY_TYPE_NONE
81
            );
82
        }
83
84
        $input = $jws->getEncodedProtectedHeaders().'.'.(null === $detached_payload ? $jws->getEncodedPayload() : $detached_payload);
85
86
        if (0 === count($jwk_set)) {
87
            return false;
88
        }
89
        foreach ($jwk_set->getKeys() as $jwk) {
90
            $algorithm = $this->getAlgorithm($complete_header, $jwk);
91
            if (!$this->checkKeyUsage($jwk, 'verification')) {
92
                continue;
93
            }
94
            if (!$this->checkKeyAlgorithm($jwk, $algorithm->getAlgorithmName())) {
95
                continue;
96
            }
97
            try {
98
                if (true === $algorithm->verify($jwk, $input, $jws->getSignature())) {
99
                    return true;
100
                }
101
            } catch (\InvalidArgumentException $e) {
102
                //We do nothing, we continue with other keys
103
            }
104
        }
105
106
        return false;
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112
    public function verify(JWTInterface $jwt)
113
    {
114
        $this->getCheckerManager()->checkJWT($jwt);
115
116
        return true;
117
    }
118
119
    /**
120
     * @param array              $header
121
     * @param \Jose\Object\JWKInterface $key
122
     *
123
     * @return \Jose\Algorithm\Signature\SignatureInterface|null
124
     */
125
    private function getAlgorithm(array $header, JWKInterface $key)
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
126
    {
127
        if (!array_key_exists('alg', $header)) {
128
            //if (!$key->hasHeader('alg')) {
129
            throw new \InvalidArgumentException("No 'alg' parameter set in the header or the key.");
130
        }/* else {
131
                $alg = $key->getHeader('alg');
132
            }*/
133
        //} else {
134
        $alg = $header['alg'];
135
        //}
136
137
        $algorithm = $this->getJWAManager()->getAlgorithm($alg);
138
        if (!$algorithm instanceof SignatureInterface) {
139
            throw new \RuntimeException("The algorithm '$alg' is not supported or does not implement SignatureInterface.");
140
        }
141
142
        return $algorithm;
143
    }
144
145
    /**
146
     * @param array $header
147
     * @param int   $key_type
148
     *
149
     * @return \Jose\Object\JWKSetInterface
150
     */
151
    private function getKeysFromCompleteHeader(array $header, $key_type)
152
    {
153
        $keys = $this->getJWKFinderManager()->findJWK($header, $key_type);
154
        $jwkset = new JWKSet($keys);
155
156
        return $jwkset;
157
    }
158
}
159