diff --git a/app/Extensions/OAuth/Providers/AuthentikProvider.php b/app/Extensions/OAuth/Providers/AuthentikProvider.php new file mode 100644 index 000000000..a7b178172 --- /dev/null +++ b/app/Extensions/OAuth/Providers/AuthentikProvider.php @@ -0,0 +1,65 @@ + null, + 'client_secret' => env('OAUTH_STEAM_CLIENT_SECRET'), + 'allowed_hosts' => [ + str_replace(['http://', 'https://'], '', env('APP_URL')), + ], + ]; + } + + public function getSettingsForm(): array + { + return array_merge(parent::getSettingsForm(), [ + TextInput::make('OAUTH_AUTHENTIK_BASE_URL') + ->label('Base URL') + ->placeholder('Base URL') + ->columnSpan(2) + ->required() + ->url() + ->autocomplete(false) + ->default(env('OAUTH_AUTHENTIK_BASE_URL')), + TextInput::make('OAUTH_AUTHENTIK_DISPLAY_NAME') + ->label('Display Name') + ->placeholder('Display Name') + ->columnSpan(2) + ->autocomplete(false) + ->default(env('OAUTH_AUTHENTIK_DISPLAY_NAME', 'Authentik')), + ]); + } + + public function getName(): string + { + return env('OAUTH_AUTHENTIK_DISPLAY_NAME') ?? 'Authentik'; + } + + public function getHexColor(): string + { + return '#fd4b2d'; + } + + public static function register(): self + { + return new self(); + } +} diff --git a/app/Extensions/OAuth/Providers/CommonProvider.php b/app/Extensions/OAuth/Providers/CommonProvider.php new file mode 100644 index 000000000..9526ddf49 --- /dev/null +++ b/app/Extensions/OAuth/Providers/CommonProvider.php @@ -0,0 +1,36 @@ +id; + } + + public function getProviderClass(): ?string + { + return $this->providerClass; + } + + public function getIcon(): ?string + { + return $this->icon; + } + + public function getHexColor(): ?string + { + return $this->hexColor; + } + + public static function register(string $id, ?string $providerClass = null, ?string $icon = null, ?string $hexColor = null): static + { + return new self($id, $providerClass, $icon, $hexColor); + } +} diff --git a/app/Extensions/OAuth/Providers/DiscordProvider.php b/app/Extensions/OAuth/Providers/DiscordProvider.php new file mode 100644 index 000000000..ae83e61e7 --- /dev/null +++ b/app/Extensions/OAuth/Providers/DiscordProvider.php @@ -0,0 +1,57 @@ +schema([ + Placeholder::make('') + ->content(new HtmlString('
Visit the Discord Developer Portal and click on New Application. Enter a Name (e.g. your panel name) and click on Create.
Copy the Client ID and the Client Secret, you will need them in the final step.
')), + Placeholder::make('') + ->content(new HtmlString('Under Redirects add the below URL.
')), + TextInput::make('_noenv_redirect') + ->label('Redirect URL') + ->disabled() + ->hintAction(CopyAction::make()) + ->formatStateUsing(fn () => config('app.url') . (Str::endsWith(config('app.url'), '/') ? '' : '/') . 'auth/oauth/callback/discord'), + ]), + ], parent::getSetupSteps()); + } + + public function getIcon(): string + { + return 'tabler-brand-discord-f'; + } + + public function getHexColor(): string + { + return '#5865F2'; + } + + public static function register(): self + { + return new self(); + } +} diff --git a/app/Extensions/OAuth/Providers/GithubProvider.php b/app/Extensions/OAuth/Providers/GithubProvider.php new file mode 100644 index 000000000..81a9606af --- /dev/null +++ b/app/Extensions/OAuth/Providers/GithubProvider.php @@ -0,0 +1,56 @@ +schema([ + Placeholder::make('') + ->content(new HtmlString('Visit the Github Developer Dashboard, go to OAuth Apps and click on New OAuth App.
Enter an Application name (e.g. your panel name), set Homepage URL to your panel url and enter the below url as Authorization callback URL.
')), + TextInput::make('_noenv_callback') + ->label('Authorization callback URL') + ->disabled() + ->hintAction(CopyAction::make()) + ->default(fn () => config('app.url') . (Str::endsWith(config('app.url'), '/') ? '' : '/') . 'auth/oauth/callback/github'), + Placeholder::make('') + ->content(new HtmlString('When you filled all fields click on Register application.
')), + ]), + Step::make('Create Client Secret') + ->schema([ + Placeholder::make('') + ->content(new HtmlString('Once you registered your app, generate a new Client Secret.
You will also need the Client ID.
')), + ]), + ], parent::getSetupSteps()); + } + + public function getIcon(): string + { + return 'tabler-brand-github-f'; + } + + public function getHexColor(): string + { + return '#4078c0'; + } + + public static function register(): self + { + return new self(); + } +} diff --git a/app/Extensions/OAuth/Providers/OAuthProvider.php b/app/Extensions/OAuth/Providers/OAuthProvider.php new file mode 100644 index 000000000..a068df639 --- /dev/null +++ b/app/Extensions/OAuth/Providers/OAuthProvider.php @@ -0,0 +1,112 @@ +getId(), static::$providers)) { + logger()->warning("Tried to create duplicate OAuth provider with id '{$this->getId()}'"); + + return; + } + + config()->set('services.' . $this->getId(), array_merge($this->getServiceConfig(), ['redirect' => '/auth/oauth/callback/' . $this->getId()])); + + if ($this->getProviderClass()) { + Event::listen(function (SocialiteWasCalled $event) { + $event->extendSocialite($this->getId(), $this->getProviderClass()); + }); + } + + static::$providers[$this->getId()] = $this; + } + + abstract public function getId(): string; + + public function getProviderClass(): ?string + { + return null; + } + + public function getServiceConfig(): array + { + $id = Str::upper($this->getId()); + + return [ + 'client_id' => env("OAUTH_{$id}_CLIENT_ID"), + 'client_secret' => env("OAUTH_{$id}_CLIENT_SECRET"), + ]; + } + + public function getSettingsForm(): array + { + $id = Str::upper($this->getId()); + + return [ + TextInput::make("OAUTH_{$id}_CLIENT_ID") + ->label('Client ID') + ->placeholder('Client ID') + ->columnSpan(2) + ->required() + ->password() + ->revealable() + ->autocomplete(false) + ->default(env("OAUTH_{$id}_CLIENT_ID")), + TextInput::make("OAUTH_{$id}_CLIENT_SECRET") + ->label('Client Secret') + ->placeholder('Client Secret') + ->columnSpan(2) + ->required() + ->password() + ->revealable() + ->autocomplete(false) + ->default(env("OAUTH_{$id}_CLIENT_SECRET")), + ]; + } + + public function getSetupSteps(): array + { + return [ + Step::make('OAuth Config') + ->columns(4) + ->schema($this->getSettingsForm()), + ]; + } + + public function getName(): string + { + return Str::title($this->getId()); + } + + public function getIcon(): ?string + { + return null; + } + + public function getHexColor(): ?string + { + return null; + } + + public function isEnabled(): bool + { + $id = Str::upper($this->getId()); + + return env("OAUTH_{$id}_ENABLED", false); + } +} diff --git a/app/Extensions/OAuth/Providers/SteamProvider.php b/app/Extensions/OAuth/Providers/SteamProvider.php new file mode 100644 index 000000000..267af540a --- /dev/null +++ b/app/Extensions/OAuth/Providers/SteamProvider.php @@ -0,0 +1,74 @@ + null, + 'client_secret' => env('OAUTH_STEAM_CLIENT_SECRET'), + 'allowed_hosts' => [ + str_replace(['http://', 'https://'], '', env('APP_URL')), + ], + ]; + } + + public function getSettingsForm(): array + { + return [ + TextInput::make('OAUTH_STEAM_CLIENT_SECRET') + ->label('Web API Key') + ->placeholder('Web API Key') + ->columnSpan(4) + ->required() + ->password() + ->revealable() + ->autocomplete(false) + ->default(env('OAUTH_STEAM_CLIENT_SECRET')), + ]; + } + + public function getSetupSteps(): array + { + return array_merge([ + Step::make('Create API Key') + ->schema([ + Placeholder::make('') + ->content(new HtmlString('Visit https://steamcommunity.com/dev/apikey to generate an API key.')), + ]), + ], parent::getSetupSteps()); + } + + public function getIcon(): string + { + return 'tabler-brand-steam-f'; + } + + public function getHexColor(): string + { + return '#00adee'; + } + + public static function register(): self + { + return new self(); + } +} diff --git a/app/Filament/Admin/Pages/Settings.php b/app/Filament/Admin/Pages/Settings.php index 97b287f14..e8352037d 100644 --- a/app/Filament/Admin/Pages/Settings.php +++ b/app/Filament/Admin/Pages/Settings.php @@ -2,12 +2,16 @@ namespace App\Filament\Admin\Pages; +use App\Extensions\OAuth\Providers\OAuthProvider; use App\Models\Backup; use App\Notifications\MailTested; use App\Traits\EnvironmentWriterTrait; use Exception; use Filament\Actions\Action; +use Filament\Forms\Components\Actions; use Filament\Forms\Components\Actions\Action as FormAction; +use Filament\Forms\Components\Group; +use Filament\Forms\Components\Hidden; use Filament\Forms\Components\Placeholder; use Filament\Forms\Components\Section; use Filament\Forms\Components\Select; @@ -28,9 +32,9 @@ use Filament\Pages\Page; use Filament\Support\Enums\MaxWidth; use Illuminate\Http\Client\Factory; use Illuminate\Support\Facades\Artisan; -use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Notification as MailNotification; use Illuminate\Support\HtmlString; +use Illuminate\Support\Str; /** * @property Form $form @@ -461,67 +465,55 @@ class Settings extends Page implements HasForms private function oauthSettings(): array { - $oauthProviders = Config::get('auth.oauth'); - $formFields = []; - foreach ($oauthProviders as $providerName => $providerConfig) { - $providerEnvPrefix = strtoupper($providerName); + $oauthProviders = OAuthProvider::get(); + foreach ($oauthProviders as $oauthProvider) { + $id = Str::upper($oauthProvider->getId()); + $name = Str::title($oauthProvider->getId()); - $fields = [ - Toggle::make("OAUTH_{$providerEnvPrefix}_ENABLED") - ->onColor('success') - ->offColor('danger') - ->onIcon('tabler-check') - ->offIcon('tabler-x') - ->live() - ->columnSpan(1) - ->label('Enabled') - ->default(env("OAUTH_{$providerEnvPrefix}_ENABLED", false)), - ]; - - if (array_key_exists('client_id', $providerConfig['service'] ?? [])) { - $fields[] = TextInput::make("OAUTH_{$providerEnvPrefix}_CLIENT_ID") - ->label('Client ID') - ->columnSpan(2) - ->required() - ->password() - ->revealable() - ->autocomplete(false) - ->hidden(fn (Get $get) => !$get("OAUTH_{$providerEnvPrefix}_ENABLED")) - ->default(env("OAUTH_{$providerEnvPrefix}_CLIENT_ID", $providerConfig['service']['client_id'] ?? '')) - ->placeholder('Client ID'); - } - - if (array_key_exists('client_secret', $providerConfig['service'] ?? [])) { - $fields[] = TextInput::make("OAUTH_{$providerEnvPrefix}_CLIENT_SECRET") - ->label('Client Secret') - ->columnSpan(2) - ->required() - ->password() - ->revealable() - ->autocomplete(false) - ->hidden(fn (Get $get) => !$get("OAUTH_{$providerEnvPrefix}_ENABLED")) - ->default(env("OAUTH_{$providerEnvPrefix}_CLIENT_SECRET", $providerConfig['service']['client_secret'] ?? '')) - ->placeholder('Client Secret'); - } - - if (array_key_exists('base_url', $providerConfig['service'] ?? [])) { - $fields[] = TextInput::make("OAUTH_{$providerEnvPrefix}_BASE_URL") - ->label('Base URL') - ->columnSpanFull() - ->autocomplete(false) - ->hidden(fn (Get $get) => !$get("OAUTH_{$providerEnvPrefix}_ENABLED")) - ->default(env("OAUTH_{$providerEnvPrefix}_BASE_URL", '')) - ->placeholder('Base URL'); - } - - $formFields[] = Section::make(ucfirst($providerName)) + $formFields[] = Section::make($name) ->columns(5) - ->icon($providerConfig['icon'] ?? 'tabler-brand-oauth') - ->collapsed(fn () => !env("OAUTH_{$providerEnvPrefix}_ENABLED", false)) + ->icon($oauthProvider->getIcon() ?? 'tabler-brand-oauth') + ->collapsed(fn () => !env("OAUTH_{$id}_ENABLED", false)) ->collapsible() - ->schema($fields); + ->schema([ + Hidden::make("OAUTH_{$id}_ENABLED") + ->live() + ->default(env("OAUTH_{$id}_ENABLED")), + Actions::make([ + FormAction::make("disable_oauth_$id") + ->visible(fn (Get $get) => $get("OAUTH_{$id}_ENABLED")) + ->label('Disable') + ->color('danger') + ->action(function (Set $set) use ($id) { + $set("OAUTH_{$id}_ENABLED", false); + }), + FormAction::make("enable_oauth_$id") + ->visible(fn (Get $get) => !$get("OAUTH_{$id}_ENABLED")) + ->label('Enable') + ->color('success') + ->steps($oauthProvider->getSetupSteps()) + ->modalHeading("Enable $name") + ->modalSubmitActionLabel('Enable') + ->modalCancelAction(false) + ->action(function ($data, Set $set) use ($id) { + $data = array_merge([ + "OAUTH_{$id}_ENABLED" => 'true', + ], $data); + + $data = array_filter($data, fn ($value) => !Str::startsWith($value, '_noenv')); + + foreach ($data as $key => $value) { + $set($key, $value); + } + }), + ])->columnSpan(1), + Group::make($oauthProvider->getSettingsForm()) + ->visible(fn (Get $get) => $get("OAUTH_{$id}_ENABLED")) + ->columns(4) + ->columnSpan(4), + ]); } return $formFields; diff --git a/app/Filament/Pages/Auth/EditProfile.php b/app/Filament/Pages/Auth/EditProfile.php index 9e3f6e027..414631273 100644 --- a/app/Filament/Pages/Auth/EditProfile.php +++ b/app/Filament/Pages/Auth/EditProfile.php @@ -3,6 +3,7 @@ namespace App\Filament\Pages\Auth; use App\Exceptions\Service\User\TwoFactorAuthenticationTokenInvalid; +use App\Extensions\OAuth\Providers\OAuthProvider; use App\Facades\Activity; use App\Models\ActivityLog; use App\Models\ApiKey; @@ -30,13 +31,13 @@ use Filament\Forms\Components\TextInput; use Filament\Forms\Get; use Filament\Notifications\Notification; use Filament\Pages\Auth\EditProfile as BaseEditProfile; +use Filament\Support\Colors\Color; use Filament\Support\Enums\MaxWidth; use Filament\Support\Exceptions\Halt; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Facades\Hash; use Illuminate\Support\HtmlString; -use Illuminate\Support\Str; use Illuminate\Validation\Rules\Password; use Laravel\Socialite\Facades\Socialite; @@ -126,8 +127,9 @@ class EditProfile extends BaseEditProfile Tab::make('OAuth') ->icon('tabler-brand-oauth') ->visible(function () { - foreach (config('auth.oauth') as $name => $data) { - if ($data['enabled']) { + $oauthProviders = OAuthProvider::get(); + foreach ($oauthProviders as $oauthProvider) { + if ($oauthProvider->isEnabled()) { return true; } } @@ -135,23 +137,27 @@ class EditProfile extends BaseEditProfile return false; }) ->schema(function () { - $providers = []; + $actions = []; - foreach (config('auth.oauth') as $name => $data) { - if (!$data['enabled']) { + $oauthProviders = OAuthProvider::get(); + foreach ($oauthProviders as $oauthProvider) { + if (!$oauthProvider->isEnabled()) { continue; } - $unlink = array_key_exists($name, $this->getUser()->oauth ?? []); + $id = $oauthProvider->getId(); + $name = $oauthProvider->getName(); - $providers[] = Action::make("oauth_$name") - ->label(($unlink ? 'Unlink ' : 'Link ') . Str::title($name)) + $unlink = array_key_exists($id, $this->getUser()->oauth ?? []); + + $actions[] = Action::make("oauth_$id") + ->label(($unlink ? 'Unlink ' : 'Link ') . $name) ->icon($unlink ? 'tabler-unlink' : 'tabler-link') - ->color($data['color']) - ->action(function (UserUpdateService $updateService) use ($name, $unlink) { + ->color(Color::hex($oauthProvider->getHexColor())) + ->action(function (UserUpdateService $updateService) use ($id, $name, $unlink) { if ($unlink) { $oauth = auth()->user()->oauth; - unset($oauth[$name]); + unset($oauth[$id]); $updateService->handle(auth()->user(), ['oauth' => $oauth]); @@ -161,13 +167,13 @@ class EditProfile extends BaseEditProfile ->title("OAuth provider '$name' unlinked") ->success() ->send(); - } elseif (config("auth.oauth.$name.enabled")) { + } else { redirect(Socialite::with($name)->redirect()->getTargetUrl()); } }); } - return [Actions::make($providers)]; + return [Actions::make($actions)]; }), Tab::make('2FA') diff --git a/app/Filament/Pages/Auth/Login.php b/app/Filament/Pages/Auth/Login.php index 774088444..681b0b598 100644 --- a/app/Filament/Pages/Auth/Login.php +++ b/app/Filament/Pages/Auth/Login.php @@ -2,13 +2,14 @@ namespace App\Filament\Pages\Auth; +use App\Extensions\OAuth\Providers\OAuthProvider; use Coderflex\FilamentTurnstile\Forms\Components\Turnstile; use Filament\Forms\Components\Actions; use Filament\Forms\Components\Actions\Action; use Filament\Forms\Components\Component; use Filament\Forms\Components\TextInput; use Filament\Pages\Auth\Login as BaseLogin; -use Illuminate\Support\Str; +use Filament\Support\Colors\Color; use Illuminate\Validation\ValidationException; class Login extends BaseLogin @@ -57,16 +58,19 @@ class Login extends BaseLogin { $actions = []; - foreach (config('auth.oauth') as $name => $data) { - if (!$data['enabled']) { + $oauthProviders = OAuthProvider::get(); + foreach ($oauthProviders as $oauthProvider) { + if (!$oauthProvider->isEnabled()) { continue; } - $actions[] = Action::make("oauth_$name") - ->label(Str::title($name)) - ->icon($data['icon']) - ->color($data['color']) - ->url(route('auth.oauth.redirect', ['driver' => $name], false)); + $id = $oauthProvider->getId(); + + $actions[] = Action::make("oauth_$id") + ->label($oauthProvider->getName()) + ->icon($oauthProvider->getIcon()) + ->color(Color::hex($oauthProvider->getHexColor())) + ->url(route('auth.oauth.redirect', ['driver' => $id], false)); } return Actions::make($actions); diff --git a/app/Http/Controllers/Auth/OAuthController.php b/app/Http/Controllers/Auth/OAuthController.php index 87403d162..40a72a5dc 100644 --- a/app/Http/Controllers/Auth/OAuthController.php +++ b/app/Http/Controllers/Auth/OAuthController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers\Auth; +use App\Extensions\OAuth\Providers\OAuthProvider; use App\Filament\Pages\Auth\EditProfile; use Filament\Notifications\Notification; use Illuminate\Auth\AuthManager; @@ -29,7 +30,7 @@ class OAuthController extends Controller protected function redirect(string $driver): RedirectResponse { // Driver is disabled - redirect to normal login - if (!config("auth.oauth.$driver.enabled")) { + if (!OAuthProvider::get($driver)->isEnabled()) { return redirect()->route('auth.login'); } @@ -42,7 +43,7 @@ class OAuthController extends Controller protected function callback(Request $request, string $driver): RedirectResponse { // Driver is disabled - redirect to normal login - if (!config("auth.oauth.$driver.enabled")) { + if (!OAuthProvider::get($driver)->isEnabled()) { return redirect()->route('auth.login'); } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index d54a449eb..ea05a4380 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -5,6 +5,11 @@ namespace App\Providers; use App\Checks\NodeVersionsCheck; use App\Checks\PanelVersionCheck; use App\Checks\UsedDiskSpaceCheck; +use App\Extensions\OAuth\Providers\AuthentikProvider; +use App\Extensions\OAuth\Providers\CommonProvider; +use App\Extensions\OAuth\Providers\DiscordProvider; +use App\Extensions\OAuth\Providers\GithubProvider; +use App\Extensions\OAuth\Providers\SteamProvider; use App\Models; use App\Models\ApiKey; use App\Models\Node; @@ -21,14 +26,12 @@ use Illuminate\Database\Eloquent\Relations\Relation; use Illuminate\Foundation\Application; use Illuminate\Foundation\Console\AboutCommand; use Illuminate\Support\Facades\Blade; -use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Gate; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\URL; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Str; use Laravel\Sanctum\Sanctum; -use SocialiteProviders\Manager\SocialiteWasCalled; use Spatie\Health\Checks\Checks\CacheCheck; use Spatie\Health\Checks\Checks\DatabaseCheck; use Spatie\Health\Checks\Checks\DebugModeCheck; @@ -82,20 +85,20 @@ class AppServiceProvider extends ServiceProvider Scramble::registerApi('client', ['api_path' => 'api/client', 'info' => ['version' => '1.0']])->afterOpenApiGenerated($bearerTokens); Scramble::registerApi('remote', ['api_path' => 'api/remote', 'info' => ['version' => '1.0']])->afterOpenApiGenerated($bearerTokens); - $oauthProviders = []; - foreach (config('auth.oauth') as $name => $data) { - config()->set("services.$name", array_merge($data['service'], ['redirect' => "/auth/oauth/callback/$name"])); + // Default OAuth providers included with Socialite + CommonProvider::register('facebook', null, 'tabler-brand-facebook-f', '#1877f2'); + CommonProvider::register('x', null, 'tabler-brand-x-f', '#1da1f2'); + CommonProvider::register('linkedin', null, 'tabler-brand-linkedin-f', '#0a66c2'); + CommonProvider::register('google', null, 'tabler-brand-google-f', '#4285f4'); + GithubProvider::register(); + CommonProvider::register('gitlab', null, 'tabler-brand-gitlab', '#fca326'); + CommonProvider::register('bitbucket', null, 'tabler-brand-bitbucket-f', '#205081'); + CommonProvider::register('slack', null, 'tabler-brand-slack', '#6ecadc'); - if (isset($data['provider'])) { - $oauthProviders[$name] = $data['provider']; - } - } - - Event::listen(function (SocialiteWasCalled $event) use ($oauthProviders) { - foreach ($oauthProviders as $name => $provider) { - $event->extendSocialite($name, $provider); - } - }); + // Additional OAuth providers from socialiteproviders.com + AuthentikProvider::register(); + DiscordProvider::register(); + SteamProvider::register(); FilamentColor::register([ 'danger' => Color::Red, diff --git a/config/auth.php b/config/auth.php index aae1c099a..eefb4ede4 100644 --- a/config/auth.php +++ b/config/auth.php @@ -1,7 +1,5 @@ [ @@ -25,116 +23,4 @@ return [ ], ], - 'oauth' => [ - // Default providers - 'facebook' => [ - 'enabled' => env('OAUTH_FACEBOOK_ENABLED'), - 'icon' => 'tabler-brand-facebook-f', - 'color' => Color::hex('#1877f2'), - 'service' => [ - 'client_id' => env('OAUTH_FACEBOOK_CLIENT_ID'), - 'client_secret' => env('OAUTH_FACEBOOK_CLIENT_SECRET'), - ], - ], - 'x' => [ - 'enabled' => env('OAUTH_X_ENABLED'), - 'icon' => 'tabler-brand-x-f', - 'color' => Color::hex('#1da1f2'), - 'service' => [ - 'client_id' => env('OAUTH_X_CLIENT_ID'), - 'client_secret' => env('OAUTH_X_CLIENT_SECRET'), - ], - ], - 'linkedin' => [ - 'enabled' => env('OAUTH_LINKEDIN_ENABLED'), - 'icon' => 'tabler-brand-linkedin-f', - 'color' => Color::hex('#0a66c2'), - 'service' => [ - 'client_id' => env('OAUTH_LINKEDIN_CLIENT_ID'), - 'client_secret' => env('OAUTH_LINKEDIN_CLIENT_SECRET'), - ], - ], - 'google' => [ - 'enabled' => env('OAUTH_GOOGLE_ENABLED'), - 'icon' => 'tabler-brand-google-f', - 'color' => Color::hex('#4285f4'), - 'service' => [ - 'client_id' => env('OAUTH_GOOGLE_CLIENT_ID'), - 'client_secret' => env('OAUTH_GOOGLE_CLIENT_SECRET'), - ], - ], - 'github' => [ - 'enabled' => env('OAUTH_GITHUB_ENABLED'), - 'icon' => 'tabler-brand-github-f', - 'color' => Color::hex('#4078c0'), - 'service' => [ - 'client_id' => env('OAUTH_GITHUB_CLIENT_ID'), - 'client_secret' => env('OAUTH_GITHUB_CLIENT_SECRET'), - ], - ], - 'gitlab' => [ - 'enabled' => env('OAUTH_GITLAB_ENABLED'), - 'icon' => 'tabler-brand-gitlab', - 'color' => Color::hex('#fca326'), - 'service' => [ - 'client_id' => env('OAUTH_GITLAB_CLIENT_ID'), - 'client_secret' => env('OAUTH_GITLAB_CLIENT_SECRET'), - ], - ], - 'bitbucket' => [ - 'enabled' => env('OAUTH_BITBUCKET_ENABLED'), - 'icon' => 'tabler-brand-bitbucket-f', - 'color' => Color::hex('#205081'), - 'service' => [ - 'client_id' => env('OAUTH_BITBUCKET_CLIENT_ID'), - 'client_secret' => env('OAUTH_BITBUCKET_CLIENT_SECRET'), - ], - ], - 'slack' => [ - 'enabled' => env('OAUTH_SLACK_ENABLED'), - 'icon' => 'tabler-brand-slack', - 'color' => Color::hex('#6ecadc'), - 'service' => [ - 'client_id' => env('OAUTH_SLACK_CLIENT_ID'), - 'client_secret' => env('OAUTH_SLACK_CLIENT_SECRET'), - ], - ], - - // Additional providers from socialiteproviders.com - 'authentik' => [ - 'enabled' => env('OAUTH_AUTHENTIK_ENABLED'), - 'icon' => null, - 'color' => Color::hex('#fd4b2d'), - 'service' => [ - 'base_url' => env('OAUTH_AUTHENTIK_BASE_URL'), - 'client_id' => env('OAUTH_AUTHENTIK_CLIENT_ID'), - 'client_secret' => env('OAUTH_AUTHENTIK_CLIENT_SECRET'), - ], - 'provider' => \SocialiteProviders\Authentik\Provider::class, - ], - 'discord' => [ - 'enabled' => env('OAUTH_DISCORD_ENABLED'), - 'icon' => 'tabler-brand-discord-f', - 'color' => Color::hex('#5865F2'), - 'service' => [ - 'client_id' => env('OAUTH_DISCORD_CLIENT_ID'), - 'client_secret' => env('OAUTH_DISCORD_CLIENT_SECRET'), - ], - 'provider' => \SocialiteProviders\Discord\Provider::class, - ], - 'steam' => [ - 'enabled' => env('OAUTH_STEAM_ENABLED'), - 'icon' => 'tabler-brand-steam-f', - 'color' => Color::hex('#00adee'), - 'service' => [ - 'client_id' => null, - 'client_secret' => env('OAUTH_STEAM_CLIENT_SECRET'), - 'allowed_hosts' => [ - str_replace(['http://', 'https://'], '', env('APP_URL')), - ], - ], - 'provider' => \SocialiteProviders\Steam\Provider::class, - ], - ], - ];