Skip to content

Commit

Permalink
Add OIDC Connect
Browse files Browse the repository at this point in the history
  • Loading branch information
heloufir committed Jan 24, 2023
1 parent 106f7f2 commit 0b18886
Show file tree
Hide file tree
Showing 15 changed files with 280 additions and 7 deletions.
Binary file added .rnd
Binary file not shown.
7 changes: 7 additions & 0 deletions app/Filament/Pages/ManageGeneralSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace App\Filament\Pages;

use App\Models\Role;
use App\Settings\GeneralSettings;
use Filament\Forms\Components\Card;
use Filament\Forms\Components\Checkbox;
Expand Down Expand Up @@ -77,6 +78,12 @@ protected function getFormSchema(): array
->helperText(__('The language used by the platform.'))
->searchable()
->options($this->getLanguages()),

Select::make('default_role')
->label(__('Default role'))
->helperText(__('The platform default role (used mainly in OIDC Connect).'))
->searchable()
->options(Role::all()->pluck('name', 'id')->toArray()),
]),
]),
]),
Expand Down
86 changes: 86 additions & 0 deletions app/Http/Controllers/Auth/OidcAuthController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use App\Models\Role;
use App\Models\User;
use App\Settings\GeneralSettings;
use Illuminate\Http\Request;
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
use League\OAuth2\Client\Provider\GenericProvider;

class OidcAuthController extends Controller
{
private $client;

public function __construct()
{
$this->client = new GenericProvider([
'clientId' => config('services.oidc.client_id'),
'clientSecret' => config('services.oidc.client_secret'),
'redirectUri' => config('services.oidc.redirect_uri'),
'urlAuthorize' => config('services.oidc.url_authorize'),
'urlAccessToken' => config('services.oidc.url_access_token'),
'urlResourceOwnerDetails' => config('services.oidc.url_resource_owner_details'),
'scopes' => config('services.oidc.scope')
]);
}

public function redirect()
{
$authUrl = $this->client->getAuthorizationUrl();
return redirect($authUrl);
}

public function callback(Request $request)
{
try {
$accessToken = $this->client->getAccessToken('authorization_code', [
'code' => $request->input('code')
]);
$user = $this->client->getResourceOwner($accessToken);

// Perform any additional validation or user creation here
if ($user) {
$data = $user->toArray();
$user = User::where('email', $data['email'])->first();
if (!$user) {
$user = User::create([
'name' => $data['given_name'] . ' ' . $data['family_name'],
'email' => $data['email'],
'oidc_username' => $data['preferred_username'],
'email_verified_at' => $data['email_verified'] ? now() : null,
'type' => 'oidc',
'oidc_sub' => $data['sub'],
'password' => null
]);
$defaultRoleSettings = app(GeneralSettings::class)->default_role;
if ($defaultRoleSettings && $defaultRole = Role::where('id', $defaultRoleSettings)->first()) {
$user->syncRoles([$defaultRole]);
}
} else {
$user->update([
'name' => $data['given_name'] . ' ' . $data['family_name'],
'email' => $data['email'],
'oidc_username' => $data['preferred_username'],
'type' => 'oidc',
'oidc_sub' => $data['sub'],
'password' => null
]);
$user->refresh();
}

// Log the user in
auth()->login($user);

return redirect()->intended();
}
session()->flash('oidc_error');
return redirect()->route('login');
} catch (IdentityProviderException $e) {
session()->flash('oidc_error');
return redirect()->route('login');
}
}
}
15 changes: 11 additions & 4 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ class User extends Authenticatable implements MustVerifyEmail, FilamentUser
'name',
'email',
'password',
'creation_token'
'creation_token',
'type',
'oidc_username',
'email_verified_at',
];

