diff --git a/.rnd b/.rnd
new file mode 100644
index 00000000..7a9afee0
Binary files /dev/null and b/.rnd differ
diff --git a/app/Filament/Pages/ManageGeneralSettings.php b/app/Filament/Pages/ManageGeneralSettings.php
index 9bb5a65d..791d1cd8 100644
--- a/app/Filament/Pages/ManageGeneralSettings.php
+++ b/app/Filament/Pages/ManageGeneralSettings.php
@@ -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;
@@ -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()),
]),
]),
]),
diff --git a/app/Http/Controllers/Auth/OidcAuthController.php b/app/Http/Controllers/Auth/OidcAuthController.php
new file mode 100644
index 00000000..0687ca91
--- /dev/null
+++ b/app/Http/Controllers/Auth/OidcAuthController.php
@@ -0,0 +1,86 @@
+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');
+ }
+ }
+}
diff --git a/app/Models/User.php b/app/Models/User.php
index 91f53628..33fba62b 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -34,7 +34,10 @@ class User extends Authenticatable implements MustVerifyEmail, FilamentUser
'name',
'email',
'password',
- 'creation_token'
+ 'creation_token',
+ 'type',
+ 'oidc_username',
+ 'email_verified_at',
];
/**
@@ -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));
+ }
});
}
diff --git a/app/Settings/GeneralSettings.php b/app/Settings/GeneralSettings.php
index d0a97feb..b822352a 100644
--- a/app/Settings/GeneralSettings.php
+++ b/app/Settings/GeneralSettings.php
@@ -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
{
diff --git a/composer.json b/composer.json
index dee6162b..ece2e4df 100644
--- a/composer.json
+++ b/composer.json
@@ -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",
diff --git a/composer.lock b/composer.lock
index 4c170dd9..84b7064f 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "d3e992c0a1606486ed8c014aa7321666",
+ "content-hash": "20230161ca53de174c58f91a9fecc906",
"packages": [
{
"name": "akaunting/laravel-money",
@@ -3366,6 +3366,76 @@
},
"time": "2022-04-15T14:02:14+00:00"
},
+ {
+ "name": "league/oauth2-client",
+ "version": "2.6.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/thephpleague/oauth2-client.git",
+ "reference": "2334c249907190c132364f5dae0287ab8666aa19"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/2334c249907190c132364f5dae0287ab8666aa19",
+ "reference": "2334c249907190c132364f5dae0287ab8666aa19",
+ "shasum": ""
+ },
+ "require": {
+ "guzzlehttp/guzzle": "^6.0 || ^7.0",
+ "paragonie/random_compat": "^1 || ^2 || ^9.99",
+ "php": "^5.6 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.3.5",
+ "php-parallel-lint/php-parallel-lint": "^1.3.1",
+ "phpunit/phpunit": "^5.7 || ^6.0 || ^9.5",
+ "squizlabs/php_codesniffer": "^2.3 || ^3.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-2.x": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "League\\OAuth2\\Client\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Alex Bilbie",
+ "email": "hello@alexbilbie.com",
+ "homepage": "http://www.alexbilbie.com",
+ "role": "Developer"
+ },
+ {
+ "name": "Woody Gilk",
+ "homepage": "https://github.com/shadowhand",
+ "role": "Contributor"
+ }
+ ],
+ "description": "OAuth 2.0 Client Library",
+ "keywords": [
+ "Authentication",
+ "SSO",
+ "authorization",
+ "identity",
+ "idp",
+ "oauth",
+ "oauth2",
+ "single sign on"
+ ],
+ "support": {
+ "issues": "https://github.com/thephpleague/oauth2-client/issues",
+ "source": "https://github.com/thephpleague/oauth2-client/tree/2.6.1"
+ },
+ "time": "2021-12-22T16:42:49+00:00"
+ },
{
"name": "league/uri-parser",
"version": "1.4.1",
diff --git a/config/services.php b/config/services.php
index 41b08b92..d5a89ad1 100644
--- a/config/services.php
+++ b/config/services.php
@@ -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')),
+ ],
+
];
diff --git a/database/migrations/2023_01_24_084637_update_users_for_oidc.php b/database/migrations/2023_01_24_084637_update_users_for_oidc.php
new file mode 100644
index 00000000..54a60b52
--- /dev/null
+++ b/database/migrations/2023_01_24_084637_update_users_for_oidc.php
@@ -0,0 +1,38 @@
+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');
+ });
+ }
+};
diff --git a/database/seeders/DefaultUserSeeder.php b/database/seeders/DefaultUserSeeder.php
index 1235faf1..f0e52ee6 100644
--- a/database/seeders/DefaultUserSeeder.php
+++ b/database/seeders/DefaultUserSeeder.php
@@ -16,12 +16,14 @@ class DefaultUserSeeder extends Seeder
public function run()
{
if (User::where('email', 'john.doe@helper.app')->count() == 0) {
- User::create([
+ $user = User::create([
'name' => 'John DOE',
'email' => 'john.doe@helper.app',
'password' => bcrypt('Passw@rd'),
'email_verified_at' => now()
]);
+ $user->creation_token = null;
+ $user->save();
}
}
}
diff --git a/database/seeders/PermissionsSeeder.php b/database/seeders/PermissionsSeeder.php
index 3c0175ec..941b9d4a 100644
--- a/database/seeders/PermissionsSeeder.php
+++ b/database/seeders/PermissionsSeeder.php
@@ -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;
@@ -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());
diff --git a/database/settings/2022_11_12_173852_add_default_role_to_general_settings.php b/database/settings/2022_11_12_173852_add_default_role_to_general_settings.php
new file mode 100644
index 00000000..441745cd
--- /dev/null
+++ b/database/settings/2022_11_12_173852_add_default_role_to_general_settings.php
@@ -0,0 +1,12 @@
+migrator->add('general.default_role');
+ }
+}
diff --git a/lang/fr.json b/lang/fr.json
index f80e6d20..0c366166 100644
--- a/lang/fr.json
+++ b/lang/fr.json
@@ -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"
}
diff --git a/resources/views/vendor/filament-breezy/login.blade.php b/resources/views/vendor/filament-breezy/login.blade.php
index 06c68d69..7c272531 100644
--- a/resources/views/vendor/filament-breezy/login.blade.php
+++ b/resources/views/vendor/filament-breezy/login.blade.php
@@ -4,6 +4,12 @@