1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Created by PhpStorm. |
4
|
|
|
* User: Alexandre |
5
|
|
|
* Date: 18/02/2018 |
6
|
|
|
* Time: 18:08 |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
namespace OAuth2\Flows; |
10
|
|
|
|
11
|
|
|
|
12
|
|
|
use OAuth2\Credentials\AuthorizationCodeInterface; |
13
|
|
|
use OAuth2\Endpoints\AuthorizationEndpoint; |
14
|
|
|
use OAuth2\Endpoints\TokenEndpoint; |
15
|
|
|
use OAuth2\Exceptions\OAuthException; |
16
|
|
|
use OAuth2\GrantTypes\AbstractGrantType; |
17
|
|
|
//use OAuth2\Parameters\CodeParameterHandler; |
|
|
|
|
18
|
|
|
//use OAuth2\Parameters\ParameterHandlerInterface; |
19
|
|
|
use OAuth2\Storages\AccessTokenStorageInterface; |
20
|
|
|
use OAuth2\Storages\AuthorizationCodeStorageInterface; |
21
|
|
|
use OAuth2\Storages\RefreshTokenStorageInterface; |
22
|
|
|
|
23
|
|
|
class AuthorizationCodeFlow extends AbstractGrantType implements FlowInterface |
24
|
|
|
{ |
25
|
|
|
protected $authorizationCodeStorage; |
26
|
|
|
/* * |
27
|
|
|
* @var ParameterHandlerInterface[] |
28
|
|
|
*/ |
29
|
|
|
// protected $accessTokenRequestParameters = []; |
|
|
|
|
30
|
|
|
|
31
|
|
|
public function __construct(AuthorizationCodeStorageInterface $authorizationCodeStorage, |
32
|
|
|
AccessTokenStorageInterface $accessTokenStorage, |
33
|
|
|
RefreshTokenStorageInterface $refreshTokenStorage) |
34
|
|
|
{ |
35
|
|
|
parent::__construct($accessTokenStorage, $refreshTokenStorage); |
36
|
|
|
$this->authorizationCodeStorage = $authorizationCodeStorage; |
37
|
|
|
// $this->accessTokenRequestParameters = [ |
|
|
|
|
38
|
|
|
// 'code' => new CodeParameterHandler() |
39
|
|
|
// ]; |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
function getResponseTypes(): array |
|
|
|
|
43
|
|
|
{ |
44
|
|
|
return ['code']; |
|
|
|
|
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
function handleAuthorizationRequest(AuthorizationEndpoint $authorizationEndpoint, array $requestData): array |
|
|
|
|
48
|
|
|
{ |
49
|
|
|
$authorizationCode = $this->authorizationCodeStorage->create( |
50
|
|
|
implode(' ', $authorizationEndpoint->getScopes()), |
51
|
|
|
$authorizationEndpoint->getClient()->getIdentifier(), |
52
|
|
|
$authorizationEndpoint->getResourceOwner()->getIdentifier(), |
53
|
|
|
$requestData['scope'] ?? null, |
54
|
|
|
$requestData['redirect_uri'] ?? null |
55
|
|
|
); |
56
|
|
|
$this->authorizationCodeStorage->save($authorizationCode); |
57
|
|
|
return ['code' => $authorizationCode->getCode()]; |
58
|
|
|
// $authorizationCode = $this->createAuthorizationCode($authorizationEndpoint); |
|
|
|
|
59
|
|
|
// return $this->saveAndGetResult($authorizationCode); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/* |
|
|
|
|
63
|
|
|
protected function createAuthorizationCode(AuthorizationEndpoint $authorizationEndpoint) |
64
|
|
|
{ |
65
|
|
|
return $this->authorizationCodeStorage->create( |
66
|
|
|
implode(' ', $authorizationEndpoint->getScopes()), |
67
|
|
|
$authorizationEndpoint->getClient()->getIdentifier(), |
68
|
|
|
$authorizationEndpoint->getResourceOwner()->getIdentifier(), |
69
|
|
|
$requestData['scope'] ?? null, |
70
|
|
|
$requestData['redirect_uri'] ?? null |
71
|
|
|
); |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
protected function saveAndGetResult(AuthorizationCodeInterface $authorizationCode) |
75
|
|
|
{ |
76
|
|
|
$this->authorizationCodeStorage->save($authorizationCode); |
77
|
|
|
return ['code' => $authorizationCode->getCode()]; |
78
|
|
|
} |
79
|
|
|
*/ |
80
|
|
|
|
81
|
|
|
function getDefaultResponseMode(): string |
|
|
|
|
82
|
|
|
{ |
83
|
|
|
return 'query'; |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
function getUnsupportedResponseModes(): array |
|
|
|
|
87
|
|
|
{ |
88
|
|
|
return []; |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
function getGrantTypes(): array |
|
|
|
|
92
|
|
|
{ |
93
|
|
|
return ['authorization_code']; |
|
|
|
|
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
/** |
97
|
|
|
* @param TokenEndpoint $tokenEndpoint |
98
|
|
|
* @param array $requestData |
99
|
|
|
* @return array |
100
|
|
|
* @throws OAuthException |
101
|
|
|
*/ |
102
|
|
|
function handleAccessTokenRequest(TokenEndpoint $tokenEndpoint, array $requestData): array |
|
|
|
|
103
|
|
|
{ |
104
|
|
|
// foreach ($this->accessTokenRequestParameters as $accessTokenRequestParameter) { |
|
|
|
|
105
|
|
|
// $accessTokenRequestParameter->handle($tokenEndpoint, $requestData); |
106
|
|
|
// } |
107
|
|
|
if (empty($requestData['code'])) { |
108
|
|
|
throw new OAuthException('invalid_request', |
109
|
|
|
'The request is missing the required parameter code.', |
110
|
|
|
'https://tools.ietf.org/html/rfc7636#section-4.4'); |
111
|
|
|
} |
112
|
|
|
$code = $requestData['code']; |
113
|
|
|
|
114
|
|
|
$authorizationCode = $this->authorizationCodeStorage->find($code); |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* ensure that the authorization code was issued to the authenticated |
118
|
|
|
* confidential client, or if the client is public, ensure that the |
119
|
|
|
* code was issued to "client_id" in the request, |
120
|
|
|
*/ |
121
|
|
|
if (!$authorizationCode || $authorizationCode->getClientIdentifier() !== $tokenEndpoint->getClient()->getIdentifier()) { |
122
|
|
|
throw new OAuthException('invalid_grant', |
123
|
|
|
'The request includes the invalid parameter code.', |
124
|
|
|
'https://tools.ietf.org/html/rfc7636#section-4.4'); |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
$this->authorizationCodeStorage->revoke($code); |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* verify that the authorization code is valid |
131
|
|
|
*/ |
132
|
|
|
if ($this->authorizationCodeStorage->hasExpired($authorizationCode)) { |
133
|
|
|
throw new OAuthException('invalid_grant', |
134
|
|
|
'The request includes the invalid parameter code. The code has expired.', |
135
|
|
|
'https://tools.ietf.org/html/rfc7636#section-4.4'); |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* ensure that the "redirect_uri" parameter is present if the |
140
|
|
|
* "redirect_uri" parameter was included in the initial authorization |
141
|
|
|
* request as described in Section 4.1.1, and if included ensure that |
142
|
|
|
* their values are identical. |
143
|
|
|
*/ |
144
|
|
|
if ($authorizationCode->getRedirectUri()) { |
145
|
|
|
if (empty($requestData['redirect_uri'])) { |
146
|
|
|
throw new OAuthException('invalid_request', |
147
|
|
|
'The request is missing the required parameter redirect_uri', |
148
|
|
|
'https://tools.ietf.org/html/rfc7636#section-4.1'); |
149
|
|
|
} |
150
|
|
|
if ($requestData['redirect_uri'] !== $authorizationCode->getRedirectUri()) { |
151
|
|
|
throw new OAuthException('invalid_request', |
152
|
|
|
'The request includes the invalid parameter redirect_uri', |
153
|
|
|
'https://tools.ietf.org/html/rfc7636#section-4.1'); |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
return $this->issueTokens($authorizationCode->getScope(), |
158
|
|
|
$authorizationCode->getResourceOwnerIdentifier(), $authorizationCode->getCode()); |
159
|
|
|
} |
160
|
|
|
} |
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.