Failed Conditions
Push — master ( de6a42...332cc0 )
by Florent
15:27
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\ClientRegistrationEndpoint\Rule;
15
16
use Jose\Component\Core\JWKSet;
17
use Jose\Component\Signature\JWSLoader;
18
use OAuth2Framework\Component\ClientRule\Rule;
19
use OAuth2Framework\Component\Core\Client\ClientId;
20
use OAuth2Framework\Component\Core\DataBag\DataBag;
21
22
final class SoftwareRule implements Rule
23
{
24
    /**
25
     * @var JWSLoader
26
     */
27
    private $jwsLoader;
28
29
    /**
30
     * @var bool
31
     */
32
    private $isSoftwareStatementRequired;
33
34
    /**
35
     * @var JWKSet
36
     */
37
    private $softwareStatementSignatureKeySet;
38
39
    /**
40
     * @var string[]
41
     */
42
    private $allowedSignatureAlgorithms;
43
44
    /**
45
     * @param JWSLoader $jwsLoader
46
     * @param JWKSet    $signatureKeySet
47
     * @param bool      $isSoftwareStatementRequired
48
     * @param array     $allowedSignatureAlgorithms
49
     */
50
    public function __construct(JWSLoader $jwsLoader, JWKSet $signatureKeySet, bool $isSoftwareStatementRequired, array $allowedSignatureAlgorithms)
51
    {
52
        $this->jwsLoader = $jwsLoader;
53
        $this->softwareStatementSignatureKeySet = $signatureKeySet;
54
        $this->isSoftwareStatementRequired = $isSoftwareStatementRequired;
55
        $this->allowedSignatureAlgorithms = $allowedSignatureAlgorithms;
56
    }
57
58
    /**
59
     * @return bool
60
     */
61
    public function isSoftwareStatementRequired(): bool
62
    {
63
        return $this->isSoftwareStatementRequired;
64
    }
65
66
    /**
67
     * {@inheritdoc}
68
     */
69
    public function handle(ClientId $clientId, DataBag $commandParameters, DataBag $validatedParameters, callable $next): DataBag
70
    {
71
        if ($this->isSoftwareStatementRequired() && !$commandParameters->has('software_statement')) {
72
            throw new \InvalidArgumentException('The parameter "software_statement" is mandatory.');
73
        }
74
        if ($commandParameters->has('software_statement')) {
75
            $statement = $commandParameters->get('software_statement');
76
            if (!is_string($statement)) {
77
                throw new \InvalidArgumentException('The software statement must be a string.');
78
            }
79
            $software_statement = $this->loadSoftwareStatement($statement);
80
            $validatedParameters = $validatedParameters->with('software_statement', $commandParameters->get('software_statement'));
81
        } else {
82
            $software_statement = [];
83
        }
84
85
        foreach (['software_id', 'software_version'] as $key) {
86
            if ($commandParameters->has($key)) {
87
                $validatedParameters = $validatedParameters->with($key, $commandParameters->get($key));
88
            }
89
        }
90
91
        $validatedParameters = $next($clientId, $commandParameters, $validatedParameters);
92
        $validatedParameters = $validatedParameters->withParameters($software_statement);
93
94
        return $validatedParameters;
95
    }
96
97
    /**
98
     * @param string $software_statement
99
     *
100
     * @return array
101
     */
102
    private function loadSoftwareStatement(string $software_statement): array
103
    {
104
        try {
105
            $jws = $this->jwsLoader->loadAndVerifyWithKeySet($software_statement, $this->softwareStatementSignatureKeySet, $signatureVerified);
106
            if (!in_array($jws->getSignature($signatureVerified)->getProtectedHeaderParameter('alg'), $this->allowedSignatureAlgorithms)) {
107
                throw new \InvalidArgumentException('Invalid Software Statement.');
108
            }
109
            $claims = json_decode($jws->getPayload(), true);
110
            if (!is_array($claims)) {
111
                throw new \InvalidArgumentException('Invalid Software Statement.');
112
            }
113
114
            return $claims;
115
        } catch (\Exception $e) {
116
            throw new \InvalidArgumentException('Invalid Software Statement.', $e->getCode(), $e);
117
        }
118
    }
119
}
120