Skip to content

Commit 021bee3

Browse files
committed
feat: add idtoken to refresh_token grant
Change-Id: I8a772f58192cce9e7da6fffceff5bad19e55caed
1 parent 9a8356d commit 021bee3

File tree

9 files changed

+81
-38
lines changed

9 files changed

+81
-38
lines changed

app/Services/OAuth2/TokenService.php

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,9 +1338,9 @@ public function clearAccessTokensForRefreshToken($value, $is_hashed = false)
13381338
}
13391339

13401340
/**
1341-
* @param string $nonce
13421341
* @param string $client_id
13431342
* @param AccessToken|null $access_token
1343+
* @param string|null $nonce
13441344
* @param AuthorizationCode|null $auth_code
13451345
* @return IBasicJWT
13461346
* @throws AbsentClientException
@@ -1351,14 +1351,16 @@ public function clearAccessTokensForRefreshToken($value, $is_hashed = false)
13511351
*/
13521352
public function createIdToken
13531353
(
1354-
$nonce,
1355-
$client_id,
1354+
string $client_id,
13561355
AccessToken $access_token = null,
1357-
AuthorizationCode $auth_code = null
1358-
)
1356+
?string $nonce = null,
1357+
?AuthorizationCode $auth_code = null
1358+
):IBasicJWT
13591359
{
1360+
Log::debug(sprintf("TokenService::createIdToken client id is %s", $client_id));
1361+
13601362
$issuer = $this->configuration_service->getSiteUrl();
1361-
if (empty($issuer)) throw new ConfigurationException('missing idp url');
1363+
if (empty($issuer)) throw new ConfigurationException('Missing IDP URL.');
13621364

13631365
$client = $this->client_repository->getClientById($client_id);
13641366
$id_token_lifetime = $this->configuration_service->getConfigValue('OAuth2.IdToken.Lifetime');
@@ -1368,7 +1370,7 @@ public function createIdToken
13681370
(
13691371
sprintf
13701372
(
1371-
"client id %d does not exists!",
1373+
"Client id %d does not exists.",
13721374
$client_id
13731375
)
13741376
);
@@ -1378,7 +1380,13 @@ public function createIdToken
13781380

13791381
if (is_null($user)) {
13801382
$user_id = $this->principal_service->get()->getUserId();
1381-
Log::debug(sprintf("user id is %s", $user_id));
1383+
Log::debug(sprintf("TokenService::createIdToken user id is %s from principal service", $user_id));
1384+
$user = $this->auth_service->getUserById($user_id);
1385+
}
1386+
1387+
if(is_null($user) && !is_null($access_token)){
1388+
$user_id = $access_token->getUserId();
1389+
Log::debug(sprintf("TokenService::createIdToken user id is %s from access token", $user_id));
13821390
$user = $this->auth_service->getUserById($user_id);
13831391
}
13841392

@@ -1428,6 +1436,7 @@ public function createIdToken
14281436
if (!is_null($sig_alg) && !is_null($auth_code))
14291437
$this->buildAuthCodeHashClaim($auth_code, $sig_alg, $claim_set);
14301438

1439+
// auth_time claim
14311440
$this->buildAuthTimeClaim($claim_set);
14321441

14331442
return $this->id_token_builder->buildJWT($claim_set, $id_token_response_info, $client);

app/libs/OAuth2/Factories/OAuth2AccessTokenFragmentResponseFactory.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ static public function build
6363

6464
$id_token = $token_service->createIdToken
6565
(
66-
$request->getNonce(),
6766
$request->getClientId(),
68-
$access_token
67+
$access_token,
68+
$request->getNonce()
6969
);
7070
}
7171

app/libs/OAuth2/Factories/OAuth2AccessTokenResponseFactory.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ static public function build
7272

7373
$id_token = $token_service->createIdToken
7474
(
75-
$auth_code->getNonce(),
7675
$auth_code->getClientId(),
77-
$access_token
76+
$access_token,
77+
$auth_code->getNonce()
7878
);
7979
}
8080

@@ -86,9 +86,9 @@ static public function build
8686

8787
$id_token = $token_service->createIdToken
8888
(
89-
$auth_code->getNonce(),
9089
$auth_code->getClientId(),
91-
$access_token
90+
$access_token,
91+
$auth_code->getNonce()
9292
);
9393
}
9494

