You've already forked php-auth
generated from siteworxpro/Php-Template
Some checks failed
🧪✨ Tests Workflow / 🛡️ 🔒 License Check (push) Successful in 2m23s
🧪✨ Tests Workflow / 🛡️ 🔒 Library Audit (push) Successful in 2m35s
🧪✨ Tests Workflow / 📝 ✨ Code Lint (push) Successful in 2m25s
🧪✨ Tests Workflow / 🧪 ✨ Database Migrations (push) Successful in 2m39s
🧪✨ Tests Workflow / 🐙 🔍 Code Sniffer (push) Failing after 2m26s
🧪✨ Tests Workflow / 🧪 ✅ Unit Tests (push) Failing after 1m5s
236 lines
6.4 KiB
PHP
236 lines
6.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Siteworxpro\App\OAuth\Entities;
|
|
|
|
use Defuse\Crypto\Exception\BadFormatException;
|
|
use Defuse\Crypto\Exception\EnvironmentIsBrokenException;
|
|
use Defuse\Crypto\Key;
|
|
use Illuminate\Database\Eloquent\Collection;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
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 Random\RandomException;
|
|
use Siteworxpro\App\Helpers\Rand;
|
|
use Siteworxpro\App\Models\ClientRedirectUri;
|
|
use Siteworxpro\App\Models\ClientScope;
|
|
use Siteworxpro\App\Models\ClientUser;
|
|
use Siteworxpro\App\Models\Model;
|
|
use Siteworxpro\App\Models\User;
|
|
use Siteworxpro\App\OAuth\AccessTokenRepository;
|
|
use Siteworxpro\App\OAuth\ClientRepository;
|
|
use Siteworxpro\App\OAuth\ScopeRepository;
|
|
|
|
/**
|
|
* Class Client
|
|
* @package Siteworxpro\App\Models
|
|
*
|
|
* @property string $id
|
|
* @property string $client_id
|
|
* @property string $client_secret
|
|
* @property string $name
|
|
* @property string $description
|
|
* @property string $private_key
|
|
* @property string $encryption_key
|
|
* @property Collection $grant_types
|
|
* @property bool $confidential
|
|
*
|
|
* @property ClientCapabilities $capabilities
|
|
* @property-read Collection<ClientRedirectUri> $clientRedirectUris
|
|
* @property-read Scope[]|Collection $scopes
|
|
*/
|
|
class Client extends Model implements ClientEntityInterface
|
|
{
|
|
use EntityTrait;
|
|
|
|
protected $casts = [
|
|
'id' => 'string',
|
|
'grant_types' => 'collection',
|
|
'confidential' => 'boolean',
|
|
];
|
|
|
|
/**
|
|
* @throws RandomException|EnvironmentIsBrokenException
|
|
*/
|
|
public function __construct(array $attributes = [])
|
|
{
|
|
parent::__construct($attributes);
|
|
|
|
$this->client_id = Rand::string(32);
|
|
$this->client_secret = Rand::string(64);
|
|
$this->generatePrivateKey();
|
|
}
|
|
|
|
public static function byClientId(string $clientId): ?Client
|
|
{
|
|
/** @var Client|null $client */
|
|
$client = self::where('client_id', $clientId)->first();
|
|
|
|
return $client;
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
* @throws EnvironmentIsBrokenException
|
|
*/
|
|
private function generatePrivateKey(): void
|
|
{
|
|
// generate rsa private and public key pair
|
|
$config = [
|
|
"digest_alg" => "sha256",
|
|
"private_key_bits" => 4096,
|
|
"private_key_type" => OPENSSL_KEYTYPE_RSA,
|
|
];
|
|
|
|
$res = openssl_pkey_new($config);
|
|
openssl_pkey_export($res, $privateKey);
|
|
$this->private_key = $privateKey;
|
|
$this->encryption_key = Key::createNewRandomKey()->saveToAsciiSafeString();
|
|
}
|
|
|
|
/**
|
|
* @return HasMany
|
|
*/
|
|
public function clientRedirectUris(): HasMany
|
|
{
|
|
return $this->hasMany(ClientRedirectUri::class);
|
|
}
|
|
|
|
/**
|
|
* @return HasManyThrough
|
|
*/
|
|
public function scopes(): HasManyThrough
|
|
{
|
|
return $this->hasManyThrough(
|
|
Scope::class,
|
|
ClientScope::class,
|
|
'client_id',
|
|
'id',
|
|
'id',
|
|
'scope_id'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return HasManyThrough
|
|
*/
|
|
public function users(): HasManyThrough
|
|
{
|
|
return $this->hasManyThrough(
|
|
User::class,
|
|
ClientUser::class,
|
|
'client_id',
|
|
'id',
|
|
'id',
|
|
'user_id'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getIdentifier(): string
|
|
{
|
|
return $this->id;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getName(): string
|
|
{
|
|
return $this->name;
|
|
}
|
|
|
|
/**
|
|
* @return string|array
|
|
*/
|
|
public function getRedirectUri(): string|array
|
|
{
|
|
return $this->clientRedirectUris->pluck('redirect_uri')->toArray();
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
*/
|
|
public function isConfidential(): bool
|
|
{
|
|
return $this->confidential;
|
|
}
|
|
|
|
public function getCapabilitiesAttribute(string $capabilities): ClientCapabilities
|
|
{
|
|
return ClientCapabilities::fromJson($capabilities);
|
|
}
|
|
|
|
/**
|
|
* @throws \JsonException
|
|
*/
|
|
public function setCapabilitiesAttribute(ClientCapabilities $capabilities): void
|
|
{
|
|
$this->attributes['capabilities'] = $capabilities->toJson();
|
|
}
|
|
|
|
/**
|
|
* @throws BadFormatException
|
|
* @throws EnvironmentIsBrokenException
|
|
* @throws \Exception
|
|
*/
|
|
public function getAuthorizationServer(): AuthorizationServer
|
|
{
|
|
|
|
$authorizationServer = new AuthorizationServer(
|
|
new ClientRepository($this),
|
|
new AccessTokenRepository(),
|
|
new ScopeRepository(),
|
|
$this->private_key,
|
|
Key::loadFromAsciiSafeString($this->encryption_key)
|
|
);
|
|
|
|
if (!empty($this->grant_types)) {
|
|
foreach ($this->grant_types as $grantType) {
|
|
switch ($grantType) {
|
|
case 'authorization_code':
|
|
$grant = new \League\OAuth2\Server\Grant\AuthCodeGrant(
|
|
new \Siteworxpro\App\OAuth\AuthCodeRepository(),
|
|
new \Siteworxpro\App\OAuth\RefreshTokenRepository(),
|
|
new \DateInterval('PT10M')
|
|
);
|
|
$grant->setRefreshTokenTTL(new \DateInterval('P1M'));
|
|
break;
|
|
case 'client_credentials':
|
|
$grant = new \League\OAuth2\Server\Grant\ClientCredentialsGrant();
|
|
break;
|
|
case 'refresh_token':
|
|
$grant = new \League\OAuth2\Server\Grant\RefreshTokenGrant(
|
|
new \Siteworxpro\App\OAuth\RefreshTokenRepository()
|
|
);
|
|
$grant->setRefreshTokenTTL(new \DateInterval('P1M'));
|
|
break;
|
|
default:
|
|
continue 2;
|
|
}
|
|
|
|
$authorizationServer->enableGrantType($grant);
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|