Don't store a new key on every login

This commit is contained in:
Dane Everitt 2022-02-13 15:06:08 -05:00
parent 2d2352017d
commit b43e8835bb
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
3 changed files with 27 additions and 37 deletions

View file

@ -7,6 +7,7 @@ use Carbon\CarbonInterface;
use Pterodactyl\Models\User;
use Illuminate\Http\Request;
use PragmaRX\Google2FA\Google2FA;
use Illuminate\Http\JsonResponse;
use Pterodactyl\Models\SecurityKey;
use Illuminate\Contracts\Encryption\Encrypter;
use Webauthn\PublicKeyCredentialRequestOptions;
@ -81,12 +82,10 @@ class LoginCheckpointController extends AbstractLoginController
/**
* Authenticates a login request using a security key for a user.
*
* @param \Illuminate\Http\Request $request
*
* @throws \Illuminate\Validation\ValidationException
* @throws \Pterodactyl\Exceptions\DisplayException
*/
public function key(Request $request)
public function key(Request $request): JsonResponse
{
$key = $request->session()->get(SecurityKey::PK_SESSION_NAME);
if (!$key instanceof PublicKeyCredentialRequestOptions) {
@ -102,16 +101,15 @@ class LoginCheckpointController extends AbstractLoginController
SecurityKey::getPsrRequestFactory($request)
);
if (!hash_equals($user->uuid, $source->getUserHandle())) {
throw new BadRequestHttpException('An unexpected error was encountered while validating that security key.');
}
if (hash_equals($user->uuid, $source->getUserHandle())) {
return $this->sendLoginResponse($user, $request);
}
throw new BadRequestHttpException('An unexpected error was encountered while validating that security key.');
}
/**
* @param \Illuminate\Http\Request $request
* @return \Pterodactyl\Models\User
* Extracts the user from the session data using the provided confirmation token.
*
* @throws \Illuminate\Validation\ValidationException
* @throws \Pterodactyl\Exceptions\DisplayException
@ -168,7 +166,7 @@ class LoginCheckpointController extends AbstractLoginController
* will return false if the data is invalid, or if more time has passed than
* was configured when the session was written.
*/
public static function isValidSessionData(ValidationFactory $validation, array $data): bool
protected static function isValidSessionData(ValidationFactory $validation, array $data): bool
{
$validator = $validation->make($data, [
'user_id' => 'required|integer|min:1',

View file

@ -54,24 +54,9 @@ class PublicKeyCredentialSourceRepository implements PublicKeyRepositoryInterfac
*/
public function saveCredentialSource(PublicKeyCredentialSource $source): void
{
$key = $this->user->securityKeys()->make();
$key->forceFill([
'uuid' => Uuid::uuid4(),
'user_id' => $this->user->id,
'public_key_id' => $source->getPublicKeyCredentialId(),
'public_key' => $source->getCredentialPublicKey(),
'aaguid' => $source->getAaguid(),
'type' => $source->getType(),
'transports' => $source->getTransports(),
'attestation_type' => $source->getAttestationType(),
'trust_path' => $source->getTrustPath(),
'user_handle' => $source->getUserHandle(),
'counter' => $source->getCounter(),
'other_ui' => $source->getOtherUI(),
]);
$key->saveOrFail();
// no-op — we handle creation of the keys in StoreSecurityKeyService
//
// If you put logic in here it is triggered on each login.
}
/**

View file

@ -2,6 +2,7 @@
namespace Pterodactyl\Services\Users\SecurityKeys;
use Ramsey\Uuid\Uuid;
use Illuminate\Support\Str;
use Pterodactyl\Models\User;
use Webmozart\Assert\Assert;
@ -9,7 +10,6 @@ use Pterodactyl\Models\SecurityKey;
use Psr\Http\Message\ServerRequestInterface;
use Webauthn\PublicKeyCredentialCreationOptions;
use Pterodactyl\Repositories\SecurityKeys\WebauthnServerRepository;
use Pterodactyl\Repositories\SecurityKeys\PublicKeyCredentialSourceRepository;
class StoreSecurityKeyService
{
@ -60,15 +60,22 @@ class StoreSecurityKeyService
// Unfortunately this repository interface doesn't define a response — it is explicitly
// void — so we need to just query the database immediately after this to pull the information
// we just stored to return to the caller.
PublicKeyCredentialSourceRepository::factory($user)->saveCredentialSource($source);
/** @var \Pterodactyl\Models\SecurityKey $key */
$key = $user->securityKeys()->forceCreate([
'uuid' => Uuid::uuid4(),
'name' => $this->keyName ?? 'Security Key (' . Str::random() . ')',
'public_key_id' => $source->getPublicKeyCredentialId(),
'public_key' => $source->getCredentialPublicKey(),
'aaguid' => $source->getAaguid(),
'type' => $source->getType(),
'transports' => $source->getTransports(),
'attestation_type' => $source->getAttestationType(),
'trust_path' => $source->getTrustPath(),
'user_handle' => $user->uuid,
'counter' => $source->getCounter(),
'other_ui' => $source->getOtherUI(),
]);
/** @var \Pterodactyl\Models\SecurityKey $created */
$created = $user->securityKeys()
->where('public_key_id', base64_encode($source->getPublicKeyCredentialId()))
->first();
$created->update(['name' => $this->keyName ?? 'Security Key (' . Str::random() . ')']);
return $created;
return $key;
}
}