You've already forked php-auth
generated from siteworxpro/Php-Template
Compare commits
2 Commits
8dbf3c22b6
...
8f5f57f5f6
| Author | SHA1 | Date | |
|---|---|---|---|
|
8f5f57f5f6
|
|||
|
96409973bf
|
@@ -9,6 +9,7 @@ use Siteworxpro\App\Cli\Commands\OAuth\AddRedirectUri;
|
|||||||
use Siteworxpro\App\Cli\Commands\OAuth\AddScope;
|
use Siteworxpro\App\Cli\Commands\OAuth\AddScope;
|
||||||
use Siteworxpro\App\Cli\Commands\OAuth\ClientCapabilities;
|
use Siteworxpro\App\Cli\Commands\OAuth\ClientCapabilities;
|
||||||
use Siteworxpro\App\Cli\Commands\OAuth\CreateClient;
|
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\OAuth\ListClients;
|
||||||
use Siteworxpro\App\Cli\Commands\Queue\Start;
|
use Siteworxpro\App\Cli\Commands\Queue\Start;
|
||||||
use Siteworxpro\App\Cli\Commands\User\Add;
|
use Siteworxpro\App\Cli\Commands\User\Add;
|
||||||
@@ -42,6 +43,7 @@ class App
|
|||||||
$this->app->addCommand(new AddScope());
|
$this->app->addCommand(new AddScope());
|
||||||
$this->app->addCommand(new ResetPassword());
|
$this->app->addCommand(new ResetPassword());
|
||||||
$this->app->addCommand(new ClientCapabilities());
|
$this->app->addCommand(new ClientCapabilities());
|
||||||
|
$this->app->addCommand(new DeleteClient());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run(): int
|
public function run(): int
|
||||||
|
|||||||
58
src/Cli/Commands/OAuth/DeleteClient.php
Normal file
58
src/Cli/Commands/OAuth/DeleteClient.php
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Siteworxpro\App\Cli\Commands\OAuth;
|
||||||
|
|
||||||
|
use Siteworxpro\App\Cli\ClimateOutput;
|
||||||
|
use Siteworxpro\App\Cli\Commands\Command;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
use Symfony\Component\Console\Input\ArgvInput;
|
||||||
|
|
||||||
|
#[AsCommand('oauth:client:delete', 'Delete an OAuth client')]
|
||||||
|
class DeleteClient extends Command
|
||||||
|
{
|
||||||
|
public function __invoke(ClimateOutput|ArgvInput $input, $output): int
|
||||||
|
{
|
||||||
|
$client = $this->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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -46,7 +46,8 @@ class ListClients extends Command
|
|||||||
'Access Token Url' => Config::get('app.url') . '/client/access_token',
|
'Access Token Url' => Config::get('app.url') . '/client/access_token',
|
||||||
'OAuth Config Url' => Config::get('app.url') .
|
'OAuth Config Url' => Config::get('app.url') .
|
||||||
'/client/' . $client->id . '/.well-known/openid-configuration',
|
'/client/' . $client->id . '/.well-known/openid-configuration',
|
||||||
'Scopes' => $client->scopes->toArray()
|
'Scopes' => $client->scopes->toArray(),
|
||||||
|
'Capabilities' => $client->capabilities->toArray(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return self::SUCCESS;
|
return self::SUCCESS;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ use Symfony\Component\Console\Question\Question as QuestionInput;
|
|||||||
#[AsCommand('user:add', 'Add a new user associated with an OAuth client')]
|
#[AsCommand('user:add', 'Add a new user associated with an OAuth client')]
|
||||||
class Add extends Command
|
class Add extends Command
|
||||||
{
|
{
|
||||||
public function __invoke(ClimateOutput|ArgvInput|InputInterface $input, ClimateOutput $output): int
|
public function __invoke(ClimateOutput|ArgvInput|InputInterface $input, $output): int
|
||||||
{
|
{
|
||||||
$client = $this->askForClient($output, $input);
|
$client = $this->askForClient($output, $input);
|
||||||
if (!$client) {
|
if (!$client) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace Siteworxpro\App\Cli\Commands\User;
|
|||||||
use Siteworxpro\App\Cli\ClimateOutput;
|
use Siteworxpro\App\Cli\ClimateOutput;
|
||||||
use Siteworxpro\App\Cli\Commands\Command;
|
use Siteworxpro\App\Cli\Commands\Command;
|
||||||
use Siteworxpro\App\CommandBus\Commands\SendPasswordReset;
|
use Siteworxpro\App\CommandBus\Commands\SendPasswordReset;
|
||||||
|
use Siteworxpro\App\Mailer\Message;
|
||||||
use Siteworxpro\App\Services\Facades\CommandBus;
|
use Siteworxpro\App\Services\Facades\CommandBus;
|
||||||
use Symfony\Component\Console\Attribute\AsCommand;
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
use Symfony\Component\Console\Helper\QuestionHelper;
|
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||||
@@ -41,9 +42,13 @@ class ResetPassword extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($input->getOption('send-email')) {
|
if ($input->getOption('send-email')) {
|
||||||
CommandBus::handle(new SendPasswordReset($user, $client));
|
/** @var Message $message */
|
||||||
|
$message = CommandBus::handle(new SendPasswordReset($user, $client));
|
||||||
$output->info('Password reset email sent to the user.');
|
$output->info('Password reset email sent to the user.');
|
||||||
|
|
||||||
|
$output->info('Email Subject: ' . $message->getSubject());
|
||||||
|
$output->info('Email Body: ' . $message->getBody());
|
||||||
|
|
||||||
return \Symfony\Component\Console\Command\Command::SUCCESS;
|
return \Symfony\Component\Console\Command\Command::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class SendPasswordResetHandler extends CommandHandler
|
|||||||
/**
|
/**
|
||||||
* @throws RandomException
|
* @throws RandomException
|
||||||
*/
|
*/
|
||||||
public function __invoke(Command|SendPasswordReset $command): User
|
public function __invoke(Command|SendPasswordReset $command): Message
|
||||||
{
|
{
|
||||||
if (!$command instanceof SendPasswordReset) {
|
if (!$command instanceof SendPasswordReset) {
|
||||||
throw new CommandHandlerException('Invalid command type provided to handler.');
|
throw new CommandHandlerException('Invalid command type provided to handler.');
|
||||||
@@ -33,13 +33,23 @@ class SendPasswordResetHandler extends CommandHandler
|
|||||||
|
|
||||||
$content = Twig::render('password-reset.twig', [
|
$content = Twig::render('password-reset.twig', [
|
||||||
'user' => $command->getUser(),
|
'user' => $command->getUser(),
|
||||||
'resetLink' => Config::get('app.url') . '/reset-password?token=' . $token,
|
'resetLink' => sprintf(
|
||||||
|
'%s/authorize?token=%s&client_id=%s&response_type=code&redirect_uri=%s#/password-reset',
|
||||||
|
Config::get('app.url'),
|
||||||
|
$token,
|
||||||
|
$command->getClient()->client_id,
|
||||||
|
urlencode($command->getClient()->clientRedirectUris->first()->redirect_uri)
|
||||||
|
),
|
||||||
'client' => $command->getClient()
|
'client' => $command->getClient()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$from = $command->getClient()->capabilities->toArray()['support_email'] != ''
|
||||||
|
? $command->getClient()->capabilities->toArray()['support_email']
|
||||||
|
: Config::get('app.default_support_email');
|
||||||
|
|
||||||
$message = new Message(
|
$message = new Message(
|
||||||
$command->getUser()->email,
|
$command->getUser()->email,
|
||||||
$command->getClient()->capabilities->toArray()['support_email'] ?? Config::get('app.default_support_email'),
|
$from,
|
||||||
'Password Reset Request',
|
'Password Reset Request',
|
||||||
$content
|
$content
|
||||||
);
|
);
|
||||||
@@ -50,6 +60,6 @@ class SendPasswordResetHandler extends CommandHandler
|
|||||||
|
|
||||||
Redis::set('password_reset:' . $command->getUser()->id, $token, 'EX', Redis::MINUTE * 15);
|
Redis::set('password_reset:' . $command->getUser()->id, $token, 'EX', Redis::MINUTE * 15);
|
||||||
|
|
||||||
return $command->getUser();
|
return $message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,10 @@ final class AccessTokenController extends Controller
|
|||||||
/** @var Response $response */
|
/** @var Response $response */
|
||||||
$response = $client
|
$response = $client
|
||||||
->getAuthorizationServer()
|
->getAuthorizationServer()
|
||||||
->respondToAccessTokenRequest($request, JsonResponseFactory::createJsonResponse([]));
|
->respondToAccessTokenRequest(
|
||||||
|
$request,
|
||||||
|
JsonResponseFactory::createJsonResponse([])
|
||||||
|
);
|
||||||
|
|
||||||
Dispatcher::push(new Issued($response));
|
Dispatcher::push(new Issued($response));
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<p>Dear {{ user.firstName }},</p>
|
<p>{{ user.first_name }},</p>
|
||||||
|
|
||||||
<p>We received a request to reset your password. Click the link below to set a new password:</p>
|
<p>We received a request to reset your password. Click the link below to set a new password:</p>
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
|||||||
use League\OAuth2\Server\AuthorizationServer;
|
use League\OAuth2\Server\AuthorizationServer;
|
||||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||||
|
use League\OAuth2\Server\Grant\ClientCredentialsGrant as ClientCredentialsGrant;
|
||||||
use Random\RandomException;
|
use Random\RandomException;
|
||||||
use Siteworxpro\App\Helpers\Rand;
|
use Siteworxpro\App\Helpers\Rand;
|
||||||
use Siteworxpro\App\Models\ClientRedirectUri;
|
use Siteworxpro\App\Models\ClientRedirectUri;
|
||||||
@@ -195,6 +196,9 @@ class Client extends Model implements ClientEntityInterface
|
|||||||
Key::loadFromAsciiSafeString($this->encryption_key)
|
Key::loadFromAsciiSafeString($this->encryption_key)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$accessTokenTtl = $this->capabilities->toArray()['tokenSettings']['accessTokenTTL'] ?? 'PT1H';
|
||||||
|
$refreshTokenTtl = $this->capabilities->toArray()['tokenSettings']['refreshTokenTTL'] ?? 'P1M';
|
||||||
|
|
||||||
if (!empty($this->grant_types)) {
|
if (!empty($this->grant_types)) {
|
||||||
foreach ($this->grant_types as $grantType) {
|
foreach ($this->grant_types as $grantType) {
|
||||||
switch ($grantType) {
|
switch ($grantType) {
|
||||||
@@ -204,22 +208,22 @@ class Client extends Model implements ClientEntityInterface
|
|||||||
new \Siteworxpro\App\OAuth\RefreshTokenRepository(),
|
new \Siteworxpro\App\OAuth\RefreshTokenRepository(),
|
||||||
new \DateInterval('PT10M')
|
new \DateInterval('PT10M')
|
||||||
);
|
);
|
||||||
$grant->setRefreshTokenTTL(new \DateInterval('P1M'));
|
$grant->setRefreshTokenTTL(new \DateInterval($refreshTokenTtl));
|
||||||
break;
|
break;
|
||||||
case 'client_credentials':
|
case 'client_credentials':
|
||||||
$grant = new \League\OAuth2\Server\Grant\ClientCredentialsGrant();
|
$grant = new ClientCredentialsGrant();
|
||||||
break;
|
break;
|
||||||
case 'refresh_token':
|
case 'refresh_token':
|
||||||
$grant = new \League\OAuth2\Server\Grant\RefreshTokenGrant(
|
$grant = new \League\OAuth2\Server\Grant\RefreshTokenGrant(
|
||||||
new \Siteworxpro\App\OAuth\RefreshTokenRepository()
|
new \Siteworxpro\App\OAuth\RefreshTokenRepository()
|
||||||
);
|
);
|
||||||
$grant->setRefreshTokenTTL(new \DateInterval('P1M'));
|
$grant->setRefreshTokenTTL(new \DateInterval($refreshTokenTtl));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
continue 2;
|
continue 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
$authorizationServer->enableGrantType($grant);
|
$authorizationServer->enableGrantType($grant, new \DateInterval($accessTokenTtl));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ class ClientCapabilities implements Arrayable
|
|||||||
'logoUrl' => null,
|
'logoUrl' => null,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
private array $tokenSettings = [
|
||||||
|
'accessTokenTTL' => 'PT1H',
|
||||||
|
'refreshTokenTTL' => 'P1M',
|
||||||
|
];
|
||||||
|
|
||||||
public function __construct(array $capabilities = [])
|
public function __construct(array $capabilities = [])
|
||||||
{
|
{
|
||||||
if (isset($capabilities['userPass'])) {
|
if (isset($capabilities['userPass'])) {
|
||||||
@@ -47,6 +52,10 @@ class ClientCapabilities implements Arrayable
|
|||||||
if (isset($capabilities['support_email'])) {
|
if (isset($capabilities['support_email'])) {
|
||||||
$this->support_email = (string)$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
|
public static function fromJson(string $data): self
|
||||||
@@ -66,7 +75,8 @@ class ClientCapabilities implements Arrayable
|
|||||||
'passkey' => "bool",
|
'passkey' => "bool",
|
||||||
'socials' => "array",
|
'socials' => "array",
|
||||||
'branding' => "array",
|
'branding' => "array",
|
||||||
'support_email' => "string"
|
'support_email' => "string",
|
||||||
|
'tokenSettings' => "array",
|
||||||
])]
|
])]
|
||||||
public function toArray(): array
|
public function toArray(): array
|
||||||
{
|
{
|
||||||
@@ -77,6 +87,7 @@ class ClientCapabilities implements Arrayable
|
|||||||
'socials' => $this->socials,
|
'socials' => $this->socials,
|
||||||
'branding' => $this->branding,
|
'branding' => $this->branding,
|
||||||
'support_email' => $this->support_email,
|
'support_email' => $this->support_email,
|
||||||
|
'tokenSettings' => $this->tokenSettings,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user