Logic cleanup after a bit of dust collection

This commit is contained in:
Dane Everitt 2022-02-13 14:15:18 -05:00
parent 8971e78ab5
commit 969d40d6c1
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
6 changed files with 74 additions and 43 deletions

View file

@ -61,6 +61,7 @@ class SecurityKeyController extends ClientApiController
$tokenId = Str::random(64);
$credentials = $this->createPublicKeyCredentials->handle($request->user());
// TODO: session
$this->cache->put(
"register-security-key:$tokenId",
serialize($credentials),

View file

@ -7,27 +7,27 @@ use Illuminate\Support\Str;
use Illuminate\Http\Request;
use Pterodactyl\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Contracts\View\View;
use LaravelWebauthn\Facades\Webauthn;
use Illuminate\Contracts\View\Factory as ViewFactory;
use Pterodactyl\Models\SecurityKey;
use Illuminate\Support\Facades\View;
use Illuminate\Contracts\View\View as ViewContract;
use Pterodactyl\Services\Users\SecurityKeys\GeneratePublicKeyCredentialsRequestService;
class LoginController extends AbstractLoginController
{
private const SESSION_PUBLICKEY_REQUEST = 'webauthn.publicKeyRequest';
private const METHOD_TOTP = 'totp';
private const METHOD_WEBAUTHN = 'webauthn';
private const SESSION_PUBLICKEY_REQUEST = 'webauthn.publicKeyRequest';
private ViewFactory $view;
protected GeneratePublicKeyCredentialsRequestService $service;
/**
* LoginController constructor.
* @param \Pterodactyl\Services\Users\SecurityKeys\GeneratePublicKeyCredentialsRequestService $service
*/
public function __construct(ViewFactory $view)
public function __construct(GeneratePublicKeyCredentialsRequestService $service)
{
parent::__construct();
$this->view = $view;
$this->service = $service;
}
/**
@ -35,9 +35,9 @@ class LoginController extends AbstractLoginController
* base authentication view component. React will take over at this point and
* turn the login area into an SPA.
*/
public function index(): View
public function index(): ViewContract
{
return $this->view->make('templates/auth.core');
return View::make('templates/auth.core');
}
/**
@ -75,23 +75,11 @@ class LoginController extends AbstractLoginController
return;
}
$useTotp = $user->use_totp;
$webauthnKeys = $user->webauthnKeys()->get();
if (!$useTotp && count($webauthnKeys) < 1) {
if (!$user->use_totp && empty($user->security_keys_count)) {
return $this->sendLoginResponse($user, $request);
}
$methods = [];
if ($useTotp) {
$methods[] = self::METHOD_TOTP;
}
if (count($webauthnKeys) > 0) {
$methods[] = self::METHOD_WEBAUTHN;
}
$token = Str::random(64);
$request->session()->put('auth_confirmation_token', [
'user_id' => $user->id,
'token_value' => $token,
@ -100,17 +88,21 @@ class LoginController extends AbstractLoginController
$response = [
'complete' => false,
'methods' => $methods,
'methods' => array_filter([
$user->use_totp ? self::METHOD_TOTP : null,
$user->security_keys_count > 0 ? self::METHOD_WEBAUTHN : null,
]),
'confirmation_token' => $token,
];
if (count($webauthnKeys) > 0) {
$publicKey = Webauthn::getAuthenticateData($user);
$request->session()->put(self::SESSION_PUBLICKEY_REQUEST, $publicKey);
$response['webauthn'] = [
'public_key' => $publicKey,
];
if ($user->security_keys_count > 0) {
// $key = $this->service->handle($user);
//
// $request->session()->put(self::SESSION_PUBLICKEY_REQUEST, $publicKey);
//
// $response['webauthn'] = [
// 'public_key' => $publicKey,
// ];
}
return new JsonResponse($response);

View file

@ -2,7 +2,6 @@
namespace Pterodactyl\Models;
use Stringable;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
use Webauthn\TrustPath\TrustPath;
@ -82,12 +81,7 @@ class SecurityKey extends Model
return null;
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
public function getPublicKeyCredentialsDescriptorAttribute(): PublicKeyCredentialDescriptor
public function getPublicKeyCredentialDescriptor(): PublicKeyCredentialDescriptor
{
return new PublicKeyCredentialDescriptor(
$this->type,
@ -96,7 +90,7 @@ class SecurityKey extends Model
);
}
public function getPublicKeyCredentialSourceAttribute(): PublicKeyCredentialSource
public function getPublicKeyCredentialSource(): PublicKeyCredentialSource
{
return new PublicKeyCredentialSource(
$this->public_key_id,
@ -110,4 +104,9 @@ class SecurityKey extends Model
$this->counter
);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}

View file

@ -29,7 +29,7 @@ class PublicKeyCredentialSourceRepository implements PublicKeyRepositoryInterfac
->where('public_key_id', $id)
->first();
return $key ? $key->public_key_credential_source : null;
return optional($key)->getPublicKeyCredentialSource();
}
/**
@ -43,7 +43,7 @@ class PublicKeyCredentialSourceRepository implements PublicKeyRepositoryInterfac
->get();
return $results->map(function (SecurityKey $key) {
return $key->public_key_credential_source;
return $key->getPublicKeyCredentialSource();
})->values()->toArray();
}

View file

@ -22,7 +22,7 @@ class CreatePublicKeyCredentialsService
$entity = new PublicKeyCredentialUserEntity($user->username, $user->uuid, $user->email, null);
$excluded = $user->securityKeys->map(function (SecurityKey $key) {
return $key->public_key_credentials_descriptor;
return $key->getPublicKeyCredentialDescriptor();
})->values()->toArray();
$server = $this->webauthnServerRepository->getServer($user);

View file

@ -0,0 +1,39 @@
<?php
namespace Pterodactyl\Services\Users\SecurityKeys;
use Pterodactyl\Models\User;
use Pterodactyl\Models\SecurityKey;
use Webauthn\PublicKeyCredentialRequestOptions;
use Pterodactyl\Repositories\SecurityKeys\WebauthnServerRepository;
class GeneratePublicKeyCredentialsRequestService
{
protected WebauthnServerRepository $serverRepository;
/**
* @param \Pterodactyl\Repositories\SecurityKeys\WebauthnServerRepository $serverRepository
*/
public function __construct(WebauthnServerRepository $serverRepository)
{
$this->serverRepository = $serverRepository;
}
/**
* @param \Pterodactyl\Models\User $user
* @return \Webauthn\PublicKeyCredentialRequestOptions
*/
public function handle(User $user): PublicKeyCredentialRequestOptions
{
$credentials = $user->securityKeys->map(function (SecurityKey $key) {
return $key->getPublicKeyCredentialDescriptor();
});
$response = $this->serverRepository->getServer($user)
->generatePublicKeyCredentialRequestOptions(
PublicKeyCredentialRequestOptions::USER_VERIFICATION_REQUIREMENT_PREFERRED, $credentials
);
return $response->setTimeout(300);
}
}