You've already forked php-auth
generated from siteworxpro/Php-Template
Basics of auth
Some checks failed
🧪✨ Tests Workflow / 🛡️ 🔒 Library Audit (push) Successful in 2m31s
🧪✨ Tests Workflow / 📝 ✨ Code Lint (push) Successful in 2m24s
🧪✨ Tests Workflow / 🛡️ 🔒 License Check (push) Successful in 2m57s
🧪✨ Tests Workflow / 🧪 ✨ Database Migrations (push) Successful in 3m14s
🧪✨ Tests Workflow / 🐙 🔍 Code Sniffer (push) Failing after 2m58s
🧪✨ Tests Workflow / 🧪 ✅ Unit Tests (push) Failing after 1m24s
Some checks failed
🧪✨ Tests Workflow / 🛡️ 🔒 Library Audit (push) Successful in 2m31s
🧪✨ Tests Workflow / 📝 ✨ Code Lint (push) Successful in 2m24s
🧪✨ Tests Workflow / 🛡️ 🔒 License Check (push) Successful in 2m57s
🧪✨ Tests Workflow / 🧪 ✨ Database Migrations (push) Successful in 3m14s
🧪✨ Tests Workflow / 🐙 🔍 Code Sniffer (push) Failing after 2m58s
🧪✨ Tests Workflow / 🧪 ✅ Unit Tests (push) Failing after 1m24s
This commit is contained in:
16
.dev/.env
Normal file
16
.dev/.env
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
JWT_ISSUER: https://auth.siteworxpro.com/application/o/postman/
|
||||||
|
JWT_AUDIENCE: 1RWyqJFlyA4hmsDzq6kSxs0LXvk7UgEAfgmBCpQ9
|
||||||
|
JWT_SIGNING_KEY: https://auth.siteworxpro.com/application/o/postman/.well-known/openid-configuration
|
||||||
|
QUEUE_BROKER: redis
|
||||||
|
PHP_IDE_CONFIG: serverName=localhost
|
||||||
|
WORKERS: 1
|
||||||
|
GRPC_WORKERS: 1
|
||||||
|
DEBUG: 1
|
||||||
|
REDIS_HOST: redis
|
||||||
|
DB_HOST: postgres
|
||||||
|
DEV_MODE: 1
|
||||||
|
APP_ENCRYPTION_KEY: base64:40U+IWaPTpp5o23quMfxcZJ0lOzkNy07SQ1rH6AV13o=
|
||||||
|
DB_USERNAME: siteworxpro
|
||||||
|
DB_PASSWORD: password
|
||||||
|
DB_DATABASE: siteworxpro
|
||||||
|
DB_PORT: 5432
|
||||||
@@ -73,12 +73,8 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
environment:
|
env_file:
|
||||||
DB_USERNAME: ${DB_USERNAME:-siteworxpro}
|
- .env
|
||||||
DB_PASSWORD: ${DB_PASSWORD:-password}
|
|
||||||
DB_DATABASE: ${DB_DATABASE:-siteworxpro}
|
|
||||||
DB_HOST: ${DB_HOST-postgres}
|
|
||||||
DB_PORT: ${DB_PORT-5432}
|
|
||||||
|
|
||||||
dev-runtime:
|
dev-runtime:
|
||||||
labels:
|
labels:
|
||||||
@@ -116,18 +112,8 @@ services:
|
|||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
environment:
|
env_file:
|
||||||
JWT_ISSUER: https://auth.siteworxpro.com/application/o/postman/
|
- .env
|
||||||
JWT_AUDIENCE: 1RWyqJFlyA4hmsDzq6kSxs0LXvk7UgEAfgmBCpQ9
|
|
||||||
JWT_SIGNING_KEY: https://auth.siteworxpro.com/application/o/postman/.well-known/openid-configuration
|
|
||||||
QUEUE_BROKER: redis
|
|
||||||
PHP_IDE_CONFIG: serverName=localhost
|
|
||||||
WORKERS: 1
|
|
||||||
GRPC_WORKERS: 1
|
|
||||||
DEBUG: 1
|
|
||||||
REDIS_HOST: redis
|
|
||||||
DB_HOST: postgres
|
|
||||||
DEV_MODE: 1
|
|
||||||
|
|
||||||
## Kafka and Zookeeper for local development
|
## Kafka and Zookeeper for local development
|
||||||
kafka-ui:
|
kafka-ui:
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ return [
|
|||||||
'app' => [
|
'app' => [
|
||||||
'log_level' => Env::get('LOG_LEVEL', 'debug'),
|
'log_level' => Env::get('LOG_LEVEL', 'debug'),
|
||||||
'dev_mode' => Env::get('DEV_MODE', false, 'bool'),
|
'dev_mode' => Env::get('DEV_MODE', false, 'bool'),
|
||||||
|
'url' => Env::get('APP_URL', 'https://localhost'),
|
||||||
|
'encryption_key' => Env::get('APP_ENCRYPTION_KEY', 'base64:change_me'),
|
||||||
],
|
],
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,41 +1,41 @@
|
|||||||
create table clients
|
create table clients
|
||||||
(
|
(
|
||||||
id uuid default gen_random_uuid()
|
id VARCHAR(26) not null
|
||||||
constraint client_pk
|
constraint client_pk
|
||||||
primary key,
|
primary key,
|
||||||
client_id varchar not null
|
client_id varchar not null
|
||||||
constraint client_client_id_key
|
constraint client_client_id_key
|
||||||
unique,
|
unique,
|
||||||
client_secret varchar not null,
|
client_secret varchar not null,
|
||||||
name varchar not null,
|
name varchar not null,
|
||||||
description varchar default '',
|
description varchar default '',
|
||||||
private_key text not null,
|
private_key text not null,
|
||||||
encryption_key text not null,
|
encryption_key text not null,
|
||||||
grant_types jsonb not null default '[]'::jsonb,
|
grant_types jsonb not null default '[]'::jsonb,
|
||||||
capabilities jsonb not null default '[]'::jsonb,
|
capabilities jsonb not null default '[]'::jsonb,
|
||||||
confidential boolean not null default true,
|
confidential boolean not null default true,
|
||||||
created_at timestamp default now(),
|
created_at timestamp default now(),
|
||||||
updated_at timestamp default now()
|
updated_at timestamp default now()
|
||||||
);
|
);
|
||||||
|
|
||||||
create table client_redirect_uris
|
create table client_redirect_uris
|
||||||
(
|
(
|
||||||
id uuid default gen_random_uuid()
|
id VARCHAR(26) not null
|
||||||
constraint client_redirect_uris_pk
|
constraint client_redirect_uris_pk
|
||||||
primary key,
|
primary key,
|
||||||
client_id uuid not null
|
client_id VARCHAR(26) not null
|
||||||
constraint client_redirect_uris_client_id_fk
|
constraint client_redirect_uris_client_id_fk
|
||||||
references clients
|
references clients
|
||||||
on delete cascade,
|
on delete cascade,
|
||||||
redirect_uri varchar not null
|
redirect_uri varchar not null
|
||||||
);
|
);
|
||||||
|
|
||||||
create table scopes
|
create table scopes
|
||||||
(
|
(
|
||||||
id uuid default gen_random_uuid()
|
id VARCHAR(26) not null
|
||||||
constraint scopes_pk
|
constraint scopes_pk
|
||||||
primary key,
|
primary key,
|
||||||
name varchar not null
|
name varchar not null
|
||||||
constraint scopes_name_key
|
constraint scopes_name_key
|
||||||
unique,
|
unique,
|
||||||
description varchar
|
description varchar
|
||||||
@@ -43,14 +43,14 @@ create table scopes
|
|||||||
|
|
||||||
create table client_scopes
|
create table client_scopes
|
||||||
(
|
(
|
||||||
id uuid default gen_random_uuid()
|
id VARCHAR(26) not null
|
||||||
constraint client_scopes_pk
|
constraint client_scopes_pk
|
||||||
primary key,
|
primary key,
|
||||||
client_id uuid not null
|
client_id VARCHAR(26) not null
|
||||||
constraint client_scopes_client_id_fk
|
constraint client_scopes_client_id_fk
|
||||||
references clients
|
references clients
|
||||||
on delete cascade,
|
on delete cascade,
|
||||||
scope_id uuid not null
|
scope_id VARCHAR(26) not null
|
||||||
constraint client_scopes_scope_id_fk
|
constraint client_scopes_scope_id_fk
|
||||||
references scopes
|
references scopes
|
||||||
on delete cascade,
|
on delete cascade,
|
||||||
@@ -60,29 +60,29 @@ create table client_scopes
|
|||||||
|
|
||||||
create table users
|
create table users
|
||||||
(
|
(
|
||||||
id uuid default gen_random_uuid()
|
id VARCHAR(26) not null
|
||||||
constraint users_pk
|
constraint users_pk
|
||||||
primary key,
|
primary key,
|
||||||
first_name varchar not null,
|
first_name varchar not null,
|
||||||
last_name varchar not null,
|
last_name varchar not null,
|
||||||
email varchar not null
|
email varchar not null
|
||||||
constraint users_email_key
|
constraint users_email_key
|
||||||
unique,
|
unique,
|
||||||
password varchar not null,
|
password varchar not null,
|
||||||
created_at timestamp default now(),
|
created_at timestamp default now(),
|
||||||
updated_at timestamp default now()
|
updated_at timestamp default now()
|
||||||
);
|
);
|
||||||
|
|
||||||
create table client_users
|
create table client_users
|
||||||
(
|
(
|
||||||
id uuid default gen_random_uuid()
|
id VARCHAR(26) not null
|
||||||
constraint client_users_pk
|
constraint client_users_pk
|
||||||
primary key,
|
primary key,
|
||||||
client_id uuid not null
|
client_id VARCHAR(26) not null
|
||||||
constraint client_users_client_id_fk
|
constraint client_users_client_id_fk
|
||||||
references clients
|
references clients
|
||||||
on delete cascade,
|
on delete cascade,
|
||||||
user_id uuid not null
|
user_id VARCHAR(26) not null
|
||||||
constraint client_users_user_id_fk
|
constraint client_users_user_id_fk
|
||||||
references users
|
references users
|
||||||
on delete cascade,
|
on delete cascade,
|
||||||
|
|||||||
@@ -4,9 +4,7 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div class="flex flex-col items-center justify-center">
|
<div class="flex flex-col items-center justify-center">
|
||||||
<div>
|
<div>
|
||||||
<Image width="300"
|
|
||||||
src="https://i.careeruprising.com/_Pa5TnsUJ5v-EHQQZy3BHnbaiCjMGxusd7qNcvhd8jA/pr:sm/sm:1/enc/Ec8S-CxpyLc2M5XdibEf85vGU5KNfdR0Dx8Qf6DI2nbZG85hSSFtDV7TuynR5djSw5jhdTIyjd5xDX5z-Dgemw"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="text-2xl mt-5">
|
<div class="text-2xl mt-5">
|
||||||
<span v-if="capabilities.client_name !== ''">{{ capabilities.client_name }}</span>
|
<span v-if="capabilities.client_name !== ''">{{ capabilities.client_name }}</span>
|
||||||
@@ -270,7 +268,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
||||||
axios.post('/login', this.form).then(r => {
|
axios.post('/authorize', this.form).then(r => {
|
||||||
window.location.href = r.data.location
|
window.location.href = r.data.location
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
this.$toast.add({
|
this.$toast.add({
|
||||||
|
|||||||
17
src/Api.php
17
src/Api.php
@@ -9,11 +9,13 @@ use League\Route\Http\Exception\NotFoundException;
|
|||||||
use League\Route\RouteGroup;
|
use League\Route\RouteGroup;
|
||||||
use League\Route\Router;
|
use League\Route\Router;
|
||||||
use Nyholm\Psr7\Factory\Psr17Factory;
|
use Nyholm\Psr7\Factory\Psr17Factory;
|
||||||
|
use Siteworxpro\App\Controllers\AccessTokenController;
|
||||||
use Siteworxpro\App\Controllers\AuthorizeController;
|
use Siteworxpro\App\Controllers\AuthorizeController;
|
||||||
use Siteworxpro\App\Controllers\CapabilitiesController;
|
use Siteworxpro\App\Controllers\CapabilitiesController;
|
||||||
use Siteworxpro\App\Controllers\HealthcheckController;
|
use Siteworxpro\App\Controllers\HealthcheckController;
|
||||||
use Siteworxpro\App\Controllers\IndexController;
|
use Siteworxpro\App\Controllers\IndexController;
|
||||||
use Siteworxpro\App\Controllers\OpenApiController;
|
use Siteworxpro\App\Controllers\OpenApiController;
|
||||||
|
use Siteworxpro\App\Controllers\OpenIdController;
|
||||||
use Siteworxpro\App\Http\JsonResponseFactory;
|
use Siteworxpro\App\Http\JsonResponseFactory;
|
||||||
use Siteworxpro\App\Http\Middleware\CorsMiddleware;
|
use Siteworxpro\App\Http\Middleware\CorsMiddleware;
|
||||||
use Siteworxpro\App\Http\Middleware\JwtMiddleware;
|
use Siteworxpro\App\Http\Middleware\JwtMiddleware;
|
||||||
@@ -22,6 +24,7 @@ use Siteworxpro\App\Http\Responses\NotFoundResponse;
|
|||||||
use Siteworxpro\App\Http\Responses\ServerErrorResponse;
|
use Siteworxpro\App\Http\Responses\ServerErrorResponse;
|
||||||
use Siteworxpro\App\Services\Facades\Config;
|
use Siteworxpro\App\Services\Facades\Config;
|
||||||
use Siteworxpro\App\Services\Facades\Logger;
|
use Siteworxpro\App\Services\Facades\Logger;
|
||||||
|
use Siteworxpro\HttpStatus\CodesEnum;
|
||||||
use Spiral\RoadRunner\Http\PSR7Worker;
|
use Spiral\RoadRunner\Http\PSR7Worker;
|
||||||
use Spiral\RoadRunner\Worker;
|
use Spiral\RoadRunner\Worker;
|
||||||
|
|
||||||
@@ -84,7 +87,14 @@ class Api
|
|||||||
$group->get('/capabilities', CapabilitiesController::class . '::get');
|
$group->get('/capabilities', CapabilitiesController::class . '::get');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Authorize URL
|
||||||
$this->router->get('/authorize', AuthorizeController::class . '::get');
|
$this->router->get('/authorize', AuthorizeController::class . '::get');
|
||||||
|
$this->router->post('/authorize', AuthorizeController::class . '::post');
|
||||||
|
|
||||||
|
$this->router->group('/client/{client_id}', function (RouteGroup $group) {
|
||||||
|
$group->get('/.well-known/openid-configuration', OpenIdController::class . '::get');
|
||||||
|
$group->post('/access_token', AccessTokenController::class . '::post');
|
||||||
|
});
|
||||||
|
|
||||||
$this->router->middleware(new CorsMiddleware());
|
$this->router->middleware(new CorsMiddleware());
|
||||||
$this->router->middleware(new JwtMiddleware());
|
$this->router->middleware(new JwtMiddleware());
|
||||||
@@ -125,14 +135,17 @@ class Api
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->worker->respond(
|
$this->worker->respond(
|
||||||
JsonResponseFactory::createJsonResponse(new NotFoundResponse($uri))
|
JsonResponseFactory::createJsonResponse(new NotFoundResponse($uri), CodesEnum::NOT_FOUND)
|
||||||
);
|
);
|
||||||
} catch (\Throwable $e) {
|
} catch (\Throwable $e) {
|
||||||
Logger::error($e->getMessage());
|
Logger::error($e->getMessage());
|
||||||
Logger::error($e->getTraceAsString());
|
Logger::error($e->getTraceAsString());
|
||||||
|
|
||||||
$this->worker->respond(
|
$this->worker->respond(
|
||||||
JsonResponseFactory::createJsonResponse(new ServerErrorResponse($e))
|
JsonResponseFactory::createJsonResponse(
|
||||||
|
new ServerErrorResponse($e),
|
||||||
|
CodesEnum::INTERNAL_SERVER_ERROR
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,11 @@ declare(strict_types=1);
|
|||||||
namespace Siteworxpro\App\Cli;
|
namespace Siteworxpro\App\Cli;
|
||||||
|
|
||||||
use Ahc\Cli\Application;
|
use Ahc\Cli\Application;
|
||||||
|
use Siteworxpro\App\Cli\Commands\Crypt\GenerateKey;
|
||||||
use Siteworxpro\App\Cli\Commands\OAuth\AddRedirectUri;
|
use Siteworxpro\App\Cli\Commands\OAuth\AddRedirectUri;
|
||||||
use Siteworxpro\App\Cli\Commands\OAuth\CreateClient;
|
use Siteworxpro\App\Cli\Commands\OAuth\CreateClient;
|
||||||
use Siteworxpro\App\Cli\Commands\Queue\Start;
|
use Siteworxpro\App\Cli\Commands\Queue\Start;
|
||||||
|
use Siteworxpro\App\Cli\Commands\User\Add;
|
||||||
use Siteworxpro\App\Helpers\Version;
|
use Siteworxpro\App\Helpers\Version;
|
||||||
use Siteworxpro\App\Kernel;
|
use Siteworxpro\App\Kernel;
|
||||||
|
|
||||||
@@ -25,7 +27,9 @@ class App
|
|||||||
|
|
||||||
$this->app->add(new CreateClient());
|
$this->app->add(new CreateClient());
|
||||||
$this->app->add(new AddRedirectUri());
|
$this->app->add(new AddRedirectUri());
|
||||||
|
$this->app->add(new Add());
|
||||||
$this->app->add(new Start());
|
$this->app->add(new Start());
|
||||||
|
$this->app->add(new GenerateKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function run(): int
|
public function run(): int
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace Siteworxpro\App\Cli\Commands;
|
|||||||
use Ahc\Cli\Application as App;
|
use Ahc\Cli\Application as App;
|
||||||
use League\CLImate\CLImate;
|
use League\CLImate\CLImate;
|
||||||
|
|
||||||
abstract class Command extends \Ahc\Cli\Input\Command
|
abstract class Command extends \Ahc\Cli\Input\Command implements CommandInterface
|
||||||
{
|
{
|
||||||
protected Climate $climate;
|
protected Climate $climate;
|
||||||
|
|
||||||
|
|||||||
30
src/Cli/Commands/Crypt/GenerateKey.php
Normal file
30
src/Cli/Commands/Crypt/GenerateKey.php
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Siteworxpro\App\Cli\Commands\Crypt;
|
||||||
|
|
||||||
|
use Random\RandomException;
|
||||||
|
use Siteworxpro\App\Cli\Commands\Command;
|
||||||
|
|
||||||
|
class GenerateKey extends Command
|
||||||
|
{
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct('crypt:generate-key', 'Generate a new encryption key for the application');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws RandomException
|
||||||
|
*/
|
||||||
|
public function execute(): int
|
||||||
|
{
|
||||||
|
$key = base64_encode(random_bytes(SODIUM_CRYPTO_SECRETBOX_KEYBYTES));
|
||||||
|
|
||||||
|
$this->climate->info('Generated Encryption Key:');
|
||||||
|
$this->climate->out('base64:' . $key);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
80
src/Cli/Commands/User/Add.php
Normal file
80
src/Cli/Commands/User/Add.php
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Siteworxpro\App\Cli\Commands\User;
|
||||||
|
|
||||||
|
use Siteworxpro\App\Cli\Commands\Command;
|
||||||
|
use Siteworxpro\App\Models\ClientUser;
|
||||||
|
use Siteworxpro\App\Models\User;
|
||||||
|
use Siteworxpro\App\OAuth\Entities\Client;
|
||||||
|
|
||||||
|
class Add extends Command
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct('user:add', 'Add a new user to the system');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(): int
|
||||||
|
{
|
||||||
|
$clients = Client::all(['id', 'name']);
|
||||||
|
|
||||||
|
$this->climate->info('Available OAuth Clients:');
|
||||||
|
foreach ($clients as $client) {
|
||||||
|
$this->climate->out("[$client->id] $client->name");
|
||||||
|
}
|
||||||
|
|
||||||
|
$input = $this->climate->input('Enter the client ID to associate the new user with: ');
|
||||||
|
$input->accept(
|
||||||
|
$clients->pluck('id')->toArray()
|
||||||
|
);
|
||||||
|
|
||||||
|
$id = $input->prompt();
|
||||||
|
|
||||||
|
$client = Client::find($id);
|
||||||
|
if (!$client) {
|
||||||
|
$this->climate->error('Client not found.');
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->climate->info("Adding a new user for client: $client->name");
|
||||||
|
|
||||||
|
$input = $this->climate->input('Enter the user\'s email:');
|
||||||
|
$email = $input->prompt();
|
||||||
|
|
||||||
|
$user = User::where('email', $email)->first();
|
||||||
|
if ($user) {
|
||||||
|
$this->climate->error('A user with this email already exists. Associating the user with the client.');
|
||||||
|
$clientUser = new ClientUser();
|
||||||
|
$clientUser->client_id = $client->id;
|
||||||
|
$clientUser->user_id = $user->id;
|
||||||
|
$clientUser->save();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$passwordInput = $this->climate->password('Enter the user\'s password: 🔐');
|
||||||
|
$password = $passwordInput->prompt();
|
||||||
|
|
||||||
|
$firstNameInput = $this->climate->input('Enter the user\'s first name: ');
|
||||||
|
$firstName = $firstNameInput->prompt();
|
||||||
|
|
||||||
|
$lastNameInput = $this->climate->input('Enter the user\'s last name: ');
|
||||||
|
$lastName = $lastNameInput->prompt();
|
||||||
|
|
||||||
|
$user = new User();
|
||||||
|
$user->email = $email;
|
||||||
|
$user->password = $password;
|
||||||
|
$user->first_name = $firstName;
|
||||||
|
$user->last_name = $lastName;
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
$clientUser = new ClientUser();
|
||||||
|
$clientUser->client_id = $client->id;
|
||||||
|
$clientUser->user_id = $user->id;
|
||||||
|
$clientUser->save();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
66
src/Controllers/AccessTokenController.php
Normal file
66
src/Controllers/AccessTokenController.php
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Siteworxpro\App\Controllers;
|
||||||
|
|
||||||
|
use Defuse\Crypto\Exception\BadFormatException;
|
||||||
|
use Defuse\Crypto\Exception\EnvironmentIsBrokenException;
|
||||||
|
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||||
|
use Nyholm\Psr7\ServerRequest;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Siteworxpro\App\Http\JsonResponseFactory;
|
||||||
|
use Siteworxpro\App\Http\Responses\GenericResponse;
|
||||||
|
use Siteworxpro\App\OAuth\Entities\AuthorizationCode;
|
||||||
|
use Siteworxpro\App\OAuth\Entities\Client;
|
||||||
|
use Siteworxpro\HttpStatus\CodesEnum;
|
||||||
|
|
||||||
|
final class AccessTokenController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param ServerRequest $request
|
||||||
|
* @return ResponseInterface
|
||||||
|
* @throws BadFormatException
|
||||||
|
* @throws EnvironmentIsBrokenException
|
||||||
|
* @throws \JsonException
|
||||||
|
* @throws OAuthServerException
|
||||||
|
*/
|
||||||
|
public function post(ServerRequest $request): ResponseInterface
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$grantType = $request->getParsedBody()['grant_type'] ?? null;
|
||||||
|
$client = Client::find($request->getAttribute('client_id'));
|
||||||
|
if ($client === null) {
|
||||||
|
return JsonResponseFactory::createJsonResponse(
|
||||||
|
new GenericResponse('Invalid client'),
|
||||||
|
CodesEnum::BAD_REQUEST,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($grantType) {
|
||||||
|
case 'authorization_code':
|
||||||
|
return $client
|
||||||
|
->getAuthorizationServer()
|
||||||
|
->respondToAccessTokenRequest($request, JsonResponseFactory::createJsonResponse([]));
|
||||||
|
|
||||||
|
case 'refresh_token':
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return JsonResponseFactory::createJsonResponse(
|
||||||
|
new GenericResponse('Unsupported grant type'),
|
||||||
|
CodesEnum::BAD,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$response = $this->authorizationServer->respondToAccessTokenRequest(
|
||||||
|
$request,
|
||||||
|
new Response(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
} catch (OAuthServerException $e) {
|
||||||
|
return $e->generateHttpResponse(new Response());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/Controllers/Admin/ClientsController.php
Normal file
28
src/Controllers/Admin/ClientsController.php
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Siteworxpro\App\Controllers\Admin;
|
||||||
|
|
||||||
|
use Nyholm\Psr7\ServerRequest;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Siteworxpro\App\Attributes\Guards\Jwt;
|
||||||
|
use Siteworxpro\App\Attributes\Guards\Scope;
|
||||||
|
use Siteworxpro\App\Controllers\Controller;
|
||||||
|
use Siteworxpro\App\Http\JsonResponseFactory;
|
||||||
|
use Siteworxpro\App\OAuth\Entities\Client;
|
||||||
|
|
||||||
|
#[Jwt]
|
||||||
|
final class ClientsController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @throws \JsonException
|
||||||
|
*/
|
||||||
|
#[Scope(['admin:clients:view'])]
|
||||||
|
public function get(ServerRequest $request): ResponseInterface
|
||||||
|
{
|
||||||
|
$clients = Client::all();
|
||||||
|
|
||||||
|
return JsonResponseFactory::createJsonResponse($clients->toArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,12 +4,14 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Siteworxpro\App\Controllers;
|
namespace Siteworxpro\App\Controllers;
|
||||||
|
|
||||||
|
use Defuse\Crypto\Exception\BadFormatException;
|
||||||
|
use Defuse\Crypto\Exception\EnvironmentIsBrokenException;
|
||||||
use HansOtt\PSR7Cookies\SetCookie;
|
use HansOtt\PSR7Cookies\SetCookie;
|
||||||
use League\OAuth2\Server\Exception\OAuthServerException;
|
use League\OAuth2\Server\Exception\OAuthServerException;
|
||||||
|
use League\OAuth2\Server\RequestTypes\AuthorizationRequest;
|
||||||
use Nyholm\Psr7\Response;
|
use Nyholm\Psr7\Response;
|
||||||
use Nyholm\Psr7\ServerRequest;
|
use Nyholm\Psr7\ServerRequest;
|
||||||
use Nyholm\Psr7\Stream;
|
use Nyholm\Psr7\Stream;
|
||||||
use Psr\SimpleCache\InvalidArgumentException;
|
|
||||||
use Siteworxpro\App\Helpers\Rand;
|
use Siteworxpro\App\Helpers\Rand;
|
||||||
use Siteworxpro\App\Http\JsonResponseFactory;
|
use Siteworxpro\App\Http\JsonResponseFactory;
|
||||||
use Siteworxpro\App\Http\Responses\ServerErrorResponse;
|
use Siteworxpro\App\Http\Responses\ServerErrorResponse;
|
||||||
@@ -21,75 +23,64 @@ use Siteworxpro\HttpStatus\CodesEnum;
|
|||||||
final class AuthorizeController extends Controller
|
final class AuthorizeController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @throws InvalidArgumentException
|
* @param ServerRequest $request
|
||||||
|
* @return Response
|
||||||
|
* @throws BadFormatException
|
||||||
|
* @throws EnvironmentIsBrokenException
|
||||||
|
* @throws \JsonException
|
||||||
*/
|
*/
|
||||||
// #[\Override] public function post(ServerRequest $request): Response
|
public function post(ServerRequest $request): Response
|
||||||
// {
|
{
|
||||||
// $s = $request->getCookieParams()['s'] ?? '';
|
$s = $request->getCookieParams()['s'] ?? '';
|
||||||
//
|
|
||||||
// $password = $request->getParsedBody()['password'] ?? '';
|
$password = $request->getParsedBody()['password'] ?? '';
|
||||||
// $email = $request->getParsedBody()['email'] ?? '';
|
$email = $request->getParsedBody()['email'] ?? '';
|
||||||
//
|
|
||||||
// if (!$this->redis->get('session:' . $s)) {
|
if (!Redis::get('session:' . $s)) {
|
||||||
// $this->log->error('Session Timed out', ['session' => $s]);
|
Logger::warning('Session Timed out', ['session' => $s]);
|
||||||
//
|
|
||||||
// return $this->sendJsonResponse(
|
return JsonResponseFactory::createJsonResponse([]);
|
||||||
// [
|
}
|
||||||
// 'error' => "your login session has timed out. please try again."
|
|
||||||
// ],
|
/** @var AuthorizationRequest $authRequest */
|
||||||
// 400
|
$authRequest = unserialize(Redis::get('session:' . $s));
|
||||||
// );
|
|
||||||
// }
|
/** @var Client $client */
|
||||||
//
|
$client = $authRequest->getClient();
|
||||||
// /** @var AuthorizationRequest $authRequest */
|
|
||||||
// $authRequest = unserialize($this->redis->get('session:' . $s));
|
$authorizationServer = $client->getAuthorizationServer();
|
||||||
//
|
|
||||||
// if ($authRequest->isAuthorizationApproved()) {
|
if ($authRequest->isAuthorizationApproved()) {
|
||||||
// $response = $this
|
$response = $authorizationServer
|
||||||
// ->authorizationServer
|
->completeAuthorizationRequest($authRequest, JsonResponseFactory::createJsonResponse([]));
|
||||||
// ->completeAuthorizationRequest($authRequest, $this->sendJsonResponse());
|
|
||||||
//
|
return JsonResponseFactory::createJsonResponse([
|
||||||
// return $this->sendJsonResponse(
|
'success' => true,
|
||||||
// [
|
'location' => $response->getHeader('Location')[0]
|
||||||
// 'success' => true,
|
]);
|
||||||
// 'location' => $response->getHeader('Location')[0]
|
}
|
||||||
// ]
|
|
||||||
// );
|
$user = $client->loginUser($email, $password);
|
||||||
// }
|
|
||||||
//
|
if (!$user) {
|
||||||
// /** @var Client $client */
|
return JsonResponseFactory::createJsonResponse([
|
||||||
// $client = $authRequest->getClient();
|
'success' => false,
|
||||||
//
|
'reason' => 'login failed'
|
||||||
// /** @var LoginInterface $entitiesModel */
|
], CodesEnum::UNAUTHORIZED);
|
||||||
// $entitiesModel = $client->entities_model;
|
}
|
||||||
//
|
|
||||||
// /** @var User | null $entity */
|
$authRequest->setUser($user);
|
||||||
// $entity = $entitiesModel::performLogin($email, $password);
|
$authRequest->setAuthorizationApproved(true);
|
||||||
// if (!$entity) {
|
$response = $authorizationServer
|
||||||
// return $this->sendJsonResponse(
|
->completeAuthorizationRequest($authRequest, JsonResponseFactory::createJsonResponse([]));
|
||||||
// [
|
|
||||||
// 'success' => false,
|
Redis::del('session:' . $s);
|
||||||
// 'reason' => 'login failed'
|
|
||||||
// ],
|
return JsonResponseFactory::createJsonResponse([
|
||||||
// 401
|
'success' => true,
|
||||||
// );
|
'location' => $response->getHeader('Location')[0]
|
||||||
// }
|
]);
|
||||||
//
|
}
|
||||||
// $authRequest->setUser($entity);
|
|
||||||
// $authRequest->setAuthorizationApproved(true);
|
|
||||||
// $response = $this
|
|
||||||
// ->authorizationServer
|
|
||||||
// ->completeAuthorizationRequest($authRequest, $this->sendJsonResponse());
|
|
||||||
//
|
|
||||||
// $this->redis->delete('session:' . $s);
|
|
||||||
//
|
|
||||||
// return $this->sendJsonResponse(
|
|
||||||
// [
|
|
||||||
// 'success' => true,
|
|
||||||
// 'location' => $response->getHeader('Location')[0]
|
|
||||||
// ]
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws \Exception
|
* @throws \Exception
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ final class CapabilitiesController extends Controller
|
|||||||
return JsonResponseFactory::createJsonResponse(new NotFoundResponse($request->getUri()->getPath()));
|
return JsonResponseFactory::createJsonResponse(new NotFoundResponse($request->getUri()->getPath()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return JsonResponseFactory::createJsonResponse($client->capabilities->toArray());
|
return JsonResponseFactory::createJsonResponse(array_merge($client->capabilities->toArray(), [
|
||||||
|
'client_name' => $client->name,
|
||||||
|
]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
48
src/Controllers/OpenIdController.php
Normal file
48
src/Controllers/OpenIdController.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Siteworxpro\App\Controllers;
|
||||||
|
|
||||||
|
use Nyholm\Psr7\ServerRequest;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Siteworxpro\App\Http\JsonResponseFactory;
|
||||||
|
use Siteworxpro\App\OAuth\Entities\Client;
|
||||||
|
use Siteworxpro\App\Services\Facades\Config;
|
||||||
|
use Siteworxpro\HttpStatus\CodesEnum;
|
||||||
|
|
||||||
|
final class OpenIdController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @throws \JsonException
|
||||||
|
*/
|
||||||
|
public function get(ServerRequest $request): ResponseInterface
|
||||||
|
{
|
||||||
|
$clientId = $request->getAttribute('client_id');
|
||||||
|
|
||||||
|
$client = Client::find($clientId);
|
||||||
|
if (!$client) {
|
||||||
|
return JsonResponseFactory::createJsonResponse(
|
||||||
|
['error' => 'invalid_client'],
|
||||||
|
CodesEnum::BAD_REQUEST
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'issuer' => Config::get('app.url') . '/' . $clientId,
|
||||||
|
'authorization_endpoint' => Config::get('app.url') . '/authorize',
|
||||||
|
'token_endpoint' => Config::get('app.url') . '/client/' . $clientId . '/access_token',
|
||||||
|
'userinfo_endpoint' => Config::get('app.url') . '/user_info',
|
||||||
|
'end_session_endpoint' => Config::get('app.url') . '/end-session',
|
||||||
|
'introspection_endpoint' => Config::get('app.url') . '/introspect',
|
||||||
|
'revocation_endpoint' => Config::get('app.url') . '/revoke',
|
||||||
|
'device_authorization_endpoint' => Config::get('app.url') . '/device',
|
||||||
|
'jwks_uri' => Config::get('app.url') . '/client/' . $clientId . '/jwks',
|
||||||
|
'grant_types_supported' => $client->grant_types,
|
||||||
|
'scopes_supported' => $client->scopes->pluck('name')->toArray()
|
||||||
|
];
|
||||||
|
|
||||||
|
return JsonResponseFactory::createJsonResponse($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/Helpers/Encryption.php
Normal file
52
src/Helpers/Encryption.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Siteworxpro\App\Helpers;
|
||||||
|
|
||||||
|
use Random\RandomException;
|
||||||
|
|
||||||
|
readonly class Encryption
|
||||||
|
{
|
||||||
|
public function __construct(private string $key)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypt the given data with AES256-GCM
|
||||||
|
* @param string $data
|
||||||
|
* @return string
|
||||||
|
* @throws RandomException
|
||||||
|
* @throws \SodiumException
|
||||||
|
*/
|
||||||
|
public function encrypt(string $data): string
|
||||||
|
{
|
||||||
|
$nonce = random_bytes(SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
|
||||||
|
|
||||||
|
$enc = sodium_crypto_secretbox(
|
||||||
|
$data,
|
||||||
|
$nonce,
|
||||||
|
$this->key
|
||||||
|
);
|
||||||
|
|
||||||
|
return $nonce . $enc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrypt the given data with AES256-GCM
|
||||||
|
* @param string $encryptedData
|
||||||
|
* @return string
|
||||||
|
* @throws \SodiumException
|
||||||
|
*/
|
||||||
|
public function decrypt(string $encryptedData): string
|
||||||
|
{
|
||||||
|
$nonce = substr($encryptedData, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
|
||||||
|
$ciphertext = substr($encryptedData, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES);
|
||||||
|
|
||||||
|
return sodium_crypto_secretbox_open(
|
||||||
|
$ciphertext,
|
||||||
|
$nonce,
|
||||||
|
$this->key
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,12 +12,15 @@ abstract class Env
|
|||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param string $key
|
* @param string $key
|
||||||
* @param null $default
|
* @param mixed $default
|
||||||
* @param string $castTo
|
* @param string $castTo
|
||||||
* @return float|bool|int|string
|
* @return float|bool|int|string
|
||||||
*/
|
*/
|
||||||
public static function get(string $key, $default = null, string $castTo = 'string'): float | bool | int | string
|
public static function get(
|
||||||
{
|
string $key,
|
||||||
|
mixed $default = null,
|
||||||
|
string $castTo = 'string'
|
||||||
|
): float | bool | int | string {
|
||||||
$env = getenv($key) !== false ? getenv($key) : $default;
|
$env = getenv($key) !== false ? getenv($key) : $default;
|
||||||
|
|
||||||
return match ($castTo) {
|
return match ($castTo) {
|
||||||
|
|||||||
@@ -17,6 +17,6 @@ class Ulid
|
|||||||
*/
|
*/
|
||||||
public static function generate(): string
|
public static function generate(): string
|
||||||
{
|
{
|
||||||
return \Ulid\Ulid::generate()->getRandomness();
|
return (string) \Ulid\Ulid::generate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use Siteworxpro\App\Services\Facades\Dispatcher;
|
|||||||
use Siteworxpro\App\Services\ServiceProviders\BrokerServiceProvider;
|
use Siteworxpro\App\Services\ServiceProviders\BrokerServiceProvider;
|
||||||
use Siteworxpro\App\Services\ServiceProviders\CommandBusProvider;
|
use Siteworxpro\App\Services\ServiceProviders\CommandBusProvider;
|
||||||
use Siteworxpro\App\Services\ServiceProviders\DispatcherServiceProvider;
|
use Siteworxpro\App\Services\ServiceProviders\DispatcherServiceProvider;
|
||||||
|
use Siteworxpro\App\Services\ServiceProviders\EncryptionServiceProvider;
|
||||||
use Siteworxpro\App\Services\ServiceProviders\LoggerServiceProvider;
|
use Siteworxpro\App\Services\ServiceProviders\LoggerServiceProvider;
|
||||||
use Siteworxpro\App\Services\ServiceProviders\RedisServiceProvider;
|
use Siteworxpro\App\Services\ServiceProviders\RedisServiceProvider;
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ class Kernel
|
|||||||
DispatcherServiceProvider::class,
|
DispatcherServiceProvider::class,
|
||||||
BrokerServiceProvider::class,
|
BrokerServiceProvider::class,
|
||||||
CommandBusProvider::class,
|
CommandBusProvider::class,
|
||||||
|
EncryptionServiceProvider::class,
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -14,5 +14,4 @@ namespace Siteworxpro\App\Models;
|
|||||||
*/
|
*/
|
||||||
class ClientScope extends Model
|
class ClientScope extends Model
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,5 +14,5 @@ namespace Siteworxpro\App\Models;
|
|||||||
*/
|
*/
|
||||||
class ClientUser extends Model
|
class ClientUser extends Model
|
||||||
{
|
{
|
||||||
|
public $timestamps = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ declare(strict_types=1);
|
|||||||
namespace Siteworxpro\App\Models;
|
namespace Siteworxpro\App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model as ORM;
|
use Illuminate\Database\Eloquent\Model as ORM;
|
||||||
|
use Siteworxpro\App\Helpers\Ulid;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Model
|
* Class Model
|
||||||
@@ -16,4 +17,10 @@ use Illuminate\Database\Eloquent\Model as ORM;
|
|||||||
abstract class Model extends ORM
|
abstract class Model extends ORM
|
||||||
{
|
{
|
||||||
protected $dateFormat = 'Y-m-d H:i:s';
|
protected $dateFormat = 'Y-m-d H:i:s';
|
||||||
|
|
||||||
|
public function __construct(array $attributes = [])
|
||||||
|
{
|
||||||
|
parent::__construct($attributes);
|
||||||
|
$this->attributes['id'] = $this->attributes['id'] ?? Ulid::generate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ namespace Siteworxpro\App\Models;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||||
|
use League\OAuth2\Server\Entities\UserEntityInterface;
|
||||||
use OpenApi\Attributes as OA;
|
use OpenApi\Attributes as OA;
|
||||||
use Siteworxpro\App\Helpers\Ulid;
|
use Siteworxpro\App\Helpers\Ulid;
|
||||||
|
|
||||||
@@ -39,11 +40,10 @@ use Siteworxpro\App\Helpers\Ulid;
|
|||||||
new OA\Property(property: "created_at", type: "string", format: "date-time"),
|
new OA\Property(property: "created_at", type: "string", format: "date-time"),
|
||||||
]
|
]
|
||||||
)]
|
)]
|
||||||
class User extends Model
|
class User extends Model implements UserEntityInterface
|
||||||
{
|
{
|
||||||
use EntityTrait;
|
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
|
'id' => 'string',
|
||||||
'created_at' => 'datetime',
|
'created_at' => 'datetime',
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -58,12 +58,6 @@ class User extends Model
|
|||||||
'password',
|
'password',
|
||||||
];
|
];
|
||||||
|
|
||||||
public function __construct(array $attributes = [])
|
|
||||||
{
|
|
||||||
parent::__construct($attributes);
|
|
||||||
$this->attributes['id'] = $this->attributes['id'] ?? Ulid::generate();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getFullNameAttribute(): string
|
public function getFullNameAttribute(): string
|
||||||
{
|
{
|
||||||
return "$this->first_name $this->last_name";
|
return "$this->first_name $this->last_name";
|
||||||
@@ -77,4 +71,20 @@ class User extends Model
|
|||||||
strtolower($this->email)
|
strtolower($this->email)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function verifyPassword(string $password): bool
|
||||||
|
{
|
||||||
|
// Verify the provided password against the stored hashed password
|
||||||
|
return password_verify($password, $this->password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPasswordAttribute(string $password): void
|
||||||
|
{
|
||||||
|
$this->attributes['password'] = password_hash($password, PASSWORD_ARGON2ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getIdentifier(): string
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,4 +47,4 @@ class AccessTokenRepository implements AccessTokenRepositoryInterface
|
|||||||
|
|
||||||
return $accessToken === null;
|
return $accessToken === null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,26 +6,35 @@ namespace Siteworxpro\App\OAuth;
|
|||||||
|
|
||||||
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
|
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
|
||||||
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
|
use League\OAuth2\Server\Repositories\AuthCodeRepositoryInterface;
|
||||||
|
use Psr\SimpleCache\InvalidArgumentException;
|
||||||
|
use Siteworxpro\App\OAuth\Entities\AuthorizationCode;
|
||||||
|
|
||||||
class AuthCodeRepository implements AuthCodeRepositoryInterface
|
class AuthCodeRepository implements AuthCodeRepositoryInterface
|
||||||
{
|
{
|
||||||
public function getNewAuthCode(): AuthCodeEntityInterface
|
public function getNewAuthCode(): AuthCodeEntityInterface
|
||||||
{
|
{
|
||||||
// TODO: Implement getNewAuthCode() method.
|
return new AuthorizationCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function persistNewAuthCode(AuthCodeEntityInterface $authCodeEntity): void
|
public function persistNewAuthCode(AuthCodeEntityInterface | AuthorizationCode $authCodeEntity): void
|
||||||
{
|
{
|
||||||
// TODO: Implement persistNewAuthCode() method.
|
$authCodeEntity->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
public function revokeAuthCode(string $codeId): void
|
public function revokeAuthCode(string $codeId): void
|
||||||
{
|
{
|
||||||
// TODO: Implement revokeAuthCode() method.
|
$authCode = AuthorizationCode::find($codeId);
|
||||||
|
|
||||||
|
$authCode?->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isAuthCodeRevoked(string $codeId): bool
|
public function isAuthCodeRevoked(string $codeId): bool
|
||||||
{
|
{
|
||||||
// TODO: Implement isAuthCodeRevoked() method.
|
$authCode = AuthorizationCode::find($codeId);
|
||||||
|
|
||||||
|
return $authCode === null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,17 +40,15 @@ readonly class ClientRepository implements ClientRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function validateClient(string $clientIdentifier, ?string $clientSecret, ?string $grantType): bool
|
public function validateClient(string $clientIdentifier, ?string $clientSecret, ?string $grantType): bool
|
||||||
{
|
{
|
||||||
$client = Client::find($clientIdentifier);
|
if ($this->client->client_id != $clientIdentifier) {
|
||||||
|
|
||||||
if ($client === null) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($clientSecret && $client->client_secret != $clientSecret) {
|
if ($clientSecret && $this->client->client_secret != $clientSecret) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($grantType && !in_array($grantType, $client->grant_types)) {
|
if ($grantType && !in_array($grantType, $this->client->grant_types->toArray())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Siteworxpro\App\OAuth\Entities;
|
namespace Siteworxpro\App\OAuth\Entities;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||||
@@ -14,24 +15,31 @@ class AccessToken extends RedisModel implements AccessTokenEntityInterface
|
|||||||
{
|
{
|
||||||
use AccessTokenTrait;
|
use AccessTokenTrait;
|
||||||
|
|
||||||
|
private Client |null $client = null;
|
||||||
|
|
||||||
|
private string | null $userIdentifier = null;
|
||||||
|
|
||||||
|
/** @var ScopeEntityInterface|Scope[] */
|
||||||
|
private array $scopes = [];
|
||||||
|
|
||||||
public function getClient(): ClientEntityInterface
|
public function getClient(): ClientEntityInterface
|
||||||
{
|
{
|
||||||
// TODO: Implement getClient() method.
|
return $this->client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getExpiryDateTime(): DateTimeImmutable
|
public function getExpiryDateTime(): DateTimeImmutable
|
||||||
{
|
{
|
||||||
// TODO: Implement getExpiryDateTime() method.
|
return $this->expiryDateTime->toDateTimeImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getUserIdentifier(): string|null
|
public function getUserIdentifier(): string|null
|
||||||
{
|
{
|
||||||
// TODO: Implement getUserIdentifier() method.
|
return $this->userIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getScopes(): array
|
public function getScopes(): array
|
||||||
{
|
{
|
||||||
// TODO: Implement getScopes() method.
|
return $this->scopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static function getRedisPrefix(): string
|
protected static function getRedisPrefix(): string
|
||||||
@@ -41,21 +49,21 @@ class AccessToken extends RedisModel implements AccessTokenEntityInterface
|
|||||||
|
|
||||||
public function setExpiryDateTime(DateTimeImmutable $dateTime): void
|
public function setExpiryDateTime(DateTimeImmutable $dateTime): void
|
||||||
{
|
{
|
||||||
// TODO: Implement setExpiryDateTime() method.
|
$this->expiryDateTime = Carbon::instance($dateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUserIdentifier(string $identifier): void
|
public function setUserIdentifier(string $identifier): void
|
||||||
{
|
{
|
||||||
// TODO: Implement setUserIdentifier() method.
|
$this->userIdentifier = $identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setClient(ClientEntityInterface $client): void
|
public function setClient(ClientEntityInterface $client): void
|
||||||
{
|
{
|
||||||
// TODO: Implement setClient() method.
|
$this->client = $client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addScope(ScopeEntityInterface $scope): void
|
public function addScope(ScopeEntityInterface $scope): void
|
||||||
{
|
{
|
||||||
// TODO: Implement addScope() method.
|
$this->scopes[] = $scope;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Siteworxpro\App\OAuth\Entities;
|
namespace Siteworxpro\App\OAuth\Entities;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
|
use League\OAuth2\Server\Entities\AuthCodeEntityInterface;
|
||||||
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
use League\OAuth2\Server\Entities\ClientEntityInterface;
|
||||||
@@ -14,6 +15,15 @@ class AuthorizationCode extends RedisModel implements AuthCodeEntityInterface
|
|||||||
{
|
{
|
||||||
use AuthCodeTrait;
|
use AuthCodeTrait;
|
||||||
|
|
||||||
|
private Client | null $client = null;
|
||||||
|
|
||||||
|
private string | null $userIdentifier = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array<ScopeEntityInterface | Scope> $scopes
|
||||||
|
*/
|
||||||
|
private array $scopes = [];
|
||||||
|
|
||||||
protected static function getRedisPrefix(): string
|
protected static function getRedisPrefix(): string
|
||||||
{
|
{
|
||||||
return 'oauth_auth_code';
|
return 'oauth_auth_code';
|
||||||
@@ -21,41 +31,41 @@ class AuthorizationCode extends RedisModel implements AuthCodeEntityInterface
|
|||||||
|
|
||||||
public function getExpiryDateTime(): DateTimeImmutable
|
public function getExpiryDateTime(): DateTimeImmutable
|
||||||
{
|
{
|
||||||
// TODO: Implement getExpiryDateTime() method.
|
return $this->expiryDateTime->toDateTimeImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setExpiryDateTime(DateTimeImmutable $dateTime): void
|
public function setExpiryDateTime(DateTimeImmutable $dateTime): void
|
||||||
{
|
{
|
||||||
// TODO: Implement setExpiryDateTime() method.
|
$this->expiryDateTime = Carbon::instance($dateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setUserIdentifier(string $identifier): void
|
public function setUserIdentifier(string $identifier): void
|
||||||
{
|
{
|
||||||
// TODO: Implement setUserIdentifier() method.
|
$this->userIdentifier = $identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getUserIdentifier(): string|null
|
public function getUserIdentifier(): string|null
|
||||||
{
|
{
|
||||||
// TODO: Implement getUserIdentifier() method.
|
return $this->userIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getClient(): ClientEntityInterface
|
public function getClient(): ClientEntityInterface | Client
|
||||||
{
|
{
|
||||||
// TODO: Implement getClient() method.
|
return $this->client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setClient(ClientEntityInterface $client): void
|
public function setClient(ClientEntityInterface $client): void
|
||||||
{
|
{
|
||||||
// TODO: Implement setClient() method.
|
$this->client = $client;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addScope(ScopeEntityInterface $scope): void
|
public function addScope(ScopeEntityInterface $scope): void
|
||||||
{
|
{
|
||||||
// TODO: Implement addScope() method.
|
$this->scopes[] = $scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getScopes(): array
|
public function getScopes(): array
|
||||||
{
|
{
|
||||||
// TODO: Implement getScopes() method.
|
return $this->scopes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ use Siteworxpro\App\OAuth\ScopeRepository;
|
|||||||
* @property string $description
|
* @property string $description
|
||||||
* @property string $private_key
|
* @property string $private_key
|
||||||
* @property string $encryption_key
|
* @property string $encryption_key
|
||||||
* @property string[] $grant_types
|
* @property Collection<string> $grant_types
|
||||||
* @property bool $confidential
|
* @property bool $confidential
|
||||||
*
|
*
|
||||||
* @property-read ClientCapabilities $capabilities
|
* @property-read ClientCapabilities $capabilities
|
||||||
@@ -101,7 +101,14 @@ class Client extends Model implements ClientEntityInterface
|
|||||||
*/
|
*/
|
||||||
public function scopes(): HasManyThrough
|
public function scopes(): HasManyThrough
|
||||||
{
|
{
|
||||||
return $this->hasManyThrough(Scope::class, ClientScope::class);
|
return $this->hasManyThrough(
|
||||||
|
Scope::class,
|
||||||
|
ClientScope::class,
|
||||||
|
'client_id',
|
||||||
|
'id',
|
||||||
|
'id',
|
||||||
|
'scope_id'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,7 +116,14 @@ class Client extends Model implements ClientEntityInterface
|
|||||||
*/
|
*/
|
||||||
public function users(): HasManyThrough
|
public function users(): HasManyThrough
|
||||||
{
|
{
|
||||||
return $this->hasManyThrough(User::class, ClientUser::class);
|
return $this->hasManyThrough(
|
||||||
|
User::class,
|
||||||
|
ClientUser::class,
|
||||||
|
'client_id',
|
||||||
|
'id',
|
||||||
|
'id',
|
||||||
|
'user_id'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -154,7 +168,7 @@ class Client extends Model implements ClientEntityInterface
|
|||||||
*/
|
*/
|
||||||
public function setCapabilitiesAttribute(ClientCapabilities $capabilities): void
|
public function setCapabilitiesAttribute(ClientCapabilities $capabilities): void
|
||||||
{
|
{
|
||||||
$this->attributes->capabilities = $capabilities->toJson();
|
$this->attributes['capabilities'] = $capabilities->toJson();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -203,4 +217,16 @@ class Client extends Model implements ClientEntityInterface
|
|||||||
|
|
||||||
return $authorizationServer;
|
return $authorizationServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function loginUser(string $username, string $password): ?User
|
||||||
|
{
|
||||||
|
/** @var User|null $user */
|
||||||
|
$user = $this->users()->where('email', $username)->first();
|
||||||
|
|
||||||
|
if (!$user) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $user->verifyPassword($password) ? $user : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class ClientCapabilities implements Arrayable
|
|||||||
private bool $passkey = false;
|
private bool $passkey = false;
|
||||||
private array $socials = [];
|
private array $socials = [];
|
||||||
|
|
||||||
private array $theme = [
|
private array $branding = [
|
||||||
'primaryColor' => '#000000',
|
'primaryColor' => '#000000',
|
||||||
'secondaryColor' => '#FFFFFF',
|
'secondaryColor' => '#FFFFFF',
|
||||||
'logoUrl' => null,
|
'logoUrl' => null,
|
||||||
@@ -37,8 +37,8 @@ class ClientCapabilities implements Arrayable
|
|||||||
$this->socials = $capabilities['socials'];
|
$this->socials = $capabilities['socials'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($capabilities['theme']) && is_array($capabilities['theme'])) {
|
if (isset($capabilities['branding']) && is_array($capabilities['branding'])) {
|
||||||
$this->theme = array_merge($this->theme, $capabilities['theme']);
|
$this->branding = array_merge($this->branding, $capabilities['branding']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ class ClientCapabilities implements Arrayable
|
|||||||
'magicLink' => $this->magicLink,
|
'magicLink' => $this->magicLink,
|
||||||
'passkey' => $this->passkey,
|
'passkey' => $this->passkey,
|
||||||
'socials' => $this->socials,
|
'socials' => $this->socials,
|
||||||
'theme' => $this->theme,
|
'branding' => $this->branding,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,28 +8,24 @@ use Carbon\Carbon;
|
|||||||
use DateTimeImmutable;
|
use DateTimeImmutable;
|
||||||
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
use League\OAuth2\Server\Entities\Traits\EntityTrait;
|
||||||
use Psr\SimpleCache\InvalidArgumentException;
|
use Psr\SimpleCache\InvalidArgumentException;
|
||||||
|
use Siteworxpro\App\Services\Facades\Encryption;
|
||||||
use Siteworxpro\App\Services\Facades\Redis;
|
use Siteworxpro\App\Services\Facades\Redis;
|
||||||
|
|
||||||
abstract class RedisModel
|
abstract class RedisModel
|
||||||
{
|
{
|
||||||
use EntityTrait;
|
use EntityTrait;
|
||||||
|
|
||||||
private \Predis\Client $redis;
|
protected ?Carbon $expiryDateTime;
|
||||||
|
|
||||||
protected ?DateTimeImmutable $expireTime;
|
|
||||||
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->redis = Redis::getFacadeRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract protected static function getRedisPrefix(): string;
|
abstract protected static function getRedisPrefix(): string;
|
||||||
|
|
||||||
public static function find(string $identifier): ?self
|
public static function find(string $identifier): ?static
|
||||||
{
|
{
|
||||||
$instance = Redis::get(static::getRedisPrefix() . ':' . $identifier);
|
$instance = Redis::get(static::getRedisPrefix() . ':' . $identifier);
|
||||||
|
|
||||||
if ($instance !== null) {
|
if ($instance !== null) {
|
||||||
|
$instance = Encryption::decrypt($instance);
|
||||||
|
|
||||||
return unserialize($instance);
|
return unserialize($instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,22 +35,20 @@ abstract class RedisModel
|
|||||||
public function save(): void
|
public function save(): void
|
||||||
{
|
{
|
||||||
$diff = 0;
|
$diff = 0;
|
||||||
if ($this->expireTime) {
|
if ($this->expiryDateTime) {
|
||||||
$diff = $this->expireTime->getTimestamp() - Carbon::now()->timestamp;
|
$diff = $this->expiryDateTime->getTimestamp() - Carbon::now()->timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->redis->set(
|
Redis::set(
|
||||||
static::getRedisPrefix() . ':' . $this->getIdentifier(),
|
static::getRedisPrefix() . ':' . $this->getIdentifier(),
|
||||||
serialize($this),
|
Encryption::encrypt(serialize($this)),
|
||||||
|
'EX',
|
||||||
$diff
|
$diff
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws InvalidArgumentException
|
|
||||||
*/
|
|
||||||
public function delete(): void
|
public function delete(): void
|
||||||
{
|
{
|
||||||
$this->redis->delete(static::getRedisPrefix() . ':' . $this->getIdentifier());
|
Redis::del(static::getRedisPrefix() . ':' . $this->getIdentifier());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,15 +4,37 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Siteworxpro\App\OAuth\Entities;
|
namespace Siteworxpro\App\OAuth\Entities;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use League\OAuth2\Server\Entities\AccessTokenEntityInterface;
|
||||||
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
||||||
use League\OAuth2\Server\Entities\Traits\RefreshTokenTrait;
|
|
||||||
|
|
||||||
class RefreshToken extends RedisModel implements RefreshTokenEntityInterface
|
class RefreshToken extends RedisModel implements RefreshTokenEntityInterface
|
||||||
{
|
{
|
||||||
use RefreshTokenTrait;
|
private AccessToken | null $accessToken = null;
|
||||||
|
|
||||||
protected static function getRedisPrefix(): string
|
protected static function getRedisPrefix(): string
|
||||||
{
|
{
|
||||||
return 'oauth_refresh_token';
|
return 'oauth_refresh_token';
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public function getExpiryDateTime(): DateTimeImmutable
|
||||||
|
{
|
||||||
|
return $this->expiryDateTime->toDateTimeImmutable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setExpiryDateTime(DateTimeImmutable $dateTime): void
|
||||||
|
{
|
||||||
|
$this->expiryDateTime = Carbon::instance($dateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAccessToken(AccessTokenEntityInterface $accessToken): void
|
||||||
|
{
|
||||||
|
$this->accessToken = $accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAccessToken(): AccessTokenEntityInterface
|
||||||
|
{
|
||||||
|
return $this->accessToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,27 +6,33 @@ namespace Siteworxpro\App\OAuth;
|
|||||||
|
|
||||||
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
use League\OAuth2\Server\Entities\RefreshTokenEntityInterface;
|
||||||
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
use League\OAuth2\Server\Repositories\RefreshTokenRepositoryInterface;
|
||||||
|
use Psr\SimpleCache\InvalidArgumentException;
|
||||||
|
use Siteworxpro\App\OAuth\Entities\RefreshToken;
|
||||||
|
|
||||||
class RefreshTokenRepository implements RefreshTokenRepositoryInterface
|
class RefreshTokenRepository implements RefreshTokenRepositoryInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
public function getNewRefreshToken(): ?RefreshTokenEntityInterface
|
public function getNewRefreshToken(): ?RefreshTokenEntityInterface
|
||||||
{
|
{
|
||||||
// TODO: Implement getNewRefreshToken() method.
|
return new RefreshToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function persistNewRefreshToken(RefreshTokenEntityInterface $refreshTokenEntity): void
|
public function persistNewRefreshToken(RefreshTokenEntityInterface | RefreshToken $refreshTokenEntity): void
|
||||||
{
|
{
|
||||||
// TODO: Implement persistNewRefreshToken() method.
|
$refreshTokenEntity->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
public function revokeRefreshToken(string $tokenId): void
|
public function revokeRefreshToken(string $tokenId): void
|
||||||
{
|
{
|
||||||
// TODO: Implement revokeRefreshToken() method.
|
$token = RefreshToken::find($tokenId);
|
||||||
|
$token?->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isRefreshTokenRevoked(string $tokenId): bool
|
public function isRefreshTokenRevoked(string $tokenId): bool
|
||||||
{
|
{
|
||||||
// TODO: Implement isRefreshTokenRevoked() method.
|
$token = RefreshToken::find($tokenId);
|
||||||
|
return $token === null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/Services/Facades/Encryption.php
Normal file
19
src/Services/Facades/Encryption.php
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Siteworxpro\App\Services\Facades;
|
||||||
|
|
||||||
|
use Siteworxpro\App\Services\Facade;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method static string encrypt(string $data)
|
||||||
|
* @method static string decrypt(string $data)
|
||||||
|
*/
|
||||||
|
class Encryption extends Facade
|
||||||
|
{
|
||||||
|
protected static function getFacadeAccessor(): string
|
||||||
|
{
|
||||||
|
return \Siteworxpro\App\Helpers\Encryption::class;
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/Services/ServiceProviders/EncryptionServiceProvider.php
Normal file
33
src/Services/ServiceProviders/EncryptionServiceProvider.php
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Siteworxpro\App\Services\ServiceProviders;
|
||||||
|
|
||||||
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Siteworxpro\App\Helpers\Encryption;
|
||||||
|
use Siteworxpro\App\Services\Facades\Config;
|
||||||
|
|
||||||
|
class EncryptionServiceProvider extends ServiceProvider
|
||||||
|
{
|
||||||
|
public function provides(): array
|
||||||
|
{
|
||||||
|
return [Encryption::class];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function register(): void
|
||||||
|
{
|
||||||
|
$this->app->singleton(Encryption::class, function () {
|
||||||
|
$key = Config::get('app.encryption_key');
|
||||||
|
if (empty($key)) {
|
||||||
|
throw new \RuntimeException('Encryption key is not set in configuration.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str_contains($key, 'base64:')) {
|
||||||
|
$key = base64_decode(substr($key, 7));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Encryption($key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user