Skip to content

Commit f7fc673

Browse files
committed
Ensure tokens are found in the database using the expected logic
1 parent e9c633f commit f7fc673

File tree

5 files changed

+39
-25
lines changed

5 files changed

+39
-25
lines changed

app/Exceptions/Handler.php

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,18 @@ class Handler extends ExceptionHandler
4747
ValidationException::class,
4848
];
4949

50+
/**
51+
* Maps exceptions to a specific response code. This handles special exception
52+
* types that don't have a defined response code.
53+
*
54+
* @var array<string, int>
55+
*/
56+
protected static array $exceptionResponseCodes = [
57+
AuthenticationException::class => 401,
58+
AuthorizationException::class => 403,
59+
ValidationException::class => 422,
60+
];
61+
5062
/**
5163
* A list of the inputs that are never flashed for validation exceptions.
5264
*
@@ -187,12 +199,14 @@ public function invalidJson($request, ValidationException $exception)
187199
*/
188200
public static function convertToArray(Throwable $exception, array $override = []): array
189201
{
202+
$match = self::$exceptionResponseCodes[get_class($exception)] ?? null;
203+
190204
$error = [
191205
'code' => class_basename($exception),
192206
'status' => method_exists($exception, 'getStatusCode')
193207
? strval($exception->getStatusCode())
194-
: ($exception instanceof ValidationException ? '422' : '500'),
195-
'detail' => $exception instanceof HttpExceptionInterface
208+
: strval($match ?? '500'),
209+
'detail' => $exception instanceof HttpExceptionInterface || !is_null($match)
196210
? $exception->getMessage()
197211
: 'An unexpected error was encountered while processing this request, please try again.',
198212
];

app/Http/Controllers/Api/Client/AccountController.php

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,19 @@ class AccountController extends ClientApiController
1919
private $updateService;
2020

2121
/**
22-
* @var \Illuminate\Auth\SessionGuard
22+
* @var \Illuminate\Auth\AuthManager
2323
*/
24-
private $sessionGuard;
24+
private $manager;
2525

2626
/**
2727
* AccountController constructor.
2828
*/
29-
public function __construct(AuthManager $sessionGuard, UserUpdateService $updateService)
29+
public function __construct(AuthManager $manager, UserUpdateService $updateService)
3030
{
3131
parent::__construct();
3232

3333
$this->updateService = $updateService;
34-
$this->sessionGuard = $sessionGuard;
34+
$this->manager = $manager;
3535
}
3636

3737
public function index(Request $request): array
@@ -64,13 +64,17 @@ public function updatePassword(UpdatePasswordRequest $request): JsonResponse
6464
{
6565
$user = $this->updateService->handle($request->user(), $request->validated());
6666

67+
$guard = $this->manager->guard();
6768
// If you do not update the user in the session you'll end up working with a
6869
// cached copy of the user that does not include the updated password. Do this
6970
// to correctly store the new user details in the guard and allow the logout
7071
// other devices functionality to work.
71-
$this->sessionGuard->setUser($user);
72+
$guard->setUser($user);
7273

73-
$this->sessionGuard->logoutOtherDevices($request->input('password'));
74+
// This method doesn't exist in the stateless Sanctum world.
75+
if (method_exists($guard, 'logoutOtherDevices')) {
76+
$guard->logoutOtherDevices($request->input('password'));
77+
}
7478

7579
return new JsonResponse([], Response::HTTP_NO_CONTENT);
7680
}

app/Models/ApiKey.php

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,13 @@ public function tokenable()
195195
public static function findToken($token)
196196
{
197197
$id = Str::substr($token, 0, self::IDENTIFIER_LENGTH);
198-
$token = Str::substr($token, strlen($id));
199198

200-
return static::where('identifier', $id)->where('token', encrypt($token))->first();
199+
$model = static::where('identifier', $id)->first();
200+
if (!is_null($model) && decrypt($model->token) === Str::substr($token, strlen($id))) {
201+
return $model;
202+
}
203+
204+
return null;
201205
}
202206

203207
/**

database/Factories/ApiKeyFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public function definition(): array
2525

2626
return [
2727
'key_type' => ApiKey::TYPE_APPLICATION,
28-
'identifier' => Str::random(ApiKey::IDENTIFIER_LENGTH),
28+
'identifier' => ApiKey::generateTokenIdentifier(),
2929
'token' => $token ?: $token = encrypt(Str::random(ApiKey::KEY_LENGTH)),
3030
'allowed_ips' => null,
3131
'memo' => 'Test Function Key',

tests/Integration/Api/Application/ApplicationApiIntegrationTestCase.php

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
namespace Pterodactyl\Tests\Integration\Api\Application;
44

5-
use Pterodactyl\Models\User;
65
use Illuminate\Http\Request;
6+
use Pterodactyl\Models\User;
77
use PHPUnit\Framework\Assert;
88
use Pterodactyl\Models\ApiKey;
99
use Pterodactyl\Services\Acl\Api\AdminAcl;
@@ -41,10 +41,9 @@ public function setUp(): void
4141
$this->user = $this->createApiUser();
4242
$this->key = $this->createApiKey($this->user);
4343

44-
$this->withHeader('Accept', 'application/vnd.pterodactyl.v1+json');
45-
$this->withHeader('Authorization', 'Bearer ' . $this->getApiKey()->identifier . decrypt($this->getApiKey()->token));
46-
47-
$this->withMiddleware('api..key:' . ApiKey::TYPE_APPLICATION);
44+
$this
45+
->withHeader('Accept', 'application/vnd.pterodactyl.v1+json')
46+
->withHeader('Authorization', 'Bearer ' . $this->key->identifier . decrypt($this->key->token));
4847
}
4948

5049
public function getApiUser(): User
@@ -63,17 +62,10 @@ public function getApiKey(): ApiKey
6362
protected function createNewDefaultApiKey(User $user, array $permissions = []): ApiKey
6463
{
6564
$this->key = $this->createApiKey($user, $permissions);
66-
$this->refreshHeaders($this->key);
6765

68-
return $this->key;
69-
}
66+
$this->withHeader('Authorization', 'Bearer ' . $this->key->identifier . decrypt($this->key->token));
7067

71-
/**
72-
* Refresh the authorization header for a request to use a different API key.
73-
*/
74-
protected function refreshHeaders(ApiKey $key)
75-
{
76-
$this->withHeader('Authorization', 'Bearer ' . $key->identifier . decrypt($key->token));
68+
return $this->key;
7769
}
7870

7971
/**

0 commit comments

Comments
 (0)