Issues (16)

src/Entity/Client.php (1 issue)

Severity
1
<?php
2
3
/**
4
 * Platine OAuth2
5
 *
6
 * Platine OAuth2 is a library that implements the OAuth2 specification
7
 *
8
 * This content is released under the MIT License (MIT)
9
 *
10
 * Copyright (c) 2020 Platine OAuth2
11
 *
12
 * Permission is hereby granted, free of charge, to any person obtaining a copy
13
 * of this software and associated documentation files (the "Software"), to deal
14
 * in the Software without restriction, including without limitation the rights
15
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
 * copies of the Software, and to permit persons to whom the Software is
17
 * furnished to do so, subject to the following conditions:
18
 *
19
 * The above copyright notice and this permission notice shall be included in all
20
 * copies or substantial portions of the Software.
21
 *
22
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
 * SOFTWARE.
29
 */
30
31
declare(strict_types=1);
32
33
namespace Platine\OAuth2\Entity;
34
35
use Platine\Stdlib\Helper\Str;
36
use RuntimeException;
37
38
/**
39
 * @class Client
40
 * @package Platine\OAuth2\Entity
41
 */
42
class Client
43
{
44
    /**
45
     * The client id
46
     * @var string
47
     */
48
    protected string $id;
49
50
    /**
51
     * The client name
52
     * @var string
53
     */
54
    protected string $name;
55
56
    /**
57
     * The client secret
58
     * @var string
59
     */
60
    protected string $secret = '';
61
62
    /**
63
     * The client redirect URIs
64
     * @var array<string>
65
     */
66
    protected array $redirectUris = [];
67
68
    /**
69
     * The client scopes
70
     * @var array<string>
71
     */
72
    protected array $scopes = [];
73
74
    /**
75
     * Can not rewrite the constructor in child classes
76
     */
77
    final public function __construct()
78
    {
79
    }
80
81
    /**
82
     * Create new client
83
     * @param string $name
84
     * @param string|array<string>|null $redirectUris
85
     * @param array<string>|null $scopes
86
     * @return self
87
     */
88
    public static function createNewClient(
89
        string $name,
90
        string|array $redirectUris = null,
91
        ?array $scopes = null
92
    ): self {
93
        if (is_string($redirectUris)) {
0 ignored issues
show
The condition is_string($redirectUris) is always false.
Loading history...
94
            $redirectUris = explode(' ', $redirectUris);
95
        }
96
97
        if ($redirectUris !== null) {
98
            foreach ($redirectUris as &$redirectUri) {
99
                $redirectUri = trim((string) $redirectUri);
100
            }
101
        }
102
103
        $client = new static();
104
        $client->id = Str::randomString('hexdec', 20);
105
        $client->name = $name;
106
        $client->redirectUris = $redirectUris ?? [];
107
        $client->scopes = $scopes ?? [];
108
109
        return $client;
110
    }
111
112
    /**
113
     * Create client using given data
114
     * @param array<string, mixed> $data
115
     * @return self
116
     */
117
    public static function hydrate(array $data): self
118
    {
119
        $client = new static();
120
        $client->id = $data['id'];
121
        $client->name = $data['name'];
122
        $client->secret = $data['secret'];
123
        $client->redirectUris = (array) $data['redirect_uris'];
124
        $client->scopes = $data['scopes'];
125
126
        return $client;
127
    }
128
129
    /**
130
     * Return the client id
131
     * @return string
132
     */
133
    public function getId(): string
134
    {
135
        return $this->id;
136
    }
137
138
    /**
139
     * Return the name
140
     * @return string
141
     */
142
    public function getName(): string
143
    {
144
        return $this->name;
145
    }
146
147
    /**
148
     * Return the secret
149
     * @return string
150
     */
151
    public function getSecret(): string
152
    {
153
        return $this->secret;
154
    }
155
156
    /**
157
     * Return the redirect URIs
158
     * @return array<string>
159
     */
160
    public function getRedirectUris(): array
161
    {
162
        return $this->redirectUris;
163
    }
164
165
    /**
166
     * Return the scopes
167
     * @return array<string>
168
     */
169
    public function getScopes(): array
170
    {
171
        return $this->scopes;
172
    }
173
174
    /**
175
     * Whether the client has the given redirect URI
176
     * @param string $redirectUri
177
     * @return bool
178
     */
179
    public function hasRedirectUri(string $redirectUri): bool
180
    {
181
        return in_array($redirectUri, $this->redirectUris, true);
182
    }
183
184
    /**
185
     * Whether it's the public client
186
     * @return bool
187
     */
188
    public function isPublic(): bool
189
    {
190
        return empty($this->secret);
191
    }
192
193
    /**
194
     * Authenticate the client
195
     * @return bool
196
     */
197
    public function authenticate(string $secret): bool
198
    {
199
        return password_verify($secret, $this->getSecret());
200
    }
201
202
    /**
203
     * Generate a strong, unique secret and crypt it.
204
     * @return string
205
     */
206
    public function generateSecret(): string
207
    {
208
        $secret = bin2hex(random_bytes(20));
209
        $secretHash = password_hash($secret, PASSWORD_DEFAULT);
210
        if ($secretHash === false) {
211
            throw new RuntimeException('Can not hash secret');
212
        }
213
        $this->secret = $secretHash;
214
215
        return $secret;
216
    }
217
}
218