Passed
Push — develop ( dfc3dd...7c6d84 )
by nguereza
01:37
created

Client::isPublic()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
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
37
/**
38
 * @class Client
39
 * @package Platine\OAuth2\Entity
40
 */
41
class Client
42
{
43
    /**
44
     * The client id
45
     * @var string
46
     */
47
    protected string $id;
48
49
    /**
50
     * The client name
51
     * @var string
52
     */
53
    protected string $name;
54
55
    /**
56
     * The client secret
57
     * @var string
58
     */
59
    protected string $secret = '';
60
61
    /**
62
     * The client redirect URIs
63
     * @var array<string>
64
     */
65
    protected array $redirectUris = [];
66
67
    /**
68
     * The client scopes
69
     * @var array<string>
70
     */
71
    protected array $scopes = [];
72
73
    /**
74
     * Can not rewrite the constructor in child classes
75
     */
76
    final public function __construct()
77
    {
78
    }
79
80
    /**
81
     * Create new client
82
     * @param string $name
83
     * @param string|array<string>|null $redirectUris
84
     * @param array<string>|null $scopes
85
     * @return self
86
     */
87
    public static function createNewClient(
88
        string $name,
89
        $redirectUris = null,
90
        ?array $scopes = null
91
    ): self {
92
        if ($redirectUris !== null && is_string($redirectUris)) {
93
            $redirectUris = explode(' ', $redirectUris);
94
        }
95
96
        if ($redirectUris !== null && is_array($redirectUris)) {
97
            foreach ($redirectUris as &$redirectUri) {
98
                $redirectUri = trim((string) $redirectUri);
99
            }
100
        }
101
102
        $client = new static();
103
        $client->id = Str::randomString('hexdec', 20);
104
        $client->name = $name;
105
        $client->redirectUris = $redirectUris ?? [];
106
        $client->scopes = $scopes ?? [];
107
108
        return $client;
109
    }
110
111
    /**
112
     * Create client using given data
113
     * @param array<string, mixed> $data
114
     * @return self
115
     */
116
    public static function hydrate(array $data): self
117
    {
118
        $client = new static();
119
        $client->id = $data['id'];
120
        $client->name = $data['name'];
121
        $client->secret = $data['secret'];
122
        $client->redirectUris = $data['redirect_uris'];
123
        $client->scopes = $data['scopes'];
124
125
        return $client;
126
    }
127
128
    /**
129
     * Return the client id
130
     * @return string
131
     */
132
    public function getId(): string
133
    {
134
        return $this->id;
135
    }
136
137
    /**
138
     * Return the name
139
     * @return string
140
     */
141
    public function getName(): string
142
    {
143
        return $this->name;
144
    }
145
146
    /**
147
     * Return the secret
148
     * @return string
149
     */
150
    public function getSecret(): string
151
    {
152
        return $this->secret;
153
    }
154
155
    /**
156
     * Return the redirect URIs
157
     * @return array<string>
158
     */
159
    public function getRedirectUris(): array
160
    {
161
        return $this->redirectUris;
162
    }
163
164
    /**
165
     * Return the scopes
166
     * @return array<string>
167
     */
168
    public function getScopes(): array
169
    {
170
        return $this->scopes;
171
    }
172
173
    /**
174
     * Whether the client has the given redirect URI
175
     * @param string $redirectUri
176
     * @return bool
177
     */
178
    public function hasRedirectUri(string $redirectUri): bool
179
    {
180
        return in_array($redirectUri, $this->redirectUris, true);
181
    }
182
183
    /**
184
     * Whether it's the public client
185
     * @return bool
186
     */
187
    public function isPublic(): bool
188
    {
189
        return empty($this->secret);
190
    }
191
192
    /**
193
     * Authenticate the client
194
     * @return bool
195
     */
196
    public function authenticate(string $secret): bool
197
    {
198
        return password_verify($secret, $this->getSecret());
199
    }
200
201
    /**
202
     * Generate a strong, unique secret and crypt it.
203
     * @return string
204
     */
205
    public function generateSecret(): string
206
    {
207
        $secret = bin2hex(random_bytes(20));
208
        $this->secret = password_hash($secret, PASSWORD_DEFAULT);
209
210
        return $secret;
211
    }
212
}
213