Skip to content

Commit e1c0114

Browse files
authored
Merge pull request #62 from Sammyjo20/feature/oauth-2-boilerplate
Feature | OAuth2 Boilerplate
2 parents 0ba2e28 + e21725f commit e1c0114

29 files changed

+1396
-33
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919
"require": {
2020
"php": "^8.0",
2121
"guzzlehttp/guzzle": "^7.4",
22-
"illuminate/support": "^8.0|^9.0"
22+
"illuminate/support": "^8.0|^9.0",
23+
"nesbot/carbon": "^2.58"
2324
},
2425
"require-dev": {
2526
"friendsofphp/php-cs-fixer": "^3.5",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Sammyjo20\Saloon\Exceptions;
4+
5+
use Throwable;
6+
7+
class InvalidStateException extends SaloonException
8+
{
9+
public function __construct(string $message = null, int $code = 0, ?Throwable $previous = null)
10+
{
11+
parent::__construct($message ?? 'Invalid state.', $code, $previous);
12+
}
13+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Sammyjo20\Saloon\Exceptions;
4+
5+
use \Exception;
6+
7+
class OAuthConfigValidationException extends Exception
8+
{
9+
//
10+
}

src/Helpers/OAuth2/OAuthConfig.php

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
<?php
2+
3+
namespace Sammyjo20\Saloon\Helpers\OAuth2;
4+
5+
use Sammyjo20\Saloon\Exceptions\OAuthConfigValidationException;
6+
7+
class OAuthConfig
8+
{
9+
/**
10+
* The Client ID
11+
*
12+
* @var string
13+
*/
14+
protected string $clientId = '';
15+
16+
/**
17+
* The Client Secret
18+
*
19+
* @var string
20+
*/
21+
protected string $clientSecret = '';
22+
23+
/**
24+
* The Redirect URI
25+
*
26+
* @var string
27+
*/
28+
protected string $redirectUri = '';
29+
30+
/**
31+
* The endpoint used for the authorization URL.
32+
*
33+
* @var string
34+
*/
35+
protected string $authorizeEndpoint = 'authorize';
36+
37+
/**
38+
* The endpoint used to create and refresh tokens.
39+
*
40+
* @var string
41+
*/
42+
protected string $tokenEndpoint = 'token';
43+
44+
/**
45+
* The endpoint used to retrieve user information.
46+
*
47+
* @var string
48+
*/
49+
protected string $userEndpoint = 'user';
50+
51+
/**
52+
* The default scopes that will be applied to every authorization URL.
53+
*
54+
* @var array
55+
*/
56+
protected array $defaultScopes = [];
57+
58+
/**
59+
* Create a new instance of the class.
60+
*
61+
* @return static
62+
*/
63+
public static function make(): self
64+
{
65+
return new static;
66+
}
67+
68+
/**
69+
* Get the Client ID
70+
*
71+
* @return string
72+
*/
73+
public function getClientId(): string
74+
{
75+
return $this->clientId;
76+
}
77+
78+
/**
79+
* Set the Client ID
80+
*
81+
* @param string $clientId
82+
* @return OAuthConfig
83+
*/
84+
public function setClientId(string $clientId): self
85+
{
86+
$this->clientId = $clientId;
87+
88+
return $this;
89+
}
90+
91+
/**
92+
* Get the Client Secret
93+
*
94+
* @return string
95+
*/
96+
public function getClientSecret(): string
97+
{
98+
return $this->clientSecret;
99+
}
100+
101+
/**
102+
* Set the Client Secret
103+
*
104+
* @param string $clientSecret
105+
* @return OAuthConfig
106+
*/
107+
public function setClientSecret(string $clientSecret): self
108+
{
109+
$this->clientSecret = $clientSecret;
110+
111+
return $this;
112+
}
113+
114+
/**
115+
* Get the Redirect URI
116+
*
117+
* @return string
118+
*/
119+
public function getRedirectUri(): string
120+
{
121+
return $this->redirectUri;
122+
}
123+
124+
/**
125+
* Set the Redirect URI
126+
*
127+
* @param string $redirectUri
128+
* @return OAuthConfig
129+
*/
130+
public function setRedirectUri(string $redirectUri): self
131+
{
132+
$this->redirectUri = $redirectUri;
133+
134+
return $this;
135+
}
136+
137+
/**
138+
* Get the authorization endpoint.
139+
*
140+
* @return string
141+
*/
142+
public function getAuthorizeEndpoint(): string
143+
{
144+
return $this->authorizeEndpoint;
145+
}
146+
147+
/**
148+
* Set the authorization endpoint.
149+
*
150+
* @param string $authorizeEndpoint
151+
* @return OAuthConfig
152+
*/
153+
public function setAuthorizeEndpoint(string $authorizeEndpoint): self
154+
{
155+
$this->authorizeEndpoint = $authorizeEndpoint;
156+
157+
return $this;
158+
}
159+
160+
/**
161+
* Get the token endpoint.
162+
*
163+
* @return string
164+
*/
165+
public function getTokenEndpoint(): string
166+
{
167+
return $this->tokenEndpoint;
168+
}
169+
170+
/**
171+
* Set the token endpoint.
172+
*
173+
* @param string $tokenEndpoint
174+
* @return OAuthConfig
175+
*/
176+
public function setTokenEndpoint(string $tokenEndpoint): self
177+
{
178+
$this->tokenEndpoint = $tokenEndpoint;
179+
180+
return $this;
181+
}
182+
183+
/**
184+
* Get the user endpoint.
185+
*
186+
* @return string
187+
*/
188+
public function getUserEndpoint(): string
189+
{
190+
return $this->userEndpoint;
191+
}
192+
193+
/**
194+
* Set the user endpoint.
195+
*
196+
* @param string $userEndpoint
197+
* @return OAuthConfig
198+
*/
199+
public function setUserEndpoint(string $userEndpoint): self
200+
{
201+
$this->userEndpoint = $userEndpoint;
202+
203+
return $this;
204+
}
205+
206+
/**
207+
* Get the default scopes.
208+
*
209+
* @return array
210+
*/
211+
public function getDefaultScopes(): array
212+
{
213+
return $this->defaultScopes;
214+
}
215+
216+
/**
217+
* Set the default scopes.
218+
*
219+
* @param array $defaultScopes
220+
* @return OAuthConfig
221+
*/
222+
public function setDefaultScopes(array $defaultScopes): self
223+
{
224+
$this->defaultScopes = $defaultScopes;
225+
226+
return $this;
227+
}
228+
229+
/**
230+
* Validate the OAuth2 config.
231+
*
232+
* @return bool
233+
* @throws OAuthConfigValidationException
234+
*/
235+
public function validate(): bool
236+
{
237+
if (empty($this->getClientId())) {
238+
throw new OAuthConfigValidationException('The Client ID is empty or has not been provided.');
239+
}
240+
241+
if (empty($this->getClientSecret())) {
242+
throw new OAuthConfigValidationException('The Client Secret is empty or has not been provided.');
243+
}
244+
245+
if (empty($this->getRedirectUri())) {
246+
throw new OAuthConfigValidationException('The Redirect URI is empty or has not been provided.');
247+
}
248+
249+
return true;
250+
}
251+
}

src/Helpers/StateHelper.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Sammyjo20\Saloon\Helpers;
4+
5+
use Illuminate\Support\Str;
6+
7+
class StateHelper
8+
{
9+
/**
10+
* Generate a random string for the state.
11+
*
12+
* @return string
13+
*/
14+
public static function createRandomState(): string
15+
{
16+
return Str::random(32);
17+
}
18+
}

src/Helpers/URLHelper.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,25 @@ public static function matches(string $pattern, string $value): bool
1717
{
1818
return Str::is(Str::start($pattern, '*'), $value);
1919
}
20+
21+
/**
22+
* Join a base url and an endpoint together.
23+
*
24+
* @param string $baseUrl
25+
* @param string $endpoint
26+
* @return string
27+
*/
28+
public static function join(string $baseUrl, string $endpoint): string
29+
{
30+
if ($endpoint !== '/') {
31+
$endpoint = ltrim($endpoint, '/ ');
32+
}
33+
34+
$requiresTrailingSlash = ! empty($endpoint) && $endpoint !== '/';
35+
36+
$baseEndpoint = rtrim($baseUrl, '/ ');
37+
$baseEndpoint = $requiresTrailingSlash ? $baseEndpoint . '/' : $baseEndpoint;
38+
39+
return $baseEndpoint . $endpoint;
40+
}
2041
}

0 commit comments

Comments
 (0)