Skip to content

Commit eb9c2e7

Browse files
committed
fix(oauth): rotate the auth token only if the access token rotation was successful
Signed-off-by: Julien Veyssier <julien-nc@posteo.net>
1 parent 3c982dd commit eb9c2e7

2 files changed

Lines changed: 19 additions & 36 deletions

File tree

apps/oauth2/lib/Controller/OauthApiController.php

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -182,21 +182,9 @@ public function getToken(
182182
$redeemedThrottleReason = $grant_type === 'authorization_code'
183183
? 'authorization_code_already_redeemed'
184184
: 'refresh_token_already_redeemed';
185-
$tokenRotated = false;
186185

187186
$this->db->beginTransaction();
188187
try {
189-
$appToken = $this->tokenProvider->rotate(
190-
$appToken,
191-
$decryptedToken,
192-
$newToken
193-
);
194-
$tokenRotated = true;
195-
196-
// Expiration is in 1 hour again
197-
$appToken->setExpires($this->time->getTime() + 3600);
198-
$this->tokenProvider->updateToken($appToken);
199-
200188
$updatedRows = $this->accessTokenMapper->rotateToken(
201189
$accessToken->getId(),
202190
$code,
@@ -207,25 +195,31 @@ public function getToken(
207195

208196
if ($updatedRows !== 1) {
209197
$this->db->rollBack();
210-
// tokenProvider->rotate() updates the auth token cache, so we have to clear the new token on rollback
211-
$this->tokenProvider->invalidateToken($newToken);
212198
$response = new JSONResponse([
213199
'error' => 'invalid_request',
214200
], Http::STATUS_BAD_REQUEST);
215201
$response->throttle(['invalid_request' => $redeemedThrottleReason]);
216202
return $response;
217203
}
218204

205+
$appToken = $this->tokenProvider->rotate(
206+
$appToken,
207+
$decryptedToken,
208+
$newToken
209+
);
210+
211+
// Expiration is in 1 hour again
212+
$appToken->setExpires($this->time->getTime() + 3600);
213+
$this->tokenProvider->updateToken($appToken);
214+
219215
$this->db->commit();
220216
} catch (\Throwable $e) {
221217
if ($this->db->inTransaction()) {
222218
$this->db->rollBack();
223219
}
224-
225-
if ($tokenRotated) {
226-
// tokenProvider->rotate() updates the auth token cache, so we have to clear the new token on rollback
227-
$this->tokenProvider->invalidateToken($newToken);
228-
}
220+
// rotate() and updateToken() write the auth token to the cache,
221+
// so if we are past rotate() we must invalidate the new token
222+
$this->tokenProvider->invalidateToken($newToken);
229223

230224
throw $e;
231225
}

apps/oauth2/tests/Controller/OauthApiControllerTest.php

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -693,20 +693,14 @@ public function testRefreshTokenRedeemedConcurrently(): void {
693693
return 'random' . $len;
694694
});
695695

696-
$this->tokenProvider->expects($this->once())
697-
->method('rotate')
698-
->with(
699-
$appToken,
700-
'decryptedToken',
701-
'random72'
702-
)->willReturn($appToken);
696+
$this->tokenProvider->expects($this->never())
697+
->method('rotate');
703698

704699
$this->time->method('getTime')
705700
->willReturn(1000);
706701

707-
$this->tokenProvider->expects($this->once())
708-
->method('updateToken')
709-
->with($this->isInstanceOf(PublicKeyToken::class));
702+
$this->tokenProvider->expects($this->never())
703+
->method('updateToken');
710704

711705
$this->crypto->method('encrypt')
712706
->with('random72', 'random128')
@@ -718,16 +712,11 @@ public function testRefreshTokenRedeemedConcurrently(): void {
718712
$this->db->expects($this->never())
719713
->method('commit');
720714

721-
$this->db->expects($this->exactly(2))
722-
->method('inTransaction')
723-
->willReturnOnConsecutiveCalls(true, false);
724-
725715
$this->db->expects($this->once())
726716
->method('rollBack');
727717

728-
$this->tokenProvider->expects($this->once())
729-
->method('invalidateToken')
730-
->with('random72');
718+
$this->tokenProvider->expects($this->never())
719+
->method('invalidateToken');
731720

732721
$this->accessTokenMapper->expects($this->once())
733722
->method('rotateToken')

0 commit comments

Comments
 (0)