Failed Conditions
Push — v6.1 ( cdc769...108bde )
by Florent
02:14
created

DownloadedJWKSet::addKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
dl 0
loc 4
rs 10
c 1
b 0
f 1
cc 1
eloc 1
nc 1
nop 1
1
<?php
2
3
/*
4
 * The MIT License (MIT)
5
 *
6
 * Copyright (c) 2014-2018 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\Object;
13
14
use Assert\Assertion;
15
use Psr\Cache\CacheItemPoolInterface;
16
17
/**
18
 * Class DownloadedJWKSet.
19
 */
20
abstract class DownloadedJWKSet extends BaseJWKSet implements JWKSetInterface
21
{
22
    use JWKSetPEM;
23
24
    /**
25
     * @var string
26
     */
27
    private $url;
28
29
    /**
30
     * @var null|\Psr\Cache\CacheItemPoolInterface
31
     */
32
    private $cache;
33
34
    /**
35
     * @var int
36
     */
37
    private $ttl;
38
39
    /**
40
     * @var bool
41
     */
42
    private $allow_unsecured_connection;
43
44
    /**
45
     * DownloadedJWKSet constructor.
46
     *
47
     * @param string                                 $url
48
     * @param \Psr\Cache\CacheItemPoolInterface|null $cache
49
     * @param int                                    $ttl
50
     * @param bool                                   $allow_unsecured_connection
51
     * @param bool                                   $allow_http_connection
52
     */
53
    public function __construct($url, CacheItemPoolInterface $cache = null, $ttl = 86400, $allow_unsecured_connection = false, $allow_http_connection = false)
54
    {
55
        Assertion::boolean($allow_unsecured_connection);
56
        Assertion::boolean($allow_http_connection);
57
        Assertion::integer($ttl);
58
        Assertion::min($ttl, 0);
59
        Assertion::false(false === filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED), 'Invalid URL.');
60
        $allowed_protocols = ['https'];
61
        if (true === $allow_http_connection) {
62
            $allowed_protocols[] = 'http';
63
        }
64
        Assertion::inArray(mb_substr($url, 0, mb_strpos($url, '://', 0, '8bit'), '8bit'), $allowed_protocols, sprintf('The provided sector identifier URI is not valid: scheme must be one of the following: %s.', json_encode($allowed_protocols)));
65
66
        $this->url = $url;
67
        $this->cache = $cache;
68
        $this->ttl = $ttl;
69
        $this->allow_unsecured_connection = $allow_unsecured_connection;
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75
    public function addKey(JWKInterface $key)
76
    {
77
        //Not available
78
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83
    public function prependKey(JWKInterface $key)
84
    {
85
        //Not available
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91
    public function removeKey($index)
92
    {
93
        //Not available
94
    }
95
96
    /**
97
     * @return string
98
     */
99
    protected function getContent()
100
    {
101
        $cache_key = sprintf('JWKFactory-Content-%s', hash('sha512', $this->url));
102
        if (null !== $this->cache) {
103
            $item = $this->cache->getItem($cache_key);
104
            if (!$item->isHit()) {
105
                $content = $this->downloadContent();
106
                $item->set($content);
107
                if (0 !== $this->ttl) {
108
                    $item->expiresAfter($this->ttl);
109
                }
110
                $this->cache->save($item);
111
112
                return $content;
113
            } else {
114
                return $item->get();
115
            }
116
        }
117
118
        return $this->downloadContent();
119
    }
120
121
    /**
122
     * @throws \InvalidArgumentException Has CURL error message and the CURL error
123
     *                                   number as exception code.
124
     *                                   Throws exception with error number 0
125
     *                                   if the error is not related to CURL.
126
     *
127
     * @return string
128
     */
129
    private function downloadContent()
130
    {
131
        $params = [
132
            CURLOPT_RETURNTRANSFER => true,
133
            CURLOPT_URL => $this->url,
134
        ];
135
        if (false === $this->allow_unsecured_connection) {
136
            $params[CURLOPT_SSL_VERIFYPEER] = true;
137
            $params[CURLOPT_SSL_VERIFYHOST] = 2;
138
        }
139
140
        $ch = curl_init();
141
        curl_setopt_array($ch, $params);
142
        $content = curl_exec($ch);
143
144
        try {
145
            Assertion::false(false === $content, 'Failed to load JWK contents: ');
146
        } catch (\Assert\AssertionFailedException $e) {
147
            $curlError = curl_error($ch);
148
            $curlErrorNumber = curl_errno($ch);
149
150
            throw new \InvalidArgumentException(
151
                $e->getMessage().$curlError,
152
                $curlErrorNumber
153
            );
154
        } catch (\Exception $e) {
155
            throw new \InvalidArgumentException(
156
                'Failed to load JWK contents: '.$e->getMessage(),
157
                0
158
            );
159
        } finally {
160
            curl_close($ch);
161
        }
162
163
        return $content;
164
    }
165
}
166