app/libs/OAuth2/GrantTypes/HybridGrantType.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,12 +204,11 @@ protected function buildResponse(OAuth2AuthorizationRequest $request, $has_forme
204204

205205
if (in_array(OAuth2Protocol::OAuth2Protocol_ResponseType_IdToken, $request->getResponseType(false)))
206206
{
207-
208207
$id_token = $this->token_service->createIdToken
209208
(
210-
$request->getNonce(),
211209
$request->getClientId(),
212210
$access_token,
211+
$request->getNonce(),
213212
$auth_code
214213
);
215214
}

app/libs/OAuth2/GrantTypes/PasswordlessGrantType.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,9 +381,9 @@ public function completeFlow(OAuth2Request $request)
381381

382382
$id_token = $this->token_service->createIdToken
383383
(
384-
$otp->getNonce(),
385384
$this->client->getClientId(),
386-
$access_token
385+
$access_token,
386+
$otp->getNonce()
387387
);
388388

389389
$refresh_token = $access_token->getRefreshToken();

app/libs/OAuth2/GrantTypes/RefreshBearerTokenGrantType.php

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@
1919
use OAuth2\Exceptions\UseRefreshTokenException;
2020
use OAuth2\Models\IClient;
2121
use OAuth2\Repositories\IClientRepository;
22+
use OAuth2\Responses\OAuth2AccessTokenResponse;
23+
use OAuth2\Responses\OAuth2IdTokenResponse;
2224
use OAuth2\Services\ITokenService;
2325
use OAuth2\OAuth2Protocol;
2426
use OAuth2\Requests\OAuth2RefreshAccessTokenRequest;
2527
use OAuth2\Requests\OAuth2Request;
2628
use OAuth2\Requests\OAuth2TokenRequest;
27-
use OAuth2\Responses\OAuth2AccessTokenResponse;
2829
use OAuth2\Responses\OAuth2Response;
2930
use OAuth2\Services\IClientService;
3031
use Utils\Services\ILogService;
@@ -169,15 +170,43 @@ public function completeFlow(OAuth2Request $request)
169170
$new_refresh_token = $this->token_service->createRefreshToken($access_token, true);
170171
}
171172

172-
$response = new OAuth2AccessTokenResponse
173+
// add id token on response ( new id token )
174+
// see https://openid.net/specs/openid-connect-core-1_0.html#RefreshingAccessToken
175+
// considerations
176+
// 1. if the ID Token contains an auth_time Claim, its value MUST represent the time of the original
177+
// authentication - not the time that the new ID token is issued.
178+
// 2. it SHOULD NOT have a nonce Claim, even when the ID Token issued at the time of the original authentication
179+
// contained nonce; however, if it is present, its value MUST be the same as in the ID Token issued at the
180+
// time of the original authentication
181+
$id_token = null;
182+
183+
$access_token_scopes = explode(' ', $access_token->getScope());
184+
if(in_array(OAuth2Protocol::OpenIdConnect_Scope,$access_token_scopes)) {
185+
186+
$id_token = $this->token_service->createIdToken
187+
(
188+
$this->current_client->getClientId(),
189+
$access_token
190+
);
191+
}
192+
193+
if(!is_null($id_token))
194+
return new OAuth2IdTokenResponse
195+
(
196+
$access_token->getValue(),
197+
$access_token->getLifetime(),
198+
$id_token->toCompactSerialization(),
199+
!is_null($new_refresh_token) ? $new_refresh_token->getValue() : null,
200+
$scope
201+
);
202+
203+
return new OAuth2AccessTokenResponse
173204
(
174205
$access_token->getValue(),
175206
$access_token->getLifetime(),
176207
!is_null($new_refresh_token) ? $new_refresh_token->getValue() : null,
177208
$scope
178209
);
179-
180-
return $response;
181210
}
182211

183212
/**

app/libs/OAuth2/Services/ITokenService.php

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,21 +179,20 @@ public function invalidateRefreshToken(string $value, bool $is_hashed = false, ?
179179
*/
180180
public function revokeRefreshToken(string $value, bool $is_hashed = false, ?User $current_user = null);
181181

182-
183182
/**
184-
* @param string $nonce
185183
* @param string $client_id
186184
* @param AccessToken|null $access_token
187-
* @param AuthorizationCode $auth_code
185+
* @param AuthorizationCode|null $auth_code
186+
* @param string|null $nonce
188187
* @return IBasicJWT
189188
*/
190189
public function createIdToken
191190
(
192-
$nonce,
193-
$client_id,
194-
AccessToken $access_token = null,
195-
AuthorizationCode $auth_code = null
196-
);
191+
string $client_id,
192+
?AccessToken $access_token = null,
193+
?string $nonce = null,
194+
?AuthorizationCode $auth_code = null
195+
):IBasicJWT;
197196

