Don't store a new key on every login
This commit is contained in:
parent
2d2352017d
commit
b43e8835bb
3 changed files with 27 additions and 37 deletions
|
@ -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',
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue