You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
92 lines
2.6 KiB
92 lines
2.6 KiB
<?php |
|
|
|
namespace App\Services; |
|
|
|
use App\Support\ApiActor; |
|
use Illuminate\Http\Request; |
|
use Laravel\Passport\Client; |
|
use League\OAuth2\Server\Exception\OAuthServerException; |
|
use League\OAuth2\Server\ResourceServer; |
|
use Symfony\Bridge\PsrHttpMessage\Factory\PsrHttpFactory; |
|
|
|
class ApiAuthService |
|
{ |
|
public function __construct( |
|
private readonly ApiTokenService $apiTokens, |
|
private readonly LdapJwtService $ldapJwt, |
|
private readonly ResourceServer $resourceServer, |
|
private readonly PermissionService $permissions, |
|
) { |
|
} |
|
|
|
public function authenticate(Request $request): ?ApiActor |
|
{ |
|
$bearer = $request->bearerToken(); |
|
|
|
if ($bearer === null || $bearer === '') { |
|
return null; |
|
} |
|
|
|
if (str_starts_with($bearer, config('api.token_prefix'))) { |
|
return $this->fromApiToken($bearer); |
|
} |
|
|
|
if ($ldap = $this->fromLdapJwt($bearer)) { |
|
return $ldap; |
|
} |
|
|
|
return $this->fromPassportToken($request); |
|
} |
|
|
|
private function fromApiToken(string $plain): ?ApiActor |
|
{ |
|
$record = $this->apiTokens->findByPlainText($plain); |
|
|
|
if ($record === null) { |
|
return null; |
|
} |
|
|
|
$scopes = $record->scopes ?? []; |
|
$isAdmin = in_array('admin', $scopes, true); |
|
|
|
return new ApiActor('api_token', $record->name, $scopes, $isAdmin); |
|
} |
|
|
|
private function fromLdapJwt(string $jwt): ?ApiActor |
|
{ |
|
$payload = $this->ldapJwt->validate($jwt); |
|
|
|
if ($payload === null || $payload['username'] === '') { |
|
return null; |
|
} |
|
|
|
$groups = $payload['groups'] ?? []; |
|
$resolvedPermissions = $this->permissions->permissionsForGroups($groups); |
|
|
|
return new ApiActor( |
|
'ldap_jwt', |
|
$payload['username'], |
|
$payload['scopes'], |
|
$payload['is_admin'], |
|
$groups, |
|
$resolvedPermissions, |
|
); |
|
} |
|
|
|
private function fromPassportToken(Request $request): ?ApiActor |
|
{ |
|
try { |
|
$psr = (new PsrHttpFactory)->createRequest($request); |
|
$validated = $this->resourceServer->validateAuthenticatedRequest($psr); |
|
$clientId = (string) $validated->getAttribute('oauth_client_id'); |
|
$scopes = array_filter(explode(' ', (string) $validated->getAttribute('oauth_scopes', ''))); |
|
|
|
$client = Client::find($clientId); |
|
$name = $client?->name ?? $clientId; |
|
|
|
return new ApiActor('oauth_client', $name, array_values($scopes), in_array('admin', $scopes, true)); |
|
} catch (OAuthServerException) { |
|
return null; |
|
} |
|
} |
|
}
|
|
|