198197
/**
199198
* @param OAuth2PasswordlessAuthenticationRequest $request

database/seeds/TestSeeder.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ private function createTestUsers(){
235235
'first_name' => 'Sebastian',
236236
'last_name' => 'Marcet',
237237
'email' => '[email protected]',
238-
'password' => '1qaz2wsx',
238+
'password' => '1Qaz2wsx!',
239239
'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4,
240240
'gender' => 'male',
241241
'address1' => 'Av. Siempre Viva 111',
@@ -256,7 +256,7 @@ private function createTestUsers(){
256256
'first_name' => 'Sebastian',
257257
'last_name' => 'Marcet IDN',
258258
'email' => 'hei@やる.ca',
259-
'password' => '1qaz2wsx',
259+
'password' => '1Qaz2wsx!',
260260
'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4,
261261
'gender' => 'male',
262262
'address1' => 'Av. Siempre Viva 111',
@@ -277,7 +277,7 @@ private function createTestUsers(){
277277
'first_name' => 'Márton',
278278
'last_name' => 'Kiss',
279279
'email' => '[email protected]',
280-
'password' => '1qaz2wsx',
280+
'password' => '1Qaz2wsx!',
281281
'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4,
282282
'gender' => 'male',
283283
'address1' => 'Av. Siempre Viva 111',
@@ -298,7 +298,7 @@ private function createTestUsers(){
298298
'first_name' => '',
299299
'last_name' => '金刚',
300300
'email' => '[email protected]',
301-
'password' => '1qaz2wsx',
301+
'password' => '1Qaz2wsx!',
302302
'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4,
303303
'gender' => 'male',
304304
'address1' => 'Av. Siempre Viva 111',
@@ -319,7 +319,7 @@ private function createTestUsers(){
319319
'first_name' => 'Bharath',
320320
'last_name' => 'Kumar M R',
321321
'email' => '[email protected]',
322-
'password' => '1qaz2wsx',
322+
'password' => '1Qaz2wsx!',
323323
'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4,
324324
'gender' => 'male',
325325
'address1' => 'Av. Siempre Viva 111',
@@ -340,7 +340,7 @@ private function createTestUsers(){
340340
'first_name' => '大塚',
341341
'last_name' => '元央',
342342
'email' => '[email protected]',
343-
'password' => '1qaz2wsx',
343+
'password' => '1Qaz2wsx!',
344344
'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4,
345345
'gender' => 'male',
346346
'address1' => 'Av. Siempre Viva 111',
@@ -361,7 +361,7 @@ private function createTestUsers(){
361361
'first_name' => 'Ian Y.',
362362
'last_name' => 'Choi',
363363
'email' => '[email protected]',
364-
'password' => '1qaz2wsx',
364+
'password' => '1Qaz2wsx!',
365365
'password_enc' => \Auth\AuthHelper::AlgSHA1_V2_4,
366366
'gender' => 'male',
367367
'address1' => 'Av. Siempre Viva 111',
@@ -385,7 +385,7 @@ private function createTestUsers(){
385385
EntityManager::persist($user);
386386
$raw_password = $payload['password'];
387387
if(!$user->checkPassword($raw_password))
388-
throw new Exception("password verification failed !!!");
388+
throw new \Exception("password verification failed !!!");
389389
}
390390
EntityManager::flush();
391391
}

tests/OIDCPasswordlessTest.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,11 @@ public function testCodeInlineFlowComplete()
621621

622622
$this->assertTrue(!empty($refresh_token));
623623

624+
$id_token = $response->id_token;
625+
626+
$this->assertTrue(!empty($id_token));
627+
628+
624629
$params = [
625630
'refresh_token' => $refresh_token,
626631
'grant_type' => OAuth2Protocol::OAuth2Protocol_GrantType_RefreshToken,
@@ -643,9 +648,11 @@ public function testCodeInlineFlowComplete()
643648
//get new access token and new refresh token...
644649
$new_access_token = $response->access_token;
645650
$new_refresh_token = $response->refresh_token;
651+
$new_id_token = $response->id_token;
646652

647653
$this->assertTrue(!empty($new_access_token));
648654
$this->assertTrue(!empty($new_refresh_token));
655+
$this->assertTrue(!empty($new_id_token));
649656

650657
}
651658

0 commit comments

Comments
 (0)