diff --git a/src/Cli/App.php b/src/Cli/App.php index ad47397..c5ecb5a 100644 --- a/src/Cli/App.php +++ b/src/Cli/App.php @@ -9,6 +9,7 @@ use Siteworxpro\App\Cli\Commands\OAuth\AddRedirectUri; use Siteworxpro\App\Cli\Commands\OAuth\AddScope; use Siteworxpro\App\Cli\Commands\OAuth\ClientCapabilities; use Siteworxpro\App\Cli\Commands\OAuth\CreateClient; +use Siteworxpro\App\Cli\Commands\OAuth\DeleteClient; use Siteworxpro\App\Cli\Commands\OAuth\ListClients; use Siteworxpro\App\Cli\Commands\Queue\Start; use Siteworxpro\App\Cli\Commands\User\Add; @@ -42,6 +43,7 @@ class App $this->app->addCommand(new AddScope()); $this->app->addCommand(new ResetPassword()); $this->app->addCommand(new ClientCapabilities()); + $this->app->addCommand(new DeleteClient()); } public function run(): int diff --git a/src/Cli/Commands/OAuth/DeleteClient.php b/src/Cli/Commands/OAuth/DeleteClient.php new file mode 100644 index 0000000..c93d99c --- /dev/null +++ b/src/Cli/Commands/OAuth/DeleteClient.php @@ -0,0 +1,58 @@ +askForClient($output, $input); + + if ($client === null) { + $output->red('No client selected, aborting.'); + + return \Symfony\Component\Console\Command\Command::FAILURE; + } + + $output->red()->bold('You are about to delete the following OAuth client:'); + $output->red("ID: $client->id"); + $output->red("Name: $client->name"); + $output->red("Description: $client->description"); + + $output + ->br() + ->backgroundRed() + ->yellow() + ->bold('This action is irreversible and will remove all associated data.'); + + $question = $this->helper->ask( + $input, + $output, + new \Symfony\Component\Console\Question\ConfirmationQuestion( + 'Are you sure you want to proceed? (y/N): ', + false, + '/^(y|yes)/i' + ) + ); + + if (!$question) { + $output->info('Operation cancelled by user.'); + + return \Symfony\Component\Console\Command\Command::SUCCESS; + } + + $client->delete(); + + $output->green('OAuth client deleted successfully.'); + + return \Symfony\Component\Console\Command\Command::SUCCESS; + } +} diff --git a/src/Cli/Commands/OAuth/ListClients.php b/src/Cli/Commands/OAuth/ListClients.php index e6eb46f..b32d5aa 100644 --- a/src/Cli/Commands/OAuth/ListClients.php +++ b/src/Cli/Commands/OAuth/ListClients.php @@ -46,7 +46,8 @@ class ListClients extends Command 'Access Token Url' => Config::get('app.url') . '/client/access_token', 'OAuth Config Url' => Config::get('app.url') . '/client/' . $client->id . '/.well-known/openid-configuration', - 'Scopes' => $client->scopes->toArray() + 'Scopes' => $client->scopes->toArray(), + 'Capabilities' => $client->capabilities->toArray(), ]); return self::SUCCESS; diff --git a/src/Controllers/AccessTokenController.php b/src/Controllers/AccessTokenController.php index 2c3a70d..034d077 100644 --- a/src/Controllers/AccessTokenController.php +++ b/src/Controllers/AccessTokenController.php @@ -40,7 +40,10 @@ final class AccessTokenController extends Controller /** @var Response $response */ $response = $client ->getAuthorizationServer() - ->respondToAccessTokenRequest($request, JsonResponseFactory::createJsonResponse([])); + ->respondToAccessTokenRequest( + $request, + JsonResponseFactory::createJsonResponse([]) + ); Dispatcher::push(new Issued($response)); diff --git a/src/OAuth/Entities/Client.php b/src/OAuth/Entities/Client.php index cf36d7c..b4df14b 100644 --- a/src/OAuth/Entities/Client.php +++ b/src/OAuth/Entities/Client.php @@ -13,6 +13,7 @@ use Illuminate\Database\Eloquent\Relations\HasManyThrough; use League\OAuth2\Server\AuthorizationServer; use League\OAuth2\Server\Entities\ClientEntityInterface; use League\OAuth2\Server\Entities\Traits\EntityTrait; +use League\OAuth2\Server\Grant\ClientCredentialsGrant as ClientCredentialsGrant; use Random\RandomException; use Siteworxpro\App\Helpers\Rand; use Siteworxpro\App\Models\ClientRedirectUri; @@ -195,6 +196,9 @@ class Client extends Model implements ClientEntityInterface Key::loadFromAsciiSafeString($this->encryption_key) ); + $accessTokenTtl = $this->capabilities->toArray()['tokenSettings']['accessTokenTTL'] ?? 'PT1H'; + $refreshTokenTtl = $this->capabilities->toArray()['tokenSettings']['refreshTokenTTL'] ?? 'P1M'; + if (!empty($this->grant_types)) { foreach ($this->grant_types as $grantType) { switch ($grantType) { @@ -204,22 +208,22 @@ class Client extends Model implements ClientEntityInterface new \Siteworxpro\App\OAuth\RefreshTokenRepository(), new \DateInterval('PT10M') ); - $grant->setRefreshTokenTTL(new \DateInterval('P1M')); + $grant->setRefreshTokenTTL(new \DateInterval($refreshTokenTtl)); break; case 'client_credentials': - $grant = new \League\OAuth2\Server\Grant\ClientCredentialsGrant(); + $grant = new ClientCredentialsGrant(); break; case 'refresh_token': $grant = new \League\OAuth2\Server\Grant\RefreshTokenGrant( new \Siteworxpro\App\OAuth\RefreshTokenRepository() ); - $grant->setRefreshTokenTTL(new \DateInterval('P1M')); + $grant->setRefreshTokenTTL(new \DateInterval($refreshTokenTtl)); break; default: continue 2; } - $authorizationServer->enableGrantType($grant); + $authorizationServer->enableGrantType($grant, new \DateInterval($accessTokenTtl)); } } diff --git a/src/OAuth/Entities/ClientCapabilities.php b/src/OAuth/Entities/ClientCapabilities.php index 4ddd4a9..007abfb 100644 --- a/src/OAuth/Entities/ClientCapabilities.php +++ b/src/OAuth/Entities/ClientCapabilities.php @@ -22,6 +22,11 @@ class ClientCapabilities implements Arrayable 'logoUrl' => null, ]; + private array $tokenSettings = [ + 'accessTokenTTL' => 'PT1H', + 'refreshTokenTTL' => 'P1M', + ]; + public function __construct(array $capabilities = []) { if (isset($capabilities['userPass'])) { @@ -47,6 +52,10 @@ class ClientCapabilities implements Arrayable if (isset($capabilities['support_email'])) { $this->support_email = (string)$capabilities['support_email']; } + + if (isset($capabilities['tokenSettings']) && is_array($capabilities['tokenSettings'])) { + $this->tokenSettings = array_merge($this->tokenSettings, $capabilities['tokenSettings']); + } } public static function fromJson(string $data): self @@ -66,7 +75,8 @@ class ClientCapabilities implements Arrayable 'passkey' => "bool", 'socials' => "array", 'branding' => "array", - 'support_email' => "string" + 'support_email' => "string", + 'tokenSettings' => "array", ])] public function toArray(): array { @@ -77,6 +87,7 @@ class ClientCapabilities implements Arrayable 'socials' => $this->socials, 'branding' => $this->branding, 'support_email' => $this->support_email, + 'tokenSettings' => $this->tokenSettings, ]; }