Failed Conditions
Push — ng ( a36945...8b0de7 )
by Florent
15:25
created

SoftwareRule::handle()   C

Complexity

Conditions 7
Paths 8

Size

Total Lines 27
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 27
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 17
nc 8
nop 4
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2018 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace OAuth2Framework\Component\ClientRule;
15
16
use Jose\Component\Core\JWKSet;
17
use Jose\Component\Signature\JWSLoader;
18
use OAuth2Framework\Component\Core\Client\ClientId;
19
use OAuth2Framework\Component\Core\DataBag\DataBag;
20
21
class SoftwareRule implements Rule
22
{
23
    /**
24
     * @var JWSLoader
25
     */
26
    private $jwsLoader;
27
28
    /**
29
     * @var bool
30
     */
31
    private $isSoftwareStatementRequired;
32
33
    /**
34
     * @var JWKSet
35
     */
36
    private $softwareStatementSignatureKeySet;
37
38
    /**
39
     * @var string[]
40
     */
41
    private $allowedSignatureAlgorithms;
42
43
    /**
44
     * @param JWSLoader $jwsLoader
45
     * @param JWKSet    $signatureKeySet
46
     * @param bool      $isSoftwareStatementRequired
47
     * @param array     $allowedSignatureAlgorithms
48
     */
49
    public function __construct(JWSLoader $jwsLoader, JWKSet $signatureKeySet, bool $isSoftwareStatementRequired, array $allowedSignatureAlgorithms)
50
    {
51
        $this->jwsLoader = $jwsLoader;
52
        $this->softwareStatementSignatureKeySet = $signatureKeySet;
53
        $this->isSoftwareStatementRequired = $isSoftwareStatementRequired;
54
        $this->allowedSignatureAlgorithms = $allowedSignatureAlgorithms;
55
    }
56
57
    /**
58
     * @return bool
59
     */
60
    public function isSoftwareStatementRequired(): bool
61
    {
62
        return $this->isSoftwareStatementRequired;
63
    }
64
65
    /**
66
     * {@inheritdoc}
67
     */
68
    public function handle(ClientId $clientId, DataBag $commandParameters, DataBag $validatedParameters, callable $next): DataBag
69
    {
70
        if ($this->isSoftwareStatementRequired() && !$commandParameters->has('software_statement')) {
71
            throw new \InvalidArgumentException('The parameter "software_statement" is mandatory.');
72
        }
73
        if ($commandParameters->has('software_statement')) {
74
            $statement = $commandParameters->get('software_statement');
75
            if (!is_string($statement)) {
76
                throw new \InvalidArgumentException('The software statement must be a string.');
77
            }
78
            $software_statement = $this->loadSoftwareStatement($statement);
79
            $validatedParameters = $validatedParameters->with('software_statement', $commandParameters->get('software_statement'));
80
        } else {
81
            $software_statement = [];
82
        }
83
84
        foreach (['software_id', 'software_version'] as $key) {
85
            if ($commandParameters->has($key)) {
86
                $validatedParameters = $validatedParameters->with($key, $commandParameters->get($key));
87
            }
88
        }
89
90
        $validatedParameters = $next($clientId, $commandParameters, $validatedParameters);
91
        $validatedParameters = $validatedParameters->withParameters($software_statement);
92
93
        return $validatedParameters;
94
    }
95
96
    /**
97
     * @param string $software_statement
98
     *
99
     * @return array
100
     */
101
    private function loadSoftwareStatement(string $software_statement): array
102
    {
103
        try {
104
            $jws = $this->jwsLoader->loadAndVerifyWithKeySet($software_statement, $this->softwareStatementSignatureKeySet, $signatureVerified);
105
            if (!in_array($jws->getSignature($signatureVerified)->getProtectedHeaderParameter('alg'), $this->allowedSignatureAlgorithms)) {
106
                throw new \InvalidArgumentException('Invalid Software Statement.');
107
            }
108
            $claims = json_decode($jws->getPayload(), true);
109
            if (!is_array($claims)) {
110
                throw new \InvalidArgumentException('Invalid Software Statement.');
111
            }
112
113
            return $claims;
114
        } catch (\Exception $e) {
115
            throw new \InvalidArgumentException('Invalid Software Statement.', $e->getCode(), $e);
116
        }
117
    }
118
}
119