the browser-facing portion of osu!
at master 4.0 kB view raw
1<?php 2 3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 4// See the LICENCE file in the repository root for full licence text. 5 6namespace Tests\Controllers\OAuth; 7 8use App\Libraries\OAuth\EncodeToken; 9use App\Mail\UserVerification as UserVerificationMail; 10use App\Models\OAuth\Client; 11use App\Models\OAuth\Token; 12use App\Models\User; 13use Database\Factories\OAuth\ClientFactory; 14use Database\Factories\OAuth\RefreshTokenFactory; 15use Database\Factories\UserFactory; 16use Tests\TestCase; 17 18class TokensControllerTest extends TestCase 19{ 20 public static function dataProviderForTestIssueTokenWithRefreshTokenInheritsVerified(): array 21 { 22 return [ 23 [true], 24 [false], 25 ]; 26 } 27 28 public function testDestroyCurrent() 29 { 30 $refreshToken = (new RefreshTokenFactory())->create(); 31 $token = $refreshToken->accessToken; 32 33 $this 34 ->actingWithToken($token) 35 ->json('DELETE', route('api.oauth.tokens.current')) 36 ->assertSuccessful(); 37 38 $this->assertTrue($token->fresh()->revoked); 39 $this->assertTrue($refreshToken->fresh()->revoked); 40 } 41 42 public function testDestroyCurrentClientGrant() 43 { 44 $token = Token::factory()->create(['user_id' => null]); 45 46 $this 47 ->actingWithToken($token) 48 ->json('DELETE', route('api.oauth.tokens.current')) 49 ->assertSuccessful(); 50 51 $this->assertTrue($token->fresh()->revoked); 52 } 53 54 public function testIssueTokenWithPassword(): void 55 { 56 \Mail::fake(); 57 58 $user = User::factory()->create(); 59 $client = (new ClientFactory())->create([ 60 'password_client' => true, 61 ]); 62 63 $this->expectCountChange(fn () => $user->tokens()->count(), 1); 64 65 $tokenJson = $this->json('POST', route('oauth.passport.token'), [ 66 'grant_type' => 'password', 67 'client_id' => $client->getKey(), 68 'client_secret' => $client->secret, 69 'scope' => '*', 70 'username' => $user->username, 71 'password' => UserFactory::DEFAULT_PASSWORD, 72 ])->assertSuccessful() 73 ->decodeResponseJson(); 74 75 $this->json('GET', route('api.me'), [], [ 76 'Authorization' => "Bearer {$tokenJson['access_token']}", 77 ])->assertSuccessful() 78 ->assertJsonPath('session_verified', false); 79 80 // unverified access to api should trigger this but not necessarily return 401 81 \Mail::assertQueued(UserVerificationMail::class); 82 } 83 84 /** 85 * @dataProvider dataProviderForTestIssueTokenWithRefreshTokenInheritsVerified 86 */ 87 public function testIssueTokenWithRefreshTokenInheritsVerified(bool $verified): void 88 { 89 \Mail::fake(); 90 91 $client = Client::factory()->create(['password_client' => true]); 92 $accessToken = Token::factory()->create([ 93 'client_id' => $client, 94 'scopes' => ['*'], 95 'verified' => $verified, 96 ]); 97 $refreshToken = (new RefreshTokenFactory()) 98 ->create(['access_token_id' => $accessToken]); 99 $refreshTokenString = EncodeToken::encodeRefreshToken($refreshToken, $accessToken); 100 $user = $accessToken->user; 101 102 $this->expectCountChange(fn () => $user->tokens()->count(), 1); 103 104 $tokenJson = $this->json('POST', route('oauth.passport.token'), [ 105 'grant_type' => 'refresh_token', 106 'client_id' => $client->getKey(), 107 'client_secret' => $client->secret, 108 'refresh_token' => $refreshTokenString, 109 'scope' => implode(' ', $accessToken->scopes), 110 ])->assertSuccessful() 111 ->decodeResponseJson(); 112 113 $this->json('GET', route('api.me'), [], [ 114 'Authorization' => "Bearer {$tokenJson['access_token']}", 115 ])->assertSuccessful() 116 ->assertJsonPath('session_verified', $verified); 117 118 \Mail::assertQueued(UserVerificationMail::class, $verified ? 0 : 1); 119 } 120}