Very basic working implementation of sanctum for API validation

This commit is contained in:
Dane Everitt 2021-07-27 21:23:11 -07:00
parent 4b32828423
commit d60e8a193b
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
23 changed files with 24212 additions and 88 deletions

View file

@ -12,11 +12,14 @@ use Pterodactyl\Http\Requests\Api\Client\ClientApiRequest;
use Pterodactyl\Transformers\Api\Client\ApiKeyTransformer;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Pterodactyl\Http\Requests\Api\Client\Account\StoreApiKeyRequest;
use Pterodactyl\Transformers\Api\Client\PersonalAccessTokenTransformer;
class ApiKeyController extends ClientApiController
{
private Encrypter $encrypter;
private ApiKeyRepository $repository;
private KeyCreationService $keyCreationService;
/**
@ -41,8 +44,8 @@ class ApiKeyController extends ClientApiController
*/
public function index(ClientApiRequest $request): array
{
return $this->fractal->collection($request->user()->apiKeys)
->transformWith($this->getTransformer(ApiKeyTransformer::class))
return $this->fractal->collection($request->user()->tokens)
->transformWith($this->getTransformer(PersonalAccessTokenTransformer::class))
->toArray();
}
@ -50,25 +53,22 @@ class ApiKeyController extends ClientApiController
* Store a new API key for a user's account.
*
* @throws \Pterodactyl\Exceptions\DisplayException
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Illuminate\Contracts\Container\BindingResolutionException
*/
public function store(StoreApiKeyRequest $request): array
{
if ($request->user()->apiKeys->count() >= 5) {
if ($request->user()->tokens->count() >= 10) {
throw new DisplayException('You have reached the account limit for number of API keys.');
}
$key = $this->keyCreationService->setKeyType(ApiKey::TYPE_ACCOUNT)->handle([
'user_id' => $request->user()->id,
'memo' => $request->input('description'),
'allowed_ips' => $request->input('allowed_ips') ?? [],
]);
// TODO: this should accept an array of different scopes to apply as permissions
// for the token. Right now it allows any account level permission.
$token = $request->user()->createToken($request->input('description'));
return $this->fractal->item($key)
->transformWith($this->getTransformer(ApiKeyTransformer::class))
return $this->fractal->item($token->accessToken)
->transformWith($this->getTransformer(PersonalAccessTokenTransformer::class))
->addMeta([
'secret_token' => $this->encrypter->decrypt($key->token),
'secret_token' => $token->plainTextToken,
])
->toArray();
}
@ -78,15 +78,7 @@ class ApiKeyController extends ClientApiController
*/
public function delete(ClientApiRequest $request, string $identifier): Response
{
$response = $this->repository->deleteWhere([
'key_type' => ApiKey::TYPE_ACCOUNT,
'user_id' => $request->user()->id,
'identifier' => $identifier,
]);
if (!$response) {
throw new NotFoundHttpException();
}
$request->user()->tokens()->where('id', $identifier)->delete();
return $this->returnNoContent();
}

View file

@ -59,7 +59,7 @@ abstract class ClientApiController extends ApplicationApiController
]);
if ($transformer instanceof BaseClientTransformer) {
$transformer->setKey($this->request->attributes->get('api_key'));
// $transformer->setKey($this->request->attributes->get('api_key'));
$transformer->setUser($this->request->user());
}

View file

@ -123,8 +123,6 @@ class LoginController extends AbstractLoginController
]);
}
$this->auth->guard()->login($user, true);
return $this->sendLoginResponse($user, $request);
}
}

View file

@ -32,7 +32,9 @@ use Pterodactyl\Http\Middleware\Api\Daemon\DaemonAuthenticate;
use Pterodactyl\Http\Middleware\RequireTwoFactorAuthentication;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode;
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;
use Pterodactyl\Http\Middleware\Api\Client\SubstituteClientApiBindings;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance;
use Pterodactyl\Http\Middleware\Api\Application\AuthenticateApplicationUser;
class Kernel extends HttpKernel
@ -43,12 +45,11 @@ class Kernel extends HttpKernel
* @var array
*/
protected $middleware = [
CheckForMaintenanceMode::class,
EncryptCookies::class,
TrustProxies::class,
PreventRequestsDuringMaintenance::class,
ValidatePostSize::class,
TrimStrings::class,
ConvertEmptyStringsToNull::class,
TrustProxies::class,
];
/**
@ -58,6 +59,7 @@ class Kernel extends HttpKernel
*/
protected $middlewareGroups = [
'web' => [
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
AuthenticateSession::class,
@ -70,19 +72,23 @@ class Kernel extends HttpKernel
'api' => [
IsValidJson::class,
ApiSubstituteBindings::class,
SetSessionDriver::class,
'api..key:' . ApiKey::TYPE_APPLICATION,
EnsureFrontendRequestsAreStateful::class,
// SetSessionDriver::class,
// 'api..key:' . ApiKey::TYPE_APPLICATION,
AuthenticateApplicationUser::class,
AuthenticateIPAccess::class,
// AuthenticateIPAccess::class,
],
'client-api' => [
StartSession::class,
SetSessionDriver::class,
AuthenticateSession::class,
// StartSession::class,
// SetSessionDriver::class,
// AuthenticateSession::class,
IsValidJson::class,
EnsureFrontendRequestsAreStateful::class,
'auth:sanctum',
// 'throttle:api',
SubstituteClientApiBindings::class,
'api..key:' . ApiKey::TYPE_ACCOUNT,
AuthenticateIPAccess::class,
// 'api..key:' . ApiKey::TYPE_ACCOUNT,
// AuthenticateIPAccess::class,
// This is perhaps a little backwards with the Client API, but logically you'd be unable
// to create/get an API key without first enabling 2FA on the account, so I suppose in the
// end it makes sense.

View file

@ -14,6 +14,6 @@ class VerifyCsrfToken extends BaseVerifier
protected $except = [
'remote/*',
'daemon/*',
'api/*',
// 'api/*',
];
}