Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
31 / 31 |
|
100.00% |
5 / 5 |
CRAP | |
100.00% |
1 / 1 |
AbstractOAuth2Provider | |
100.00% |
31 / 31 |
|
100.00% |
5 / 5 |
13 | |
100.00% |
1 / 1 |
getAuthorizeUrl | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
getAccessTokenUrl | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
getScope | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
getUserProfile | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | |||||
__construct | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
authenticate | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
5 | |||
getAccessToken | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
getFullAuthorizeUrl | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
3 | |||
generateState | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 |
1 | <?php |
2 | |
3 | namespace Miniframe\SocialLogin\Provider; |
4 | |
5 | use Miniframe\Core\Config; |
6 | use Miniframe\Core\Request; |
7 | use Miniframe\Response\RedirectResponse; |
8 | use Miniframe\SocialLogin\Middleware\SocialLogin; |
9 | use Miniframe\SocialLogin\Model\User; |
10 | |
11 | abstract class AbstractOAuth2Provider extends AbstractOAuthProvider |
12 | { |
13 | /** |
14 | * Returns the Authorize URL |
15 | * |
16 | * @return string |
17 | */ |
18 | abstract protected function getAuthorizeUrl(): string; |
19 | |
20 | /** |
21 | * Returns the Access Token URL |
22 | * |
23 | * @return string |
24 | */ |
25 | abstract protected function getAccessTokenUrl(): string; |
26 | |
27 | /** |
28 | * Returns the requested scope |
29 | * |
30 | * @return string|null |
31 | */ |
32 | abstract protected function getScope(): ?string; |
33 | |
34 | /** |
35 | * Returns the user profile |
36 | * |
37 | * @param array $accessToken The access token. |
38 | * |
39 | * @return User |
40 | */ |
41 | abstract protected function getUserProfile(array $accessToken): User; |
42 | |
43 | /** |
44 | * OAuth 2.0 Client ID |
45 | * |
46 | * @var string |
47 | */ |
48 | protected $clientId; |
49 | |
50 | /** |
51 | * OAuth 2.0 Client Secret |
52 | * |
53 | * @var string |
54 | */ |
55 | protected $clientSecret; |
56 | |
57 | /** |
58 | * Creates a new OAuth 2.0 provider |
59 | * |
60 | * @param Request $request Reference to the Request object. |
61 | * @param Config $config Reference to the Config object. |
62 | */ |
63 | public function __construct(Request $request, Config $config) |
64 | { |
65 | parent::__construct($request, $config); |
66 | |
67 | // Get config |
68 | $this->clientId = $config->get('sociallogin-' . $this->shortName, 'client_id'); |
69 | $this->clientSecret = $config->get('sociallogin-' . $this->shortName, 'client_secret'); |
70 | } |
71 | |
72 | /** |
73 | * Starts the authentication process |
74 | * |
75 | * @return User |
76 | */ |
77 | public function authenticate(): User |
78 | { |
79 | if ($this->request->getRequest('state') && $this->request->getRequest('code')) { |
80 | $state = SocialLogin::parseState($this->request->getRequest('state')); |
81 | if (!isset($state['redirectUrl'])) { |
82 | throw new \RuntimeException('State incomplete'); |
83 | } |
84 | |
85 | $accessToken = $this->getAccessToken($this->request->getRequest('code')); |
86 | if (!isset($accessToken['access_token'])) { |
87 | throw new \RuntimeException('Did\'t get an access token'); |
88 | } |
89 | return $this->getUserProfile($accessToken); |
90 | } |
91 | |
92 | throw new RedirectResponse($this->getFullAuthorizeUrl()); |
93 | } |
94 | |
95 | /** |
96 | * Requests the access token based on a code from the OAuth provider |
97 | * |
98 | * @param string $code The provided code. |
99 | * |
100 | * @return array |
101 | */ |
102 | protected function getAccessToken(string $code): array |
103 | { |
104 | $data = array( |
105 | 'client_id' => $this->clientId, |
106 | 'client_secret' => $this->clientSecret, |
107 | 'code' => $code, |
108 | 'redirect_uri' => $this->getCurrentUri(), |
109 | 'grant_type' => 'authorization_code', |
110 | ); |
111 | |
112 | return $this->curlRequest($this->getAccessTokenUrl(), 'POST', $data); |
113 | } |
114 | |
115 | /** |
116 | * Gets a full authorize URL, including the client ID and all other required parameters. |
117 | * |
118 | * @param array $data Optionally extra fields to append to the authorize URL. |
119 | * |
120 | * @return string |
121 | */ |
122 | protected function getFullAuthorizeUrl(array $data = array()): string |
123 | { |
124 | $data['client_id'] = $this->clientId; |
125 | $data['redirect_uri'] = $this->getCurrentUri(); |
126 | $data['state'] = $this->generateState(); |
127 | $data['response_type'] = 'code'; |
128 | if ($this->getScope()) { |
129 | $data['scope'] = $this->getScope(); |
130 | } |
131 | |
132 | return $this->getAuthorizeUrl() |
133 | . (strpos($this->getAuthorizeUrl(), '?') !== false ? '&' : '?') |
134 | . http_build_query($data); |
135 | } |
136 | |
137 | /** |
138 | * Generates the state string |
139 | * |
140 | * @return string |
141 | */ |
142 | protected function generateState(): string |
143 | { |
144 | $state = array(); |
145 | if ($this->request->getRequest('state')) { |
146 | $state = SocialLogin::parseState($this->request->getRequest('state')); |
147 | } |
148 | if (!isset($state['redirectUrl'])) { |
149 | $state['redirectUrl'] = $this->baseHref; |
150 | } |
151 | return SocialLogin::generateState($state); |
152 | } |
153 | } |