/**
Expand All @@ -61,12 +64,16 @@ public static function boot()
parent::boot();

static::creating(function (User $item) {
$item->password = bcrypt(uniqid());
$item->creation_token = Uuid::uuid4()->toString();
if ($item->type == 'db') {
$item->password = bcrypt(uniqid());
$item->creation_token = Uuid::uuid4()->toString();
}
});

static::created(function (User $item) {
$item->notify(new UserCreatedNotification($item));
if ($item->type == 'db') {
$item->notify(new UserCreatedNotification($item));
}
});
}

Expand Down
1 change: 1 addition & 0 deletions app/Settings/GeneralSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class GeneralSettings extends Settings
public string|null $site_logo;
public string|null $enable_social_login;
public string|null $site_language;
public string|null $default_role;

public static function group(): string
{
Expand Down
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"laravel/framework": "^9.19",
"laravel/sanctum": "^3.0",
"laravel/tinker": "^2.7",
"league/oauth2-client": "^2.6",
"maatwebsite/excel": "^3.1",
"owenvoke/blade-fontawesome": "^2.1",
"protonemedia/laravel-verify-new-email": "^1.6",
Expand Down
72 changes: 71 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,16 @@
'redirect' => env('TWITTER_CLIENT_CALLBACK')
],

'oidc' => [
'is_enabled' => env('OIDC_IS_ENABLED'),
'client_id' => env('OIDC_CLIENT_ID'),
'client_secret' => env('OIDC_CLIENT_SECRET'),
'discovery_endpoint' => env('OIDC_DISCOVERY_ENDPOINT'),
'redirect_uri' => env('OIDC_REDIRECT_URI'),
'url_authorize' => env('OIDC_URL_AUTHORIZE'),
'url_access_token' => env('OIDC_URL_ACCESS_TOKEN'),
'url_resource_owner_details' => env('OIDC_URL_RESOURCE_OWNER_DETAILS'),
'scope' => explode(",", env('OIDC_SCOPE')),
],

];
38 changes: 38 additions & 0 deletions database/migrations/2023_01_24_084637_update_users_for_oidc.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->string('password')->nullable(true)->change();
$table->string('type')->default('db');
$table->string('oidc_username')->nullable();
$table->string('oidc_sub')->nullable();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->string('password')->nullable(false)->change();
$table->dropColumn('type');
$table->dropColumn('oidc_username');
$table->dropColumn('oidc_sub');
});
}
};
4 changes: 3 additions & 1 deletion database/seeders/DefaultUserSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ class DefaultUserSeeder extends Seeder
public function run()
{
if (User::where('email', '[email protected]')->count() == 0) {
User::create([
$user = User::create([
'name' => 'John DOE',
'email' => '[email protected]',
'password' => bcrypt('Passw@rd'),
'email_verified_at' => now()
]);
$user->creation_token = null;
$user->save();
}
}
}
4 changes: 4 additions & 0 deletions database/seeders/PermissionsSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use App\Models\Permission;
use App\Models\Role;
use App\Models\User;
use App\Settings\GeneralSettings;
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Str;
Expand Down Expand Up @@ -64,6 +65,9 @@ public function run()
$role = Role::firstOrCreate([
'name' => $this->defaultRole
]);
$settings = app(GeneralSettings::class);
$settings->default_role = $role->id;
$settings->save();

// Add all permissions to default role
$role->syncPermissions(Permission::all()->pluck('name')->toArray());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

use App\Models\Role;
use Spatie\LaravelSettings\Migrations\SettingsMigration;

class AddDefaultRoleToGeneralSettings extends SettingsMigration
{
public function up(): void
{
$this->migrator->add('general.default_role');
}
}
7 changes: 6 additions & 1 deletion lang/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -256,5 +256,10 @@
"Jira importation": "Importation jira",
"Jira tickets successfully imported": "Tickets jira importés avec succès",
"Before you can import jira tickets you need to have all the referentials configured": "Avant de pouvoir importer des tickets jira, vous devez avoir configuré tous les référentiels",
"No content found in jira ticket": "Aucun contenu trouvé sur le ticket jira"
"No content found in jira ticket": "Aucun contenu trouvé sur le ticket jira",
"Default role": "Rôle par défaut",
"The platform default role (used mainly in OIDC Connect).": "Le rôle par défaut de la plateforme (utilisé principal par la connexion OIDC).",
"OIDC Connect error": "Erreur de connection OIDC",
"Invalid account!": "Compte incorrect !",
"OIDC Connect": "Connexion OIDC"
}
20 changes: 20 additions & 0 deletions resources/views/vendor/filament-breezy/login.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
<x-filament::brand />
</div>

@if(session()->has('oidc_error'))
<div class="p-4 mb-4 text-sm text-red-800 rounded-lg bg-red-50 dark:bg-gray-800 dark:text-red-400" role="alert">
<span class="font-medium">{{ __('OIDC Connect error') }}</span> {{ __('Invalid account!') }}
</div>
@endif

<div>
<h2 class="font-bold tracking-tight text-center text-2xl">
{{ __('filament::login.heading') }}
Expand Down Expand Up @@ -31,4 +37,18 @@
@if(config('filament-socialite.enabled'))
<x-filament-socialite::buttons />
@endif

@if(config('services.oidc.is_enabled'))
<x-filament::button
color="secondary"
class="w-full"
tag="a"
:href="route('oidc.redirect')"
>
<div class="w-full flex items-center gap-2">
<x-heroicon-o-login class="w-5 h-5" />
{{ __('OIDC Connect') }}
</div>
</x-filament::button>
@endif
</x-filament-breezy::auth-card>
Loading

0 comments on commit 0b18886

Please sign in to comment.