mirror of
https://github.com/librenms/librenms.git
synced 2024-10-07 16:52:45 +00:00
Add support for Okta Group claims to set Roles (#15592)
* Add support for Okta Group claims to set Roles * styleci changes * make Stan happy
This commit is contained in:
@@ -27,6 +27,7 @@ use App\Models\User;
|
||||
use Config;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Laravel\Socialite\Contracts\User as SocialiteUser;
|
||||
use Laravel\Socialite\Facades\Socialite;
|
||||
@@ -52,11 +53,32 @@ class SocialiteController extends Controller
|
||||
// Re-store target url since it will be forgotten after the redirect
|
||||
$request->session()->put('url.intended', redirect()->intended()->getTargetUrl());
|
||||
|
||||
return Socialite::driver($provider)->redirect();
|
||||
$driver = Socialite::driver($provider);
|
||||
|
||||
// https://laravel.com/docs/10.x/socialite#access-scopes
|
||||
if ($driver instanceof \Laravel\Socialite\Two\AbstractProvider) {
|
||||
$scopes = LibreNMSConfig::get('auth.socialite.scopes');
|
||||
if (! empty($scopes) && is_array($scopes)) {
|
||||
return $driver
|
||||
->scopes($scopes)
|
||||
->redirect();
|
||||
}
|
||||
}
|
||||
|
||||
return $driver->redirect();
|
||||
}
|
||||
|
||||
public function callback(Request $request, string $provider): RedirectResponse
|
||||
{
|
||||
/* If we get an error in the callback then attempt to handle nicely */
|
||||
if (array_key_exists('error', $request->query())) {
|
||||
$error = $request->query('error');
|
||||
$error_description = $request->query('error_description');
|
||||
flash()->addError($error . ': ' . $error_description);
|
||||
|
||||
return redirect()->route('login');
|
||||
}
|
||||
|
||||
$this->socialite_user = Socialite::driver($provider)->user();
|
||||
|
||||
// If we already have a valid session, user is trying to pair their account
|
||||
@@ -95,6 +117,7 @@ class SocialiteController extends Controller
|
||||
}
|
||||
|
||||
Auth::login($user);
|
||||
$this->setRolesFromClaim($provider, $user);
|
||||
|
||||
return redirect()->intended();
|
||||
} catch (AuthenticationException $e) {
|
||||
@@ -126,6 +149,40 @@ class SocialiteController extends Controller
|
||||
$user->save();
|
||||
}
|
||||
|
||||
private function setRolesFromClaim(string $provider, $user): bool
|
||||
{
|
||||
$scopes = LibreNMSConfig::get('auth.socialite.scopes');
|
||||
$claims = LibreNMSConfig::get('auth.socialite.claims');
|
||||
$default_role = LibreNMSConfig::get('auth.socialite.default_role');
|
||||
|
||||
if (is_array($scopes) &&
|
||||
$this->socialite_user instanceof \Laravel\Socialite\AbstractUser &&
|
||||
! empty($claims)
|
||||
) {
|
||||
$roles = [];
|
||||
$attributes = $this->socialite_user->getRaw();
|
||||
|
||||
foreach ($scopes as $scope) {
|
||||
foreach (Arr::wrap($attributes[$scope] ?? []) as $scope_data) {
|
||||
$roles = array_merge($roles, $claims[$scope_data]['roles'] ?? []);
|
||||
}
|
||||
}
|
||||
if (count($roles) > 0) {
|
||||
$user->setRoles(array_unique($roles), true);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($default_role !== null && $default_role != 'none') {
|
||||
$user->setRoles([$default_role], false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function pairUser(string $provider): RedirectResponse
|
||||
{
|
||||
$user = Auth::user();
|
||||
|
@@ -271,6 +271,47 @@ If it doesn't work, please double check your configuration values by using the `
|
||||
lnms config:get auth.socialite
|
||||
```
|
||||
|
||||
### Default Role
|
||||
|
||||
Since most Socialite Providers don't provide Authorization only Authentication it is possible to set
|
||||
the default User Role for Authorized users. Appropriate care should be taken.
|
||||
|
||||
- none: **No Access**: User has no access
|
||||
|
||||
- normal: **Normal User**: You will need to assign device / port
|
||||
permissions for users at this level.
|
||||
|
||||
- global-read: **Global Read**: Read only Administrator.
|
||||
|
||||
- admin: **Administrator**: This is a global read/write admin account.
|
||||
|
||||
!!! setting "settings/auth/socialite"
|
||||
```bash
|
||||
lnms config:set auth.socialite.default_role global-read
|
||||
```
|
||||
|
||||
### Claims / Access Scopes
|
||||
|
||||
Socialite can specifiy scopes that should be included with in the authentication request.
|
||||
(see https://laravel.com/docs/10.x/socialite#access-scopes )
|
||||
|
||||
For example, if Okta is configured to expose group information it is possible to use these group
|
||||
names to configure User Roles.
|
||||
|
||||
First enable sending the 'groups' claim (along with the normal openid, profile, and email claims )
|
||||
!!! setting "settings/auth/socialite"
|
||||
```bash
|
||||
lnms config:set auth.socialite.scopes.+ groups
|
||||
```
|
||||
|
||||
Then setup mappings from the returned claim arrays to the User levels you want
|
||||
!!! setting "settings/auth/socialite"
|
||||
```bash
|
||||
lnms config:set auth.socialite.claims.RETURN_FROM_CLAIM.roles '["admin"]'
|
||||
lnms config:set auth.socialite.claims.OTHER_RETURN_FROM_CLAIM.roles '["global-read","cleaner"]'
|
||||
```
|
||||
|
||||
|
||||
## SAML2 Example
|
||||
|
||||
### Install plugin
|
||||
|
@@ -282,6 +282,10 @@ return [
|
||||
'configs' => [
|
||||
'description' => 'Provider configs',
|
||||
],
|
||||
'scopes' => [
|
||||
'description' => 'Scopes that should be included with in the authentication request',
|
||||
'help' => 'See https://laravel.com/docs/10.x/socialite#access-scopes',
|
||||
],
|
||||
],
|
||||
],
|
||||
'auth_ad_base_dn' => [
|
||||
|
@@ -430,6 +430,41 @@
|
||||
"value.saml.entityid": "url"
|
||||
}
|
||||
},
|
||||
"auth.socialite.scopes": {
|
||||
"group": "auth",
|
||||
"section": "socialite",
|
||||
"order": 4,
|
||||
"type": "array"
|
||||
},
|
||||
"auth.socialite.default_role": {
|
||||
"group": "auth",
|
||||
"section": "socialite",
|
||||
"order": 5,
|
||||
"type": "select",
|
||||
"default": "none",
|
||||
"options" : {
|
||||
"none" : "No Access",
|
||||
"normal" : "Normal Access",
|
||||
"global-read" : "Global Viewing Access",
|
||||
"admin" : "Global Administrative Access"
|
||||
}
|
||||
},
|
||||
"auth.socialite.claims": {
|
||||
"default": {},
|
||||
"group": "auth",
|
||||
"section": "socialite",
|
||||
"order": 6,
|
||||
"type": "group-role-map",
|
||||
"options": {
|
||||
"groupPlaceholder": "Claim Group"
|
||||
},
|
||||
"validate": {
|
||||
"value": "array",
|
||||
"value.*": "array",
|
||||
"value.*.roles": "array|required",
|
||||
"value.*.roles.*": "string"
|
||||
}
|
||||
},
|
||||
"auth_ad_base_dn": {
|
||||
"group": "auth",
|
||||
"section": "ad",
|
||||
|
Reference in New Issue
Block a user