misc_pterodactyl-panel/app/Services/Users/SecurityKeys/StoreSecurityKeyService.php

75 lines
2.4 KiB
PHP
Raw Normal View History

<?php
namespace Pterodactyl\Services\Users\SecurityKeys;
use Illuminate\Support\Str;
use Pterodactyl\Models\User;
use Webmozart\Assert\Assert;
use Pterodactyl\Models\SecurityKey;
use Psr\Http\Message\ServerRequestInterface;
use Webauthn\PublicKeyCredentialCreationOptions;
use Pterodactyl\Repositories\SecurityKeys\WebauthnServerRepository;
use Pterodactyl\Repositories\SecurityKeys\PublicKeyCredentialSourceRepository;
class StoreSecurityKeyService
{
protected WebauthnServerRepository $serverRepository;
protected ?ServerRequestInterface $request = null;
protected ?string $keyName = null;
public function __construct(WebauthnServerRepository $serverRepository)
{
$this->serverRepository = $serverRepository;
}
/**
* Sets the server request interface on the service, this is needed by the attestation
* checking service on the Webauthn server.
*/
public function setRequest(ServerRequestInterface $request): self
{
$this->request = $request;
return $this;
}
/**
* Sets the security key's name. If not provided a random string will be used.
*/
public function setKeyName(?string $name): self
{
$this->keyName = $name;
return $this;
}
/**
* Validates and stores a new hardware security key on a user's account.
*
* @throws \Throwable
*/
public function handle(User $user, array $registration, PublicKeyCredentialCreationOptions $options): SecurityKey
{
Assert::notNull($this->request, 'A request interface must be set on the service before it can be called.');
$source = $this->serverRepository->getServer($user)
->loadAndCheckAttestationResponse(json_encode($registration), $options, $this->request);
// 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 $created */
$created = $user->securityKeys()
->where('public_key_id', base64_encode($source->getPublicKeyCredentialId()))
->first();
$created->update(['name' => $this->keyName ?? 'Security Key (' . Str::random() . ')']);
return $created;
}
}