- Introduced a detailed view for OIDC apps (`show` page) with client credentials and sign-out URI management. - Added functionality to toggle app status, generate new client secrets, and display OAuth scopes. - Implemented service methods for handling OIDC app data, including `getPassportClient`, `generateNewSecret`, and `toggleStatus`. - Enhanced feature tests for role-based access and validation of client secret generation.
109 lines
3.6 KiB
PHP
109 lines
3.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services\Applications\OIDC;
|
|
|
|
use App\Data\Application\{CreatedApplicationData, StoreOIDCAppData};
|
|
use App\Data\ConnectedApp\ConnectAppRequest;
|
|
use App\Enums\{ConnectionProtocolEnum, ConnectionStatusEnum};
|
|
use App\Models\{ConnectedApp, ConnectionProtocol, ConnectionStatus};
|
|
use App\Services\{ApplicationLogoUploader, ConnectedAppService};
|
|
use App\Services\Applications\OIDC\Factory\ClientCreationFactory;
|
|
use Illuminate\Support\Facades\{DB, Log};
|
|
use Illuminate\Support\Str;
|
|
use Laravel\Passport\Client;
|
|
use Throwable;
|
|
|
|
readonly class OidcService
|
|
{
|
|
public function __construct(
|
|
private ClientCreationFactory $clientCreationFactory,
|
|
private ApplicationLogoUploader $logoUploader,
|
|
private ConnectedAppService $connectedAppService,
|
|
) {}
|
|
|
|
/**
|
|
* @throws Throwable
|
|
*/
|
|
public function createApp(StoreOIDCAppData $data): CreatedApplicationData
|
|
{
|
|
Log::info('Creating OIDC app', [
|
|
'name' => $data->name,
|
|
'type' => $data->type,
|
|
]);
|
|
try {
|
|
DB::beginTransaction();
|
|
$logo = $this->logoUploader->store($data->logo);
|
|
$appData = $this->connectedAppService->create(
|
|
new ConnectAppRequest(
|
|
name: $data->name,
|
|
connectionProtocolId: ConnectionProtocol::query()->where('name', ConnectionProtocolEnum::OIDC->value)->first()->id,
|
|
connectionProviderId: 0,
|
|
slug: Str::slug($data->name),
|
|
connectionStatusId: ConnectionStatus::query()->where('name', ConnectionStatusEnum::Connected->value)->first()->id,
|
|
settings: [
|
|
'access_url' => $data->accessUrl,
|
|
'sign_out_uris' => $data->signOutUris,
|
|
],
|
|
logo: $logo,
|
|
)
|
|
);
|
|
|
|
$clientData = $this->clientCreationFactory->for($data->type)->create($data);
|
|
DB::commit();
|
|
|
|
// remove sensitive data
|
|
$appData->settings = null;
|
|
|
|
Log::info('OIDC app created', [
|
|
'name' => $data->name,
|
|
'type' => $data->type,
|
|
'clientId' => isset($clientData->clientId),
|
|
'clientSecret' => isset($clientData->clientSecret),
|
|
]);
|
|
|
|
return new CreatedApplicationData(
|
|
application: $appData,
|
|
clientCredentials: $clientData,
|
|
);
|
|
} catch (Throwable $e) {
|
|
DB::rollBack();
|
|
Log::error('Failed to create OIDC app', [
|
|
'name' => $data->name,
|
|
'type' => $data->type,
|
|
]);
|
|
throw $e;
|
|
}
|
|
}
|
|
|
|
public function getPassportClient(ConnectedApp $app): ?Client
|
|
{
|
|
return Client::where('name', $app->name)->first();
|
|
}
|
|
|
|
public function generateNewSecret(Client $client): string
|
|
{
|
|
$plainSecret = Str::random(40);
|
|
$client->forceFill(['secret' => bcrypt($plainSecret)])->save();
|
|
|
|
return $plainSecret;
|
|
}
|
|
|
|
public function toggleStatus(ConnectedApp $app): void
|
|
{
|
|
$statusEnum = $app->status->name === ConnectionStatusEnum::Connected->value
|
|
? ConnectionStatusEnum::Disconnected
|
|
: ConnectionStatusEnum::Connected;
|
|
|
|
$newStatus = ConnectionStatus::where('name', $statusEnum->value)->firstOrFail();
|
|
$app->connection_status_id = $newStatus->id;
|
|
$app->save();
|
|
}
|
|
|
|
public function getSignOutUris(ConnectedApp $app): array
|
|
{
|
|
return data_get($app, 'settings.sign_out_uris', []);
|
|
}
|
|
}
|