1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* @author Alex Bilbie <[email protected]> |
4
|
|
|
* @copyright Copyright (c) Alex Bilbie |
5
|
|
|
* @license http://mit-license.org/ |
6
|
|
|
* |
7
|
|
|
* @link https://github.com/thephpleague/oauth2-server |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
namespace League\OAuth2\Server\Grant; |
11
|
|
|
|
12
|
|
|
use League\OAuth2\Server\Entities\ClientEntityInterface; |
13
|
|
|
use League\OAuth2\Server\Entities\UserEntityInterface; |
14
|
|
|
use League\OAuth2\Server\Exception\OAuthServerException; |
15
|
|
|
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface; |
16
|
|
|
use League\OAuth2\Server\RequestEvent; |
17
|
|
|
use League\OAuth2\Server\RequestTypes\AuthorizationRequest; |
18
|
|
|
use League\OAuth2\Server\ResponseTypes\RedirectResponse; |
19
|
|
|
use League\OAuth2\Server\ResponseTypes\ResponseTypeInterface; |
20
|
|
|
use Psr\Http\Message\ServerRequestInterface; |
21
|
|
|
|
22
|
|
|
class ImplicitGrant extends AbstractAuthorizeGrant |
23
|
|
|
{ |
24
|
|
|
/** |
25
|
|
|
* @var \DateInterval |
26
|
|
|
*/ |
27
|
|
|
private $accessTokenTTL; |
28
|
|
|
|
29
|
|
|
/** |
30
|
|
|
* @param \DateInterval $accessTokenTTL |
31
|
|
|
*/ |
32
|
|
|
public function __construct(\DateInterval $accessTokenTTL) |
33
|
|
|
{ |
34
|
|
|
$this->accessTokenTTL = $accessTokenTTL; |
35
|
|
|
} |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @param \DateInterval $refreshTokenTTL |
39
|
|
|
* |
40
|
|
|
* @throw \LogicException |
41
|
|
|
*/ |
42
|
|
|
public function setRefreshTokenTTL(\DateInterval $refreshTokenTTL) |
43
|
|
|
{ |
44
|
|
|
throw new \LogicException('The Implicit Grant does nto return refresh tokens'); |
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @param \League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface $refreshTokenRepository |
49
|
|
|
* |
50
|
|
|
* @throw \LogicException |
51
|
|
|
*/ |
52
|
|
|
public function setRefreshTokenRepository(RefreshTokenRepositoryInterface $refreshTokenRepository) |
53
|
|
|
{ |
54
|
|
|
throw new \LogicException('The Implicit Grant does nto return refresh tokens'); |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* {@inheritdoc} |
59
|
|
|
*/ |
60
|
|
|
public function canRespondToAccessTokenRequest(ServerRequestInterface $request) |
61
|
|
|
{ |
62
|
|
|
return false; |
63
|
|
|
} |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Return the grant identifier that can be used in matching up requests. |
67
|
|
|
* |
68
|
|
|
* @return string |
69
|
|
|
*/ |
70
|
|
|
public function getIdentifier() |
71
|
|
|
{ |
72
|
|
|
return 'implicit'; |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Respond to an incoming request. |
77
|
|
|
* |
78
|
|
|
* @param \Psr\Http\Message\ServerRequestInterface $request |
79
|
|
|
* @param \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface $responseType |
80
|
|
|
* @param \DateInterval $accessTokenTTL |
81
|
|
|
* |
82
|
|
|
* @return \League\OAuth2\Server\ResponseTypes\ResponseTypeInterface |
83
|
|
|
*/ |
84
|
|
|
public function respondToAccessTokenRequest( |
85
|
|
|
ServerRequestInterface $request, |
86
|
|
|
ResponseTypeInterface $responseType, |
87
|
|
|
\DateInterval $accessTokenTTL |
88
|
|
|
) { |
89
|
|
|
throw new \LogicException('This grant does not used this method'); |
90
|
|
|
} |
91
|
|
|
|
92
|
|
|
/** |
93
|
|
|
* {@inheritdoc} |
94
|
|
|
*/ |
95
|
|
|
public function canRespondToAuthorizationRequest(ServerRequestInterface $request) |
96
|
|
|
{ |
97
|
|
|
return ( |
98
|
|
|
array_key_exists('response_type', $request->getQueryParams()) |
99
|
|
|
&& $request->getQueryParams()['response_type'] === 'token' |
100
|
|
|
&& isset($request->getQueryParams()['client_id']) |
101
|
|
|
); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
/** |
105
|
|
|
* {@inheritdoc} |
106
|
|
|
*/ |
107
|
|
|
public function validateAuthorizationRequest(ServerRequestInterface $request) |
108
|
|
|
{ |
109
|
|
|
$clientId = $this->getQueryStringParameter( |
110
|
|
|
'client_id', |
111
|
|
|
$request, |
112
|
|
|
$this->getServerParameter('PHP_AUTH_USER', $request) |
113
|
|
|
); |
114
|
|
|
if (is_null($clientId)) { |
115
|
|
|
throw OAuthServerException::invalidRequest('client_id'); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
$client = $this->clientRepository->getClientEntity( |
119
|
|
|
$clientId, |
120
|
|
|
$this->getIdentifier() |
121
|
|
|
); |
122
|
|
|
|
123
|
|
|
if ($client instanceof ClientEntityInterface === false) { |
124
|
|
|
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request)); |
125
|
|
|
throw OAuthServerException::invalidClient(); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
$redirectUri = $this->getQueryStringParameter('redirect_uri', $request); |
129
|
|
|
if ($redirectUri !== null) { |
130
|
|
|
if ( |
131
|
|
|
is_string($client->getRedirectUri()) |
132
|
|
|
&& (strcmp($client->getRedirectUri(), $redirectUri) !== 0) |
133
|
|
|
) { |
134
|
|
|
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request)); |
135
|
|
|
throw OAuthServerException::invalidClient(); |
136
|
|
|
} elseif ( |
137
|
|
|
is_array($client->getRedirectUri()) |
138
|
|
|
&& in_array($redirectUri, $client->getRedirectUri()) === false |
139
|
|
|
) { |
140
|
|
|
$this->getEmitter()->emit(new RequestEvent('client.authentication.failed', $request)); |
141
|
|
|
throw OAuthServerException::invalidClient(); |
142
|
|
|
} |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
$scopes = $this->validateScopes( |
146
|
|
|
$this->getQueryStringParameter('scope', $request), |
147
|
|
|
$client->getRedirectUri() |
|
|
|
|
148
|
|
|
); |
149
|
|
|
|
150
|
|
|
$stateParameter = $this->getQueryStringParameter('state', $request); |
151
|
|
|
|
152
|
|
|
$authorizationRequest = new AuthorizationRequest(); |
153
|
|
|
$authorizationRequest->setGrantTypeId($this->getIdentifier()); |
154
|
|
|
$authorizationRequest->setClient($client); |
155
|
|
|
$authorizationRequest->setRedirectUri($redirectUri); |
156
|
|
|
$authorizationRequest->setState($stateParameter); |
157
|
|
|
$authorizationRequest->setScopes($scopes); |
158
|
|
|
|
159
|
|
|
return $authorizationRequest; |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* {@inheritdoc} |
164
|
|
|
*/ |
165
|
|
|
public function completeAuthorizationRequest(AuthorizationRequest $authorizationRequest) |
166
|
|
|
{ |
167
|
|
|
if ($authorizationRequest->getUser() instanceof UserEntityInterface === false) { |
168
|
|
|
throw new \LogicException('An instance of UserEntityInterface should be set on the AuthorizationRequest'); |
169
|
|
|
} |
170
|
|
|
|
171
|
|
|
$finalRedirectUri = ($authorizationRequest->getRedirectUri() === null) |
172
|
|
|
? is_array($authorizationRequest->getClient()->getRedirectUri()) |
173
|
|
|
? $authorizationRequest->getClient()->getRedirectUri()[0] |
174
|
|
|
: $authorizationRequest->getClient()->getRedirectUri() |
175
|
|
|
: $authorizationRequest->getRedirectUri(); |
176
|
|
|
|
177
|
|
|
// The user approved the client, redirect them back with an access token |
178
|
|
|
if ($authorizationRequest->isAuthorizationApproved() === true) { |
179
|
|
|
$accessToken = $this->issueAccessToken( |
180
|
|
|
$this->accessTokenTTL, |
181
|
|
|
$authorizationRequest->getClient(), |
182
|
|
|
$authorizationRequest->getUser()->getIdentifier(), |
183
|
|
|
$authorizationRequest->getScopes() |
184
|
|
|
); |
185
|
|
|
|
186
|
|
|
$redirectPayload['access_token'] = (string) $accessToken->convertToJWT($this->privateKey); |
|
|
|
|
187
|
|
|
$redirectPayload['token_type'] = 'bearer'; |
188
|
|
|
$redirectPayload['expires_in'] = $accessToken->getExpiryDateTime()->getTimestamp() - (new \DateTime())->getTimestamp(); |
189
|
|
|
|
190
|
|
|
$response = new RedirectResponse(); |
191
|
|
|
$response->setRedirectUri( |
192
|
|
|
$this->makeRedirectUri( |
193
|
|
|
$finalRedirectUri, |
194
|
|
|
$redirectPayload, |
195
|
|
|
'#' |
196
|
|
|
) |
197
|
|
|
); |
198
|
|
|
|
199
|
|
|
return $response; |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
// The user denied the client, redirect them back with an error |
203
|
|
|
throw OAuthServerException::accessDenied( |
204
|
|
|
'The user denied the request', |
205
|
|
|
$finalRedirectUri |
206
|
|
|
); |
207
|
|
|
} |
208
|
|
|
} |
209
|
|
|
|
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.