Compare commits
3 Commits
ae6869781e
...
5e5bb62d75
| Author | SHA1 | Date | |
|---|---|---|---|
| 5e5bb62d75 | |||
| cd80efe1e3 | |||
| 0df43fefcb |
@ -11,6 +11,7 @@ return [
|
|||||||
'urlAccessToken' => env("OAUTH2_URL_ACCESS_TOKEN", env("OAUTH2_BASE_URL")."/token"),
|
'urlAccessToken' => env("OAUTH2_URL_ACCESS_TOKEN", env("OAUTH2_BASE_URL")."/token"),
|
||||||
'urlResourceOwnerDetails' => env("OAUTH2_URL_RSOURCE_OWNER_DETAILS", env("OAUTH2_BASE_URL")."/userinfo"),
|
'urlResourceOwnerDetails' => env("OAUTH2_URL_RSOURCE_OWNER_DETAILS", env("OAUTH2_BASE_URL")."/userinfo"),
|
||||||
'urlLogout' => env("OAUTH2_URL_LOGOUT", env("OAUTH2_BASE_URL")."/logout"),
|
'urlLogout' => env("OAUTH2_URL_LOGOUT", env("OAUTH2_BASE_URL")."/logout"),
|
||||||
|
'urlAfterlogout' => env("OAUTH2_URL_AFTER_LOGOUT", url('/admin')),
|
||||||
'scopes' => env("OAUTH2_SCOPES", "profile email openid"),
|
'scopes' => env("OAUTH2_SCOPES", "profile email openid"),
|
||||||
'updateRoles' => env("OAUTH2_UPDATE_ROLES", false)
|
'updateRoles' => env("OAUTH2_UPDATE_ROLES", false)
|
||||||
|
|
||||||
|
|||||||
@ -5,19 +5,22 @@ namespace AlexanderGabriel\FilamentOauth2\Http\Controllers;
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Models\Role;
|
use App\Models\Role;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Dotenv\Exception\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Filament\Facades\Filament;
|
use Filament\Facades\Filament;
|
||||||
use Filament\Http\Responses\Auth\LoginResponse;
|
use Filament\Http\Responses\Auth\LoginResponse;
|
||||||
use Filament\Models\Contracts\FilamentUser;
|
use Filament\Models\Contracts\FilamentUser;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
|
use League\OAuth2\Client\Provider\Exception\IdentityProviderException;
|
||||||
use League\OAuth2\Client\Provider\GenericProvider;
|
use League\OAuth2\Client\Provider\GenericProvider;
|
||||||
use League\OAuth2\Client\Token\AccessToken;
|
|
||||||
|
|
||||||
class Oauth2Controller extends Controller
|
class Oauth2Controller extends Controller
|
||||||
{
|
{
|
||||||
private GenericProvider $oauth2Provider;
|
private GenericProvider $oauth2Provider;
|
||||||
|
private Model $user;
|
||||||
|
private $accessToken;
|
||||||
|
private $oauth2User;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@ -41,79 +44,41 @@ class Oauth2Controller extends Controller
|
|||||||
public function handleCallback(Request $request)
|
public function handleCallback(Request $request)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$accessToken = $this->oauth2Provider->getAccessToken('authorization_code', ['code' => $request->input('code')]);
|
$this->accessToken = $this->oauth2Provider->getAccessToken('authorization_code', ['code' => $request->input('code')]);
|
||||||
$oauth2User = $this->oauth2Provider->getResourceOwner($accessToken)->toArray();
|
$this->oauth2User = $this->oauth2Provider->getResourceOwner($this->accessToken)->toArray();
|
||||||
|
|
||||||
$user = User::firstOrCreate([
|
// Create the user if it does not exist
|
||||||
'email' => $oauth2User['email'],
|
$this->user = User::firstOrCreate([
|
||||||
|
'email' => $this->oauth2User['email'],
|
||||||
],[
|
],[
|
||||||
'name' => $oauth2User['name'],
|
'name' => $this->oauth2User['name'],
|
||||||
|
// Todo -> is there a better way?
|
||||||
'password' => 'nonsense'
|
'password' => 'nonsense'
|
||||||
]);
|
]);
|
||||||
if($user->name != $oauth2User['name'])
|
|
||||||
|
// Update user data if different from Oauth2-Server
|
||||||
|
if($this->user->name != $this->oauth2User['name'])
|
||||||
{
|
{
|
||||||
$user->name = $oauth2User['name'];
|
$this->user->name = $this->oauth2User['name'];
|
||||||
$user->save();
|
$this->user->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
Filament::auth()->loginUsingId($user->id, false);
|
// Login User by id
|
||||||
|
Filament::auth()->loginUsingId($this->user->id, false);
|
||||||
|
|
||||||
|
// Taken from original LoginClass...
|
||||||
if (
|
if (
|
||||||
($user instanceof FilamentUser) &&
|
($this->user instanceof FilamentUser) &&
|
||||||
(! $user->canAccessPanel(Filament::getCurrentPanel()))
|
(! $this->user->canAccessPanel(Filament::getCurrentPanel()))
|
||||||
) {
|
) {
|
||||||
Filament::auth()->logout();
|
Filament::auth()->logout();
|
||||||
|
|
||||||
$this->throwFailureValidationException();
|
$this->throwFailureValidationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
session()->regenerate();
|
session()->regenerate();
|
||||||
|
|
||||||
//Should i update Roles and are there roles?
|
// Handle Role Mapping
|
||||||
$hasRoles = false;
|
$this->handleRoleMapping();
|
||||||
try {
|
|
||||||
$roles = $user->roles();
|
|
||||||
if($roles) $hasRoles = true;
|
|
||||||
}
|
|
||||||
catch (Exception $e) {
|
|
||||||
//No Roles. Nothing to do
|
|
||||||
}
|
|
||||||
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);
|
return app(LoginResponse::class);
|
||||||
|
|
||||||
@ -122,6 +87,51 @@ class Oauth2Controller extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function handleRoleMapping(): void
|
||||||
|
{
|
||||||
|
if(config('filament-oauth2.updateRoles') != false) {
|
||||||
|
try {
|
||||||
|
$roles = $this->user->roles();
|
||||||
|
if($roles) {
|
||||||
|
// Are there roles in the Token?
|
||||||
|
$this->accessToken = explode(".", $this->accessToken);
|
||||||
|
if(isset($this->accessToken[1])) {
|
||||||
|
$this->accessToken = json_decode(base64_decode($this->accessToken[1]));
|
||||||
|
$clientId = config('filament-oauth2.clientId');
|
||||||
|
if(isset($this->accessToken->resource_access) && isset($this->accessToken->resource_access->$clientId)) {
|
||||||
|
// Roles are defined. Maybe empty to remove all Roles from user
|
||||||
|
// TODO: test this without roles
|
||||||
|
if(!isset($this->accessToken->resource_access->$clientId->roles)) $roles = [];
|
||||||
|
else $roles = $this->accessToken->resource_access->$clientId->roles;
|
||||||
|
$userRoles = $this->user->roles();
|
||||||
|
// Disconnect roles not in the access token any more
|
||||||
|
foreach ($userRoles as $userRole) {
|
||||||
|
if(!in_array($userRole, $roles)) {
|
||||||
|
$this->user->roles()->detach($userRole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Connect or create roles
|
||||||
|
foreach($roles as $role) {
|
||||||
|
$existingRole = Role::first('name', '=', $role);
|
||||||
|
if($existingRole) {
|
||||||
|
$this->user->roles()->attach($existingRole->id);
|
||||||
|
} else {
|
||||||
|
$newRole = Role::create(['name' => $role]);
|
||||||
|
// needed?
|
||||||
|
$newRole->save();
|
||||||
|
$this->user->roles()->attach($newRole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception $e) {
|
||||||
|
// No Roles. Nothing to do
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function throwFailureValidationException(): never
|
protected function throwFailureValidationException(): never
|
||||||
{
|
{
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
@ -131,10 +141,12 @@ class Oauth2Controller extends Controller
|
|||||||
|
|
||||||
public function handleLogout(Request $request)
|
public function handleLogout(Request $request)
|
||||||
{
|
{
|
||||||
|
// https://openid.net/specs/openid-connect-rpinitiated-1_0.html
|
||||||
session()->invalidate();
|
session()->invalidate();
|
||||||
session()->regenerateToken();
|
session()->regenerateToken();
|
||||||
Filament::auth()->logout();
|
Filament::auth()->logout();
|
||||||
$logoutUrl = config('filament-oauth2.urlLogout').'?client_id=filamentphp';
|
$logoutUrl = config('filament-oauth2.urlLogout').'?client_id=filamentphp';
|
||||||
|
if(config('filament-oauth2.urlAfterlogout') != url('/')) $logoutUrl .= '&post_logout_redirect_uri='.config('filament-oauth2.urlAfterlogout');
|
||||||
return redirect($logoutUrl);
|
return redirect($logoutUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user