<?php
namespace App\OAuth2; use App\OAuth2\Repository\AccessTokenRepository; use App\OAuth2\Repository\AuthCodeRepository; use App\OAuth2\Repository\ClientRepository; use App\OAuth2\Repository\RefreshTokenRepository; use App\OAuth2\Repository\ScopeRepository; use DateInterval; use League\OAuth2\Server\AuthorizationServer; use League\OAuth2\Server\CryptKey; use League\OAuth2\Server\Grant\AuthCodeGrant; use League\OAuth2\Server\Grant\RefreshTokenGrant; use League\OAuth2\Server\ResourceServer; class Server { private static ?Server $instance = null; private ?AuthorizationServer $authorizationServer = null; private ?ResourceServer $resourceServer = null; public static function getInstance(): self { if (self::$instance === null) { self::$instance = new self(); } return self::$instance; } public function getAuthorizationServer(): AuthorizationServer { if ($this->authorizationServer !== null) { return $this->authorizationServer; } $CFG = \Engine\Loader_Cfg::getInstance()->getGlobal(); $privateKey = new CryptKey( $CFG['oauth2']['privateKeyPath'], $CFG['oauth2']['privateKeyPassphrase'] ?? null, $this->keyPermissionsCheckEnabled() ); $server = new AuthorizationServer( new ClientRepository(), new AccessTokenRepository(), new ScopeRepository(), $privateKey, $this->getEncryptionKey() ); $server->setDefaultScope((string)($CFG['oauth2']['defaultScope'] ?? '')); $accessTokenTTL = new DateInterval($CFG['oauth2']['ttl']['accessToken']); $refreshTokenTTL = new DateInterval($CFG['oauth2']['ttl']['refreshToken']); $authCodeGrant = new AuthCodeGrant( new AuthCodeRepository(), new RefreshTokenRepository(), new DateInterval($CFG['oauth2']['ttl']['authCode']) ); $authCodeGrant->setRefreshTokenTTL($refreshTokenTTL); $server->enableGrantType($authCodeGrant, $accessTokenTTL); $refreshGrant = new RefreshTokenGrant(new RefreshTokenRepository()); $refreshGrant->setRefreshTokenTTL($refreshTokenTTL); $server->enableGrantType($refreshGrant, $accessTokenTTL); $this->authorizationServer = $server; return $this->authorizationServer; } public function getResourceServer(): ResourceServer { if ($this->resourceServer !== null) { return $this->resourceServer; } $CFG = \Engine\Loader_Cfg::getInstance()->getGlobal(); $publicKey = new CryptKey( $CFG['oauth2']['publicKeyPath'], null, $this->keyPermissionsCheckEnabled() ); $this->resourceServer = new ResourceServer( new AccessTokenRepository(), $publicKey ); return $this->resourceServer; } private function keyPermissionsCheckEnabled(): bool { $CFG = \Engine\Loader_Cfg::getInstance()->getGlobal(); return ($CFG['global']['application']['applicationType'] ?? '') === 'production'; } private function getEncryptionKey(): string { $stored = \App\OAuth2\Config::getInstance()->get('encryptionKey'); if (!$stored) { throw new \Exception( "OAuth2 server encryption key is not configured. Generate one and store it via " . "\\App\\OAuth2\\Config (encrypted). See _config/application/oauth2.cfg.php." ); } return \App\OAuth2\Config::getInstance()->decryptStr($stored); } }