2021-08-08 17:48:35 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Pterodactyl\Http\Controllers\Api\Client;
|
|
|
|
|
|
|
|
use Carbon\CarbonImmutable;
|
|
|
|
use Illuminate\Support\Str;
|
|
|
|
use Illuminate\Http\Request;
|
|
|
|
use Illuminate\Http\JsonResponse;
|
2022-02-13 19:44:50 +00:00
|
|
|
use Pterodactyl\Models\SecurityKey;
|
2021-08-08 17:48:35 +00:00
|
|
|
use Nyholm\Psr7\Factory\Psr17Factory;
|
|
|
|
use Illuminate\Contracts\Cache\Repository;
|
|
|
|
use Psr\Http\Message\ServerRequestInterface;
|
|
|
|
use Pterodactyl\Exceptions\DisplayException;
|
|
|
|
use Webauthn\PublicKeyCredentialCreationOptions;
|
|
|
|
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory;
|
2021-08-08 18:52:05 +00:00
|
|
|
use Pterodactyl\Transformers\Api\Client\SecurityKeyTransformer;
|
2021-08-08 17:48:35 +00:00
|
|
|
use Pterodactyl\Repositories\SecurityKeys\WebauthnServerRepository;
|
2021-08-08 18:52:05 +00:00
|
|
|
use Pterodactyl\Services\Users\SecurityKeys\StoreSecurityKeyService;
|
2021-08-08 17:48:35 +00:00
|
|
|
use Pterodactyl\Http\Requests\Api\Client\Account\RegisterWebauthnTokenRequest;
|
|
|
|
use Pterodactyl\Services\Users\SecurityKeys\CreatePublicKeyCredentialsService;
|
|
|
|
|
|
|
|
class SecurityKeyController extends ClientApiController
|
|
|
|
{
|
|
|
|
protected CreatePublicKeyCredentialsService $createPublicKeyCredentials;
|
|
|
|
|
|
|
|
protected Repository $cache;
|
|
|
|
|
|
|
|
protected WebauthnServerRepository $webauthnServerRepository;
|
|
|
|
|
2021-08-08 18:52:05 +00:00
|
|
|
protected StoreSecurityKeyService $storeSecurityKeyService;
|
|
|
|
|
2021-08-08 17:48:35 +00:00
|
|
|
public function __construct(
|
|
|
|
Repository $cache,
|
|
|
|
WebauthnServerRepository $webauthnServerRepository,
|
2021-08-08 18:52:05 +00:00
|
|
|
StoreSecurityKeyService $storeSecurityKeyService,
|
2021-08-08 17:48:35 +00:00
|
|
|
CreatePublicKeyCredentialsService $createPublicKeyCredentials
|
|
|
|
) {
|
|
|
|
parent::__construct();
|
|
|
|
|
|
|
|
$this->cache = $cache;
|
|
|
|
$this->webauthnServerRepository = $webauthnServerRepository;
|
|
|
|
$this->createPublicKeyCredentials = $createPublicKeyCredentials;
|
2021-08-08 18:52:05 +00:00
|
|
|
$this->storeSecurityKeyService = $storeSecurityKeyService;
|
2021-08-08 17:48:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns all of the hardware security keys (WebAuthn) that exists for a user.
|
|
|
|
*/
|
|
|
|
public function index(Request $request): array
|
|
|
|
{
|
2021-08-08 18:52:05 +00:00
|
|
|
return $this->fractal->collection($request->user()->securityKeys)
|
|
|
|
->transformWith(SecurityKeyTransformer::class)
|
|
|
|
->toArray();
|
2021-08-08 17:48:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the data necessary for creating a new hardware security key for the
|
|
|
|
* user.
|
|
|
|
*/
|
|
|
|
public function create(Request $request): JsonResponse
|
|
|
|
{
|
|
|
|
$tokenId = Str::random(64);
|
2021-08-08 18:24:11 +00:00
|
|
|
$credentials = $this->createPublicKeyCredentials->handle($request->user());
|
2021-08-08 17:48:35 +00:00
|
|
|
|
2022-02-13 19:15:18 +00:00
|
|
|
// TODO: session
|
2021-08-08 17:48:35 +00:00
|
|
|
$this->cache->put(
|
|
|
|
"register-security-key:$tokenId",
|
|
|
|
serialize($credentials),
|
|
|
|
CarbonImmutable::now()->addMinutes(10)
|
|
|
|
);
|
|
|
|
|
|
|
|
return new JsonResponse([
|
|
|
|
'data' => [
|
|
|
|
'token_id' => $tokenId,
|
|
|
|
'credentials' => $credentials->jsonSerialize(),
|
|
|
|
],
|
|
|
|
]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Stores a new key for a user account.
|
|
|
|
*
|
|
|
|
* @throws \Pterodactyl\Exceptions\DisplayException
|
2021-08-08 18:24:11 +00:00
|
|
|
* @throws \Throwable
|
2021-08-08 17:48:35 +00:00
|
|
|
*/
|
2021-08-08 18:52:05 +00:00
|
|
|
public function store(RegisterWebauthnTokenRequest $request): array
|
2021-08-08 17:48:35 +00:00
|
|
|
{
|
2021-08-08 18:24:11 +00:00
|
|
|
$credentials = unserialize(
|
|
|
|
$this->cache->pull("register-security-key:{$request->input('token_id')}", serialize(null))
|
|
|
|
);
|
2021-08-08 17:48:35 +00:00
|
|
|
|
2021-08-08 18:24:11 +00:00
|
|
|
if (
|
|
|
|
!is_object($credentials) ||
|
|
|
|
!$credentials instanceof PublicKeyCredentialCreationOptions ||
|
|
|
|
$credentials->getUser()->getId() !== $request->user()->uuid
|
|
|
|
) {
|
|
|
|
throw new DisplayException('Could not register security key: invalid data present in session, please try again.');
|
2021-08-08 17:48:35 +00:00
|
|
|
}
|
|
|
|
|
2021-08-08 18:52:05 +00:00
|
|
|
$key = $this->storeSecurityKeyService
|
2022-02-13 19:44:50 +00:00
|
|
|
->setRequest(SecurityKey::getPsrRequestFactory($request))
|
2021-08-08 18:52:05 +00:00
|
|
|
->setKeyName($request->input('name'))
|
|
|
|
->handle($request->user(), $request->input('registration'), $credentials);
|
2021-08-08 17:48:35 +00:00
|
|
|
|
2021-08-08 18:52:05 +00:00
|
|
|
return $this->fractal->item($key)
|
|
|
|
->transformWith(SecurityKeyTransformer::class)
|
|
|
|
->toArray();
|
2021-08-08 17:48:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Removes a WebAuthn key from a user's account.
|
|
|
|
*/
|
2021-08-08 18:52:05 +00:00
|
|
|
public function delete(Request $request, string $securityKey): JsonResponse
|
2021-08-08 17:48:35 +00:00
|
|
|
{
|
2021-08-08 18:52:05 +00:00
|
|
|
$request->user()->securityKeys()->where('uuid', $securityKey)->delete();
|
|
|
|
|
|
|
|
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
2021-08-08 17:48:35 +00:00
|
|
|
}
|
|
|
|
}
|