1919use OCP \AppFramework \Http ;
2020use OCP \AppFramework \Http \JSONResponse ;
2121use OCP \AppFramework \Utility \ITimeFactory ;
22+ use OCP \IDBConnection ;
2223use OCP \IRequest ;
2324use OCP \Security \Bruteforce \IThrottler ;
2425use OCP \Security \ICrypto ;
@@ -52,6 +53,8 @@ class OauthApiControllerTest extends TestCase {
5253 private $ logger ;
5354 /** @var ITimeFactory|\PHPUnit\Framework\MockObject\MockObject */
5455 private $ timeFactory ;
56+ /** @var IDBConnection|\PHPUnit\Framework\MockObject\MockObject */
57+ private $ db ;
5558 /** @var OauthApiController */
5659 private $ oauthApiController ;
5760
@@ -68,6 +71,7 @@ protected function setUp(): void {
6871 $ this ->throttler = $ this ->createMock (IThrottler::class);
6972 $ this ->logger = $ this ->createMock (LoggerInterface::class);
7073 $ this ->timeFactory = $ this ->createMock (ITimeFactory::class);
74+ $ this ->db = $ this ->createMock (IDBConnection::class);
7175
7276 $ this ->oauthApiController = new OauthApiController (
7377 'oauth2 ' ,
@@ -80,7 +84,8 @@ protected function setUp(): void {
8084 $ this ->time ,
8185 $ this ->logger ,
8286 $ this ->throttler ,
83- $ this ->timeFactory
87+ $ this ->timeFactory ,
88+ $ this ->db ,
8489 );
8590 }
8691
@@ -315,6 +320,7 @@ public function testRefreshTokenInvalidAppToken(): void {
315320
316321 public function testRefreshTokenValidAppToken (): void {
317322 $ accessToken = new AccessToken ();
323+ $ accessToken ->setId (21 );
318324 $ accessToken ->setClientId (42 );
319325 $ accessToken ->setTokenId (1337 );
320326 $ accessToken ->setEncryptedToken ('encryptedToken ' );
@@ -366,6 +372,18 @@ public function testRefreshTokenValidAppToken(): void {
366372 $ this ->time ->method ('getTime ' )
367373 ->willReturn (1000 );
368374
375+ $ this ->db ->expects ($ this ->once ())
376+ ->method ('beginTransaction ' );
377+
378+ $ this ->db ->expects ($ this ->once ())
379+ ->method ('commit ' );
380+
381+ $ this ->db ->expects ($ this ->never ())
382+ ->method ('rollBack ' );
383+
384+ $ this ->tokenProvider ->expects ($ this ->never ())
385+ ->method ('invalidateToken ' );
386+
369387 $ this ->tokenProvider ->expects ($ this ->once ())
370388 ->method ('updateToken ' )
371389 ->with (
@@ -379,13 +397,14 @@ public function testRefreshTokenValidAppToken(): void {
379397 ->willReturn ('newEncryptedToken ' );
380398
381399 $ this ->accessTokenMapper ->expects ($ this ->once ())
382- ->method ('update ' )
400+ ->method ('rotateToken ' )
383401 ->with (
384- $ this ->callback (function (AccessToken $ token ) {
385- return $ token ->getHashedCode () === hash ('sha512 ' , 'random128 ' ) &&
386- $ token ->getEncryptedToken () === 'newEncryptedToken ' ;
387- })
388- );
402+ 21 ,
403+ 'validrefresh ' ,
404+ 'random128 ' ,
405+ 'newEncryptedToken ' ,
406+ false ,
407+ )->willReturn (1 );
389408
390409 $ expected = new JSONResponse ([
391410 'access_token ' => 'random72 ' ,
@@ -411,6 +430,7 @@ public function testRefreshTokenValidAppToken(): void {
411430
412431 public function testRefreshTokenValidAppTokenBasicAuth (): void {
413432 $ accessToken = new AccessToken ();
433+ $ accessToken ->setId (21 );
414434 $ accessToken ->setClientId (42 );
415435 $ accessToken ->setTokenId (1337 );
416436 $ accessToken ->setEncryptedToken ('encryptedToken ' );
@@ -462,6 +482,18 @@ public function testRefreshTokenValidAppTokenBasicAuth(): void {
462482 $ this ->time ->method ('getTime ' )
463483 ->willReturn (1000 );
464484
485+ $ this ->db ->expects ($ this ->once ())
486+ ->method ('beginTransaction ' );
487+
488+ $ this ->db ->expects ($ this ->once ())
489+ ->method ('commit ' );
490+
491+ $ this ->db ->expects ($ this ->never ())
492+ ->method ('rollBack ' );
493+
494+ $ this ->tokenProvider ->expects ($ this ->never ())
495+ ->method ('invalidateToken ' );
496+
465497 $ this ->tokenProvider ->expects ($ this ->once ())
466498 ->method ('updateToken ' )
467499 ->with (
@@ -475,13 +507,14 @@ public function testRefreshTokenValidAppTokenBasicAuth(): void {
475507 ->willReturn ('newEncryptedToken ' );
476508
477509 $ this ->accessTokenMapper ->expects ($ this ->once ())
478- ->method ('update ' )
510+ ->method ('rotateToken ' )
479511 ->with (
480- $ this ->callback (function (AccessToken $ token ) {
481- return $ token ->getHashedCode () === hash ('sha512 ' , 'random128 ' ) &&
482- $ token ->getEncryptedToken () === 'newEncryptedToken ' ;
483- })
484- );
512+ 21 ,
513+ 'validrefresh ' ,
514+ 'random128 ' ,
515+ 'newEncryptedToken ' ,
516+ false ,
517+ )->willReturn (1 );
485518
486519 $ expected = new JSONResponse ([
487520 'access_token ' => 'random72 ' ,
@@ -510,6 +543,7 @@ public function testRefreshTokenValidAppTokenBasicAuth(): void {
510543
511544 public function testRefreshTokenExpiredAppToken (): void {
512545 $ accessToken = new AccessToken ();
546+ $ accessToken ->setId (21 );
513547 $ accessToken ->setClientId (42 );
514548 $ accessToken ->setTokenId (1337 );
515549 $ accessToken ->setEncryptedToken ('encryptedToken ' );
@@ -561,6 +595,18 @@ public function testRefreshTokenExpiredAppToken(): void {
561595 $ this ->time ->method ('getTime ' )
562596 ->willReturn (1000 );
563597
598+ $ this ->db ->expects ($ this ->once ())
599+ ->method ('beginTransaction ' );
600+
601+ $ this ->db ->expects ($ this ->once ())
602+ ->method ('commit ' );
603+
604+ $ this ->db ->expects ($ this ->never ())
605+ ->method ('rollBack ' );
606+
607+ $ this ->tokenProvider ->expects ($ this ->never ())
608+ ->method ('invalidateToken ' );
609+
564610 $ this ->tokenProvider ->expects ($ this ->once ())
565611 ->method ('updateToken ' )
566612 ->with (
@@ -574,13 +620,14 @@ public function testRefreshTokenExpiredAppToken(): void {
574620 ->willReturn ('newEncryptedToken ' );
575621
576622 $ this ->accessTokenMapper ->expects ($ this ->once ())
577- ->method ('update ' )
623+ ->method ('rotateToken ' )
578624 ->with (
579- $ this ->callback (function (AccessToken $ token ) {
580- return $ token ->getHashedCode () === hash ('sha512 ' , 'random128 ' ) &&
581- $ token ->getEncryptedToken () === 'newEncryptedToken ' ;
582- })
583- );
625+ 21 ,
626+ 'validrefresh ' ,
627+ 'random128 ' ,
628+ 'newEncryptedToken ' ,
629+ false ,
630+ )->willReturn (1 );
584631
585632 $ expected = new JSONResponse ([
586633 'access_token ' => 'random72 ' ,
@@ -603,4 +650,89 @@ public function testRefreshTokenExpiredAppToken(): void {
603650
604651 $ this ->assertEquals ($ expected , $ this ->oauthApiController ->getToken ('refresh_token ' , null , 'validrefresh ' , 'clientId ' , 'clientSecret ' ));
605652 }
653+
654+ public function testRefreshTokenRedeemedConcurrently (): void {
655+ $ expected = new JSONResponse ([
656+ 'error ' => 'invalid_request ' ,
657+ ], Http::STATUS_BAD_REQUEST );
658+ $ expected ->throttle (['invalid_request ' => 'refresh_token_already_redeemed ' ]);
659+
660+ $ accessToken = new AccessToken ();
661+ $ accessToken ->setId (21 );
662+ $ accessToken ->setClientId (42 );
663+ $ accessToken ->setTokenId (1337 );
664+ $ accessToken ->setEncryptedToken ('encryptedToken ' );
665+
666+ $ this ->accessTokenMapper ->method ('getByCode ' )
667+ ->with ('validrefresh ' )
668+ ->willReturn ($ accessToken );
669+
670+ $ client = new Client ();
671+ $ client ->setClientIdentifier ('clientId ' );
672+ $ client ->setSecret (bin2hex ('hashedClientSecret ' ));
673+ $ this ->clientMapper ->method ('getByUid ' )
674+ ->with (42 )
675+ ->willReturn ($ client );
676+
677+ $ this ->crypto
678+ ->method ('decrypt ' )
679+ ->with ('encryptedToken ' )
680+ ->willReturn ('decryptedToken ' );
681+
682+ $ this ->crypto
683+ ->method ('calculateHMAC ' )
684+ ->with ('clientSecret ' )
685+ ->willReturn ('hashedClientSecret ' );
686+
687+ $ appToken = new PublicKeyToken ();
688+ $ appToken ->setUid ('userId ' );
689+ $ this ->tokenProvider ->method ('getTokenById ' )
690+ ->with (1337 )
691+ ->willReturn ($ appToken );
692+
693+ $ this ->secureRandom ->method ('generate ' )
694+ ->willReturnCallback (function ($ len ) {
695+ return 'random ' . $ len ;
696+ });
697+
698+ $ this ->tokenProvider ->expects ($ this ->never ())
699+ ->method ('rotate ' );
700+
701+ $ this ->time ->method ('getTime ' )
702+ ->willReturn (1000 );
703+
704+ $ this ->tokenProvider ->expects ($ this ->never ())
705+ ->method ('updateToken ' );
706+
707+ $ this ->crypto ->method ('encrypt ' )
708+ ->with ('random72 ' , 'random128 ' )
709+ ->willReturn ('newEncryptedToken ' );
710+
711+ $ this ->db ->expects ($ this ->once ())
712+ ->method ('beginTransaction ' );
713+
714+ $ this ->db ->expects ($ this ->never ())
715+ ->method ('commit ' );
716+
717+ $ this ->db ->expects ($ this ->once ())
718+ ->method ('rollBack ' );
719+
720+ $ this ->tokenProvider ->expects ($ this ->never ())
721+ ->method ('invalidateToken ' );
722+
723+ $ this ->accessTokenMapper ->expects ($ this ->once ())
724+ ->method ('rotateToken ' )
725+ ->with (
726+ 21 ,
727+ 'validrefresh ' ,
728+ 'random128 ' ,
729+ 'newEncryptedToken ' ,
730+ false ,
731+ )->willReturn (0 );
732+
733+ $ this ->throttler ->expects ($ this ->never ())
734+ ->method ('resetDelay ' );
735+
736+ $ this ->assertEquals ($ expected , $ this ->oauthApiController ->getToken ('refresh_token ' , null , 'validrefresh ' , 'clientId ' , 'clientSecret ' ));
737+ }
606738}
0 commit comments