Compare commits
No commits in common. "6840624be2ed8850b4a34b611965e617b1496361" and "e24e019609bcae6c43ab828bfce0cf04ab8c0dc7" have entirely different histories.
6840624be2
...
e24e019609
@ -22,7 +22,6 @@
|
||||
"require": {
|
||||
"php": "^8.1",
|
||||
"filament/filament": "^3.0",
|
||||
"league/oauth2-client": "*",
|
||||
"spatie/laravel-package-tools": "^1.15.0"
|
||||
},
|
||||
"require-dev": {
|
||||
@ -71,4 +70,4 @@
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
// config for AlexanderGabriel/FilamentOauth2
|
||||
|
||||
return [
|
||||
|
||||
'clientId' => env("OAUTH2_CLIENT_ID"),
|
||||
'clientSecret' => env("OAUTH2_CLIENT_SECRET"),
|
||||
'baseUrl' => env("OAUTH2_BASE_URL"), // https://DOMAIN/realms/REALM/protocol/openid-connect
|
||||
'urlAuthorize' => env("OAUTH2_URL_AUTHORIZE", env("OAUTH2_BASE_URL")."/auth"),
|
||||
'urlAccessToken' => env("OAUTH2_URL_ACCESS_TOKEN", env("OAUTH2_BASE_URL")."/token"),
|
||||
'urlResourceOwnerDetails' => env("OAUTH2_URL_RSOURCE_OWNER_DETAILS", env("OAUTH2_BASE_URL")."/userinfo"),
|
||||
'scopes' => env("OAUTH2_SCOPES", "profile email openid"),
|
||||
'updateRoles' => env("OAUTH2_UPDATE_ROLES", false)
|
||||
|
||||
];
|
||||
6
config/oauth2.php
Normal file
6
config/oauth2.php
Normal file
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
// config for AlexanderGabriel/FilamentOauth2
|
||||
return [
|
||||
|
||||
];
|
||||
19
database/migrations/create_oauth2_table.php.stub
Normal file
19
database/migrations/create_oauth2_table.php.stub
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::create('filament_oauth2_table', function (Blueprint $table) {
|
||||
$table->id();
|
||||
|
||||
// add fields
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
// https://github.com/filamentphp/actions/blob/4.x/routes/web.php
|
||||
|
||||
use AlexanderGabriel\FilamentOauth2\Http\Controllers\Oauth2Controller;
|
||||
use Filament\Facades\Filament;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
$panel = Filament::getCurrentPanel();
|
||||
|
||||
Route::prefix($panel->getPath())
|
||||
->middleware($panel->getMiddleware())
|
||||
->group(function () {
|
||||
Route::get('login', [Oauth2Controller::class, 'redirectToOauth2Server'])->name('redirectToOauth2Server');
|
||||
Route::name('filament-oauth2.')
|
||||
->prefix('filament-oauth2')
|
||||
->group(function () {
|
||||
Route::get('redirectToOauth2Server', [Oauth2Controller::class, 'redirectToOauth2Server'])
|
||||
->name('redirectToOauth2Server');
|
||||
Route::get('handleCallback', [Oauth2Controller::class, 'handleCallback'])
|
||||
->name('handleCallback');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@ -2,12 +2,4 @@
|
||||
|
||||
namespace AlexanderGabriel\FilamentOauth2;
|
||||
|
||||
use AlexanderGabriel\FilamentOauth2\Http\Controllers\Oauth2Controller;
|
||||
|
||||
class FilamentOauth2 {
|
||||
|
||||
public static function getLoginRouteAction(): array
|
||||
{
|
||||
return [Oauth2Controller::class, 'redirectToOauth2Server'];
|
||||
}
|
||||
}
|
||||
class FilamentOauth2 {}
|
||||
|
||||
@ -2,7 +2,6 @@
|
||||
|
||||
namespace AlexanderGabriel\FilamentOauth2;
|
||||
|
||||
use AlexanderGabriel\FilamentOauth2\Facades\FilamentOauth2;
|
||||
use Filament\Contracts\Plugin;
|
||||
use Filament\Panel;
|
||||
|
||||
@ -15,7 +14,7 @@ class FilamentOauth2Plugin implements Plugin
|
||||
|
||||
public function register(Panel $panel): void
|
||||
{
|
||||
$panel->login(FilamentOauth2::getLoginRouteAction());
|
||||
//
|
||||
}
|
||||
|
||||
public function boot(Panel $panel): void
|
||||
|
||||
@ -2,6 +2,12 @@
|
||||
|
||||
namespace AlexanderGabriel\FilamentOauth2;
|
||||
|
||||
use Filament\Support\Assets\AlpineComponent;
|
||||
use Filament\Support\Assets\Asset;
|
||||
use Filament\Support\Assets\Css;
|
||||
use Filament\Support\Assets\Js;
|
||||
use Filament\Support\Facades\FilamentAsset;
|
||||
use Filament\Support\Facades\FilamentIcon;
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Livewire\Features\SupportTesting\Testable;
|
||||
use Spatie\LaravelPackageTools\Commands\InstallCommand;
|
||||
@ -28,9 +34,10 @@ class FilamentOauth2ServiceProvider extends PackageServiceProvider
|
||||
->hasInstallCommand(function (InstallCommand $command) {
|
||||
$command
|
||||
->publishConfigFile()
|
||||
->publishMigrations()
|
||||
->askToRunMigrations()
|
||||
->askToStarRepoOnGitHub('alexandergabriel/filament-oauth2');
|
||||
})
|
||||
->hasRoutes('web');
|
||||
});
|
||||
|
||||
$configFileName = $package->shortName();
|
||||
|
||||
@ -38,6 +45,10 @@ class FilamentOauth2ServiceProvider extends PackageServiceProvider
|
||||
$package->hasConfigFile();
|
||||
}
|
||||
|
||||
if (file_exists($package->basePath('/../database/migrations'))) {
|
||||
$package->hasMigrations($this->getMigrations());
|
||||
}
|
||||
|
||||
if (file_exists($package->basePath('/../resources/lang'))) {
|
||||
$package->hasTranslations();
|
||||
}
|
||||
@ -51,6 +62,20 @@ class FilamentOauth2ServiceProvider extends PackageServiceProvider
|
||||
|
||||
public function packageBooted(): void
|
||||
{
|
||||
// Asset Registration
|
||||
FilamentAsset::register(
|
||||
$this->getAssets(),
|
||||
$this->getAssetPackageName()
|
||||
);
|
||||
|
||||
FilamentAsset::registerScriptData(
|
||||
$this->getScriptData(),
|
||||
$this->getAssetPackageName()
|
||||
);
|
||||
|
||||
// Icon Registration
|
||||
FilamentIcon::register($this->getIcons());
|
||||
|
||||
// Handle Stubs
|
||||
if (app()->runningInConsole()) {
|
||||
foreach (app(Filesystem::class)->files(__DIR__ . '/../stubs/') as $file) {
|
||||
@ -64,6 +89,23 @@ class FilamentOauth2ServiceProvider extends PackageServiceProvider
|
||||
Testable::mixin(new TestsFilamentOauth2);
|
||||
}
|
||||
|
||||
protected function getAssetPackageName(): ?string
|
||||
{
|
||||
return 'alexandergabriel/filament-oauth2';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<Asset>
|
||||
*/
|
||||
protected function getAssets(): array
|
||||
{
|
||||
return [
|
||||
// AlpineComponent::make('filament-oauth2', __DIR__ . '/../resources/dist/components/filament-oauth2.js'),
|
||||
Css::make('filament-oauth2-styles', __DIR__ . '/../resources/dist/filament-oauth2.css'),
|
||||
Js::make('filament-oauth2-scripts', __DIR__ . '/../resources/dist/filament-oauth2.js'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string>
|
||||
*/
|
||||
@ -74,6 +116,14 @@ class FilamentOauth2ServiceProvider extends PackageServiceProvider
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
protected function getIcons(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
@ -82,4 +132,21 @@ class FilamentOauth2ServiceProvider extends PackageServiceProvider
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function getScriptData(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
*/
|
||||
protected function getMigrations(): array
|
||||
{
|
||||
return [
|
||||
'create_filament-oauth2_table',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,136 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace AlexanderGabriel\FilamentOauth2\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Role;
|
||||
use App\Models\User;
|
||||
use Dotenv\Exception\ValidationException;
|
||||
use Exception;
|
||||
use Filament\Facades\Filament;
|
||||
use Filament\Http\Responses\Auth\LoginResponse;
|
||||
use Filament\Models\Contracts\FilamentUser;
|
||||
use Illuminate\Http\Request;
|
||||
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
|
||||
use League\OAuth2\Client\Provider\GenericProvider;
|
||||
use League\OAuth2\Client\Token\AccessToken;
|
||||
|
||||
class Oauth2Controller extends Controller
|
||||
{
|
||||
private GenericProvider $oauth2Provider;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// https://oauth2-client.thephpleague.com/usage/
|
||||
$this->oauth2Provider = new GenericProvider([
|
||||
'clientId' => config('filament-oauth2.clientId'), // The client ID assigned to you by the provider
|
||||
'clientSecret' => config('filament-oauth2.clientSecret'), // The client password assigned to you by the provider
|
||||
'redirectUri' => route('filament-oauth2.handleCallback'),
|
||||
'urlAuthorize' => config('filament-oauth2.urlAuthorize'),
|
||||
'urlAccessToken' => config('filament-oauth2.urlAccessToken'),
|
||||
'urlResourceOwnerDetails' => config('filament-oauth2.urlResourceOwnerDetails'),
|
||||
'scopes' => config('filament-oauth2.scopes'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function redirectToOauth2Server()
|
||||
{
|
||||
return redirect($this->oauth2Provider->getAuthorizationUrl());
|
||||
}
|
||||
|
||||
public function handleCallback(Request $request)
|
||||
{
|
||||
try {
|
||||
$accessToken = $this->oauth2Provider->getAccessToken('authorization_code', ['code' => $request->input('code')]);
|
||||
$oauth2User = $this->oauth2Provider->getResourceOwner($accessToken)->toArray();
|
||||
|
||||
$user = User::firstOrCreate([
|
||||
'email' => $oauth2User['email'],
|
||||
],[
|
||||
'name' => $oauth2User['name'],
|
||||
'password' => 'nonsense'
|
||||
]);
|
||||
if($user->name != $oauth2User['name'])
|
||||
{
|
||||
$user->name = $oauth2User['name'];
|
||||
$user->save();
|
||||
}
|
||||
|
||||
Filament::auth()->loginUsingId($user->id, false);
|
||||
|
||||
if (
|
||||
($user instanceof FilamentUser) &&
|
||||
(! $user->canAccessPanel(Filament::getCurrentPanel()))
|
||||
) {
|
||||
Filament::auth()->logout();
|
||||
|
||||
$this->throwFailureValidationException();
|
||||
}
|
||||
|
||||
session()->regenerate();
|
||||
|
||||
//Should i update Roles and are there roles?
|
||||
$hasRoles = false;
|
||||
try {
|
||||
$roles = $user->roles();
|
||||
if($roles) $hasRoles = true;
|
||||
}
|
||||
catch (Exception $e) {
|
||||
//keine Rollen... Nichts tun...
|
||||
}
|
||||
if($hasRoles && config('filament-oauth2.updateRoles') != false) {
|
||||
//Are there roles in the Token?
|
||||
$accessToken = explode(".", $accessToken);
|
||||
if(isset($accessToken[1])) {
|
||||
$accessToken = json_decode(base64_decode($accessToken[1]));
|
||||
$clientId = config('filament-oauth2.clientId');
|
||||
if(isset($accessToken->resource_access) && isset($accessToken->resource_access->$clientId)) {
|
||||
// Roles are defined. Maybe empty to remove all Roles from user
|
||||
// TODO: test
|
||||
if(!isset($accessToken->resource_access->$clientId->roles)) $roles = [];
|
||||
else $roles = $accessToken->resource_access->$clientId->roles;
|
||||
|
||||
$userRoles = $user->roles();
|
||||
|
||||
//disconnect roles
|
||||
foreach ($userRoles as $userRole) {
|
||||
if(!in_array($userRole, $roles)) {
|
||||
$user->roles()->detach($userRole);
|
||||
}
|
||||
}
|
||||
|
||||
// connect or create roles
|
||||
foreach($roles as $role) {
|
||||
$existingRole = Role::first('name', '=', $role);
|
||||
if($existingRole) {
|
||||
$user->roles()->attach($existingRole->id);
|
||||
} else {
|
||||
$newRole = Role::create(['name' => $role]);
|
||||
$newRole->save();
|
||||
$user->roles()->attach($newRole);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return app(LoginResponse::class);
|
||||
|
||||
} catch (IdentityProviderException $e) {
|
||||
dd($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected function throwFailureValidationException(): never
|
||||
{
|
||||
throw ValidationException::withMessages([
|
||||
'data.email' => __('filament-panels::pages/auth/login.messages.failed'),
|
||||
]);
|
||||
}
|
||||
|
||||
//TODO: Logout
|
||||
// filament-oauth2-demo/vendor/filament/filament/src/Http/Controllers/Auth/LogoutController.php
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user