Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions app/Extensions/OAuth/Schemas/GenericOidcSchema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace App\Extensions\OAuth\Schemas;

use Filament\Forms\Components\ColorPicker;
use Filament\Forms\Components\TextInput;
use Filament\Infolists\Components\TextEntry;
use Filament\Schemas\Components\Wizard\Step;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
use Kovah\LaravelSocialiteOidc\OidcProvider;

final class GenericOidcSchema extends OAuthSchema
{
public function getId(): string
{
return 'oidc';
}

public function getSocialiteProvider(): string
{
return OidcProvider::class;

Check failure on line 22 in app/Extensions/OAuth/Schemas/GenericOidcSchema.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.4)

Class Kovah\LaravelSocialiteOidc\OidcProvider not found.
}

public function getServiceConfig(): array
{
$config = array_merge(parent::getServiceConfig(), [
'base_url' => env('OAUTH_OIDC_BASE_URL'),
]);

$realm = env('OAUTH_OIDC_REALM');
if ($realm) {
$config['realm'] = $realm;
}

return $config;
}

public function getSetupSteps(): array
{
return array_merge([
Step::make('Configure OIDC Provider')
->schema([
TextEntry::make('setup_instructions')
->hiddenLabel()
->state(new HtmlString(Blade::render('<p>Configure your OIDC provider (e.g., Keycloak, Auth0, Okta) with the following settings:</p><ul><li>Create an OAuth2/OpenID Connect application</li><li>Set the <b>Redirect URI</b> to the value below</li><li>Copy the <b>Client ID</b> and <b>Client Secret</b> for use in the configuration step</li></ul>'))),
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The setup instructions HTML string is too long and hard to maintain inline. Consider extracting this to a Blade component or view file for better readability and maintainability.

Copilot uses AI. Check for mistakes.
TextInput::make('_noenv_callback')
->label('Callback URL')
->dehydrated()
->disabled()
->hintCopy()
->default(fn () => url('/auth/oauth/callback/oidc')),
Comment on lines +47 to +52
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use dehydrated(false) for display-only callback URL field.

The _noenv_callback field is disabled and used only for display purposes. Using ->dehydrated() (which defaults to true) means it may still be included in form submissions. For a read-only display field, use ->dehydrated(false) to prevent it from being processed.

                     TextInput::make('_noenv_callback')
                         ->label('Callback URL')
-                        ->dehydrated()
+                        ->dehydrated(false)
                         ->disabled()
                         ->hintCopy()
                         ->default(fn () => url('/auth/oauth/callback/oidc')),
🤖 Prompt for AI Agents
In app/Extensions/OAuth/Schemas/GenericOidcSchema.php around lines 47 to 52, the
TextInput for '_noenv_callback' is currently using ->dehydrated() which leaves
it included in form submissions; change this to ->dehydrated(false) so the
disabled/read-only callback URL is not dehydrated or processed on submit,
keeping the field display-only.

TextEntry::make('keycloak_note')
->hiddenLabel()
->state(new HtmlString('<p><b>For Keycloak:</b> The Base URL should point to your realm (e.g., <code>https://keycloak.example.com/realms/my-realm</code>). Optionally, you can specify the realm name separately.</p>')),
]),
], parent::getSetupSteps());
}

Comment on lines +55 to +59
Copy link

Copilot AI Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Keycloak note HTML string is also quite long. Consider extracting this to a separate view or using a more structured approach with Blade components for better maintainability.

Suggested change
->state(new HtmlString('<p><b>For Keycloak:</b> The Base URL should point to your realm (e.g., <code>https://keycloak.example.com/realms/my-realm</code>). Optionally, you can specify the realm name separately.</p>')),
]),
], parent::getSetupSteps());
}
->state($this->getKeycloakNoteHtml()),
]),
], parent::getSetupSteps());
}
private function getKeycloakNoteHtml(): HtmlString
{
return new HtmlString(<<<'HTML'
<p><b>For Keycloak:</b> The Base URL should point to your realm (e.g., <code>https://keycloak.example.com/realms/my-realm</code>). Optionally, you can specify the realm name separately.</p>
HTML
);
}

Copilot uses AI. Check for mistakes.
public function getSettingsForm(): array
{
return array_merge(parent::getSettingsForm(), [
TextInput::make('OAUTH_OIDC_BASE_URL')
->label('Base URL')
->placeholder('https://your-oidc-provider.com')
->columnSpan(2)
->required()
->url()
->autocomplete(false)
->helperText('The base URL of your OIDC provider. For Keycloak, include the realm path (e.g., https://keycloak.example.com/realms/my-realm)')
->default(env('OAUTH_OIDC_BASE_URL')),
TextInput::make('OAUTH_OIDC_REALM')
->label('Realm')
->placeholder('Realm (optional, for Keycloak)')
->columnSpan(2)
->autocomplete(false)
->helperText('Optional: Specify the realm name if not included in the Base URL')
->default(env('OAUTH_OIDC_REALM')),
TextInput::make('OAUTH_OIDC_DISPLAY_NAME')
->label('Display Name')
->placeholder('OIDC')
->columnSpan(2)
->autocomplete(false)
->default(env('OAUTH_OIDC_DISPLAY_NAME', 'OIDC')),
ColorPicker::make('OAUTH_OIDC_DISPLAY_COLOR')
->label('Display Color')
->placeholder('#0066cc')
->default(env('OAUTH_OIDC_DISPLAY_COLOR', '#0066cc'))
->hex(),
]);
}

public function getName(): string
{
return env('OAUTH_OIDC_DISPLAY_NAME', 'OIDC');
}

public function getHexColor(): string
{
return env('OAUTH_OIDC_DISPLAY_COLOR', '#0066cc');
}

public function getIcon(): string
{
return 'tabler-key';
}
}
4 changes: 4 additions & 0 deletions app/Providers/Extensions/OAuthServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Extensions\OAuth\Schemas\BitbucketSchema;
use App\Extensions\OAuth\Schemas\DiscordSchema;
use App\Extensions\OAuth\Schemas\FacebookSchema;
use App\Extensions\OAuth\Schemas\GenericOidcSchema;
use App\Extensions\OAuth\Schemas\GithubSchema;
use App\Extensions\OAuth\Schemas\GitlabSchema;
use App\Extensions\OAuth\Schemas\GoogleSchema;
Expand Down Expand Up @@ -38,6 +39,9 @@ public function register(): void
$service->register(new DiscordSchema());
$service->register(new SteamSchema());

// Generic OIDC provider
$service->register(new GenericOidcSchema());

return $service;
});
}
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"socialiteproviders/authentik": "^5.2",
"socialiteproviders/discord": "^4.2",
"socialiteproviders/steam": "^4.3",
"kovah/laravel-socialite-oidc": "^0.5",
"spatie/laravel-data": "^4.17",
"spatie/laravel-fractal": "^6.3",
"spatie/laravel-health": "^1.34",
Expand Down
Loading
Loading