1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Created by PhpStorm. |
4
|
|
|
* User: Alexandre |
5
|
|
|
* Date: 10/03/2018 |
6
|
|
|
* Time: 17:40 |
7
|
|
|
*/ |
8
|
|
|
|
9
|
|
|
namespace OAuth2\Extensions\OpenID\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\Extensions\OpenID\Credentials\AuthorizationCode; |
17
|
|
|
use OAuth2\Extensions\OpenID\IdTokenManager; |
18
|
|
|
use OAuth2\ResponseTypes\ResponseTypeInterface; |
19
|
|
|
use OAuth2\Storages\AccessTokenStorageInterface; |
20
|
|
|
use OAuth2\Storages\AuthorizationCodeStorageInterface; |
21
|
|
|
use OAuth2\Storages\ClientStorageInterface; |
22
|
|
|
use OAuth2\Storages\RefreshTokenStorageInterface; |
23
|
|
|
use OAuth2\Storages\ResourceOwnerStorageInterface; |
24
|
|
|
|
25
|
|
|
class AuthorizationCodeFlow extends \OAuth2\Flows\AuthorizationCodeFlow |
26
|
|
|
{ |
27
|
|
|
/** |
28
|
|
|
* @var IdTokenManager |
29
|
|
|
*/ |
30
|
|
|
private $idTokenManager; |
31
|
|
|
/** |
32
|
|
|
* @var ClientStorageInterface |
33
|
|
|
*/ |
34
|
|
|
private $clientStorage; |
35
|
|
|
/** |
36
|
|
|
* @var ResourceOwnerStorageInterface |
37
|
|
|
*/ |
38
|
|
|
private $resourceOwnerStorage; |
39
|
|
|
|
40
|
|
|
public function __construct(AuthorizationCodeStorageInterface $authorizationCodeStorage, |
41
|
|
|
AccessTokenStorageInterface $accessTokenStorage, |
42
|
|
|
RefreshTokenStorageInterface $refreshTokenStorage, |
43
|
|
|
ClientStorageInterface $clientStorage, |
44
|
|
|
ResourceOwnerStorageInterface $resourceOwnerStorage, |
45
|
|
|
IdTokenManager $idTokenManager) |
46
|
|
|
{ |
47
|
|
|
parent::__construct($authorizationCodeStorage, $accessTokenStorage, $refreshTokenStorage); |
48
|
|
|
$this->idTokenManager = $idTokenManager; |
49
|
|
|
$this->clientStorage = $clientStorage; |
50
|
|
|
$this->resourceOwnerStorage = $resourceOwnerStorage; |
51
|
|
|
} |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* @param AuthorizationEndpoint $authorizationEndpoint |
55
|
|
|
* @param array $requestData |
56
|
|
|
* @throws OAuthException |
57
|
|
|
*/ |
58
|
|
|
public function verifyAuthorizationRequest(AuthorizationEndpoint $authorizationEndpoint, array $requestData) |
59
|
|
|
{ |
60
|
|
|
parent::verifyAuthorizationRequest($authorizationEndpoint, $requestData); |
61
|
|
|
|
62
|
|
|
if (in_array('openid', $authorizationEndpoint->getScopes())) { |
63
|
|
|
if (!$authorizationEndpoint instanceof \OAuth2\Extensions\OpenID\Endpoints\AuthorizationEndpoint) { |
64
|
|
|
throw new \InvalidArgumentException(); |
65
|
|
|
} |
66
|
|
|
if (!$authorizationEndpoint->getNonce()) { |
67
|
|
|
throw new OAuthException('invalid_request', 'Nonce required'); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
if (empty($requestData['redirect_uri'])) { |
71
|
|
|
throw new OAuthException('invalid_request', 'The request is missing the required parameter redirect_uri.', |
72
|
|
|
'https://tools.ietf.org/html/rfc6749#section-4.1'); |
73
|
|
|
} |
74
|
|
|
} |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
// /** |
|
|
|
|
78
|
|
|
// * @param AuthorizationEndpoint $authorizationEndpoint |
79
|
|
|
// * @param array $requestData |
80
|
|
|
// * @return array |
81
|
|
|
// */ |
82
|
|
|
// public function handleAuthorizationRequest(AuthorizationEndpoint $authorizationEndpoint, array $requestData): array |
83
|
|
|
// { |
84
|
|
|
// $authorizationCode = $this->createAuthorizationCode($authorizationEndpoint); |
85
|
|
|
// return ['code' => $authorizationCode->getCode()]; |
86
|
|
|
// } |
87
|
|
|
|
88
|
|
|
/** |
89
|
|
|
* @param TokenEndpoint $tokenEndpoint |
90
|
|
|
* @param array $requestData |
91
|
|
|
* @return array |
92
|
|
|
* @throws OAuthException |
93
|
|
|
*/ |
94
|
|
|
public function handleAccessTokenRequest(TokenEndpoint $tokenEndpoint, array $requestData): array |
95
|
|
|
{ |
96
|
|
|
$tokens = parent::handleAccessTokenRequest($tokenEndpoint, $requestData); |
97
|
|
|
|
98
|
|
|
if (in_array('openid', explode(' ', $this->authorizationCode->getScope()))) { |
99
|
|
|
|
100
|
|
|
$resourceOwnerIdentifier = $this->authorizationCode->getResourceOwnerIdentifier(); |
101
|
|
|
|
102
|
|
|
if(!is_string($resourceOwnerIdentifier)) { |
|
|
|
|
103
|
|
|
throw new OAuthException('server_error', |
104
|
|
|
'The authorization server encountered an unexpected condition that prevented it from fulfilling |
105
|
|
|
the request. The resource owner identifier of this authorization code is invalid.', |
106
|
|
|
'https://tools.ietf.org/html/rfc7636#section-4.4'); |
107
|
|
|
} |
108
|
|
|
|
109
|
|
|
$resourceOwner = $this->resourceOwnerStorage->get($resourceOwnerIdentifier); |
110
|
|
|
if (!$resourceOwner) { |
111
|
|
|
throw new OAuthException('server_error', |
112
|
|
|
'The authorization server encountered an unexpected condition that prevented it from fulfilling |
113
|
|
|
the request. The resource owner of this authorization code is missing.', |
114
|
|
|
'https://tools.ietf.org/html/rfc7636#section-4.4'); |
115
|
|
|
} |
116
|
|
|
|
117
|
|
|
$claims = []; |
118
|
|
|
|
119
|
|
|
$idToken = $this->idTokenManager->issueIdToken( |
120
|
|
|
$this->clientStorage->get($this->authorizationCode->getClientIdentifier()), |
121
|
|
|
$resourceOwner, |
122
|
|
|
$claims |
123
|
|
|
); |
124
|
|
|
$tokens['id_token'] = $idToken; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
return $tokens; |
128
|
|
|
} |
129
|
|
|
// |
|
|
|
|
130
|
|
|
// protected function createAuthorizationCode(AuthorizationEndpoint $authorizationEndpoint) |
131
|
|
|
// { |
132
|
|
|
// return $this->authorizationCodeStorage->generate( |
133
|
|
|
// implode(' ', $authorizationEndpoint->getScopes()), |
134
|
|
|
// $authorizationEndpoint->getClient()->getIdentifier(), |
135
|
|
|
// $authorizationEndpoint->getResourceOwner()->getIdentifier(), |
136
|
|
|
// $requestData['scope'] ?? null, |
137
|
|
|
// $requestData['redirect_uri'] ?? null |
138
|
|
|
// ); |
139
|
|
|
// } |
140
|
|
|
|
141
|
|
|
} |
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.