mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-18 07:23:13 +00:00
PHRAS-4108 openid : add claims mapping and groups filtering (#4563)
* openid add group mapping * add migration patch for configuration injection
This commit is contained in:
@@ -229,6 +229,14 @@ authentication:
|
|||||||
debug: false
|
debug: false
|
||||||
auto-logout: false
|
auto-logout: false
|
||||||
auto-connect-idp-name: null
|
auto-connect-idp-name: null
|
||||||
|
groupmask: "/phraseanet_([^,]+)/i"
|
||||||
|
fieldmap:
|
||||||
|
id: sub
|
||||||
|
login: email
|
||||||
|
firstname: given_name
|
||||||
|
lastname: family_name
|
||||||
|
email: email
|
||||||
|
groups: group
|
||||||
registration-fields:
|
registration-fields:
|
||||||
-
|
-
|
||||||
name: company
|
name: company
|
||||||
|
@@ -32,6 +32,14 @@ authentication:
|
|||||||
# logout with phraseanet and also logout with keycloak
|
# logout with phraseanet and also logout with keycloak
|
||||||
auto-logout: true
|
auto-logout: true
|
||||||
auto-connect-idp-name: null
|
auto-connect-idp-name: null
|
||||||
|
groupmask: "/cn=phraseanet_([^,]+),cn=users,ou=alchemy$/i"
|
||||||
|
fieldmap:
|
||||||
|
id: sub
|
||||||
|
login: email
|
||||||
|
firstname: given_name
|
||||||
|
lastname: family_name
|
||||||
|
email: email
|
||||||
|
groups: group
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -47,16 +55,19 @@ authentication:
|
|||||||
|
|
||||||
set the 'Valid post logout redirect URIs' field with `https://{phraseanet-host}/login/logout/` eg: https://phraseanet.phrasea.local/login/logout/
|
set the 'Valid post logout redirect URIs' field with `https://{phraseanet-host}/login/logout/` eg: https://phraseanet.phrasea.local/login/logout/
|
||||||
|
|
||||||
- Choose a client > client scopes > '.... dedicated'
|
- if not exist create a client scope with mapper type Group Membership
|
||||||
|
|
||||||
add a 'groups' mapper if not exist, > Add mapper > by configuration
|
|
||||||
|
|
||||||
`Mapper type` => Group Membership
|
`Mapper type` => Group Membership
|
||||||
`Name` => groups
|
`Name` => group
|
||||||
`Token Claim Name` => groups
|
`Token Claim Name` => group
|
||||||
`Full group path` => off
|
`Full group path` => off
|
||||||
`Add to userinfo` => on
|
`Add to userinfo` => on
|
||||||
|
|
||||||
|
- Add the created client scope to the client
|
||||||
|
|
||||||
|
Choose a client > client scopes > Add client scope > choose the scope
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#### token expiration
|
#### token expiration
|
||||||
- we can define token expiration in keycloak
|
- we can define token expiration in keycloak
|
||||||
|
|
||||||
|
@@ -343,20 +343,26 @@ class Openid extends AbstractProvider
|
|||||||
|
|
||||||
$this->debug();
|
$this->debug();
|
||||||
|
|
||||||
$userName = $data['preferred_username'];
|
$usegroups = isset($this->config['usegroups']) ? $this->config['usegroups'] : false;
|
||||||
|
$idKey = isset($this->config['fieldmap']['id']) ? $this->config['fieldmap']['id'] : 'sub';
|
||||||
|
$loginKey = isset($this->config['fieldmap']['login']) ? $this->config['fieldmap']['login'] : 'email';
|
||||||
|
$firstnameKey = isset($this->config['fieldmap']['firstname']) ? $this->config['fieldmap']['firstname'] : 'given_name';
|
||||||
|
$lastnameKey = isset($this->config['fieldmap']['lastname']) ? $this->config['fieldmap']['lastname'] : 'family_name';
|
||||||
|
$emailKey = isset($this->config['fieldmap']['email']) ? $this->config['fieldmap']['email'] : 'email';
|
||||||
|
$groupsKey = isset($this->config['fieldmap']['groups']) ? $this->config['fieldmap']['groups'] : 'groups';
|
||||||
|
$distantUserId = $data['sub'];
|
||||||
|
|
||||||
if (!\Swift_Validate::email($userName) && isset($data['email'])) {
|
if (!\Swift_Validate::email($data[$loginKey]) && isset($data['email'])) {
|
||||||
$userName = $data['email'];// login to be an email
|
$loginKey = 'email';// login to be an email
|
||||||
}
|
}
|
||||||
|
|
||||||
$usegroups = isset($this->config['usegroups']) ? $this->config['usegroups'] : false;
|
|
||||||
$userUA = $this->CreateUser([
|
$userUA = $this->CreateUser([
|
||||||
'id' => $distantUserId = $data['sub'],
|
'id' => $data[$idKey],
|
||||||
'login' => $userName,
|
'login' => $userName = $data[$loginKey],
|
||||||
'firstname' => isset($data['given_name']) ? $data['given_name'] : '',
|
'firstname' => isset($data[$firstnameKey]) ? $data[$firstnameKey] : '',
|
||||||
'lastname' => isset($data['family_name']) ? $data['family_name'] : '' ,
|
'lastname' => isset($data[$lastnameKey]) ? $data[$lastnameKey] : '' ,
|
||||||
'email' => isset($data['email']) ? $data['email'] : '',
|
'email' => isset($data[$emailKey]) ? $data[$emailKey] : '',
|
||||||
'_groups' => isset($data['groups']) && $usegroups ? $data['groups'] : ''
|
'_groups' => isset($data[$groupsKey]) && $usegroups ? $this->filterGroups($data[$groupsKey]) : ''
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$userAuthProviderRepository = $this->getUsrAuthProviderRepository();
|
$userAuthProviderRepository = $this->getUsrAuthProviderRepository();
|
||||||
@@ -715,6 +721,36 @@ class Openid extends AbstractProvider
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function filterGroups($groups)
|
||||||
|
{
|
||||||
|
$this->debug(sprintf("filtering openid groups :\n%s", print_r($groups, true)));
|
||||||
|
|
||||||
|
$ret = [];
|
||||||
|
if ($this->config['groupmask']) {
|
||||||
|
$this->debug(sprintf("filtering groups with regexp : \"%s\"", $this->config['groupmask']));
|
||||||
|
foreach ($groups as $grp) {
|
||||||
|
$matches = [];
|
||||||
|
$retpreg = preg_match_all($this->config['groupmask'], $grp, $matches, PREG_SET_ORDER);
|
||||||
|
|
||||||
|
$this->debug(sprintf("preg_match('%s', '%s', ...)\n - returned %s \n - matches = %s "
|
||||||
|
, $this->config['groupmask'], $grp
|
||||||
|
, print_r($retpreg, true), print_r($matches, true)));
|
||||||
|
|
||||||
|
foreach ($matches as $match) {
|
||||||
|
if (count($match)>0 && isset($match[1]) && !array_key_exists($match[1], $ret)) {
|
||||||
|
$ret[] = $match[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$this->debug(sprintf("no groupmask defined, openid groups ignored"));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->debug(sprintf("filtered groups :\n%s", print_r($ret, true)));
|
||||||
|
|
||||||
|
return empty($ret) ? '' : $ret ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -50,13 +50,36 @@ class patch_4111PHRAS4106 implements patchInterface
|
|||||||
$conf = $app['conf'];
|
$conf = $app['conf'];
|
||||||
foreach ($app['conf']->get(['authentication', 'providers'], []) as $providerId => $data) {
|
foreach ($app['conf']->get(['authentication', 'providers'], []) as $providerId => $data) {
|
||||||
if ($data['type'] === "openid") {
|
if ($data['type'] === "openid") {
|
||||||
if(!isset($data['options']['usegroups'])) {
|
if (!isset($data['options']['usegroups'])) {
|
||||||
$data['options']['usegroups'] = false;
|
$data['options']['usegroups'] = false;
|
||||||
|
|
||||||
$providerConfig[$providerId] = $data;
|
$providerConfig[$providerId] = $data;
|
||||||
|
|
||||||
$conf->merge(['authentication', 'providers'], $providerConfig);
|
$conf->merge(['authentication', 'providers'], $providerConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isset($data['options']['fieldmap'])) {
|
||||||
|
$data['options']['fieldmap'] = [
|
||||||
|
'id' => 'sub',
|
||||||
|
'login' => 'email',
|
||||||
|
'firstname' => 'given_name',
|
||||||
|
'lastname' => 'family_name',
|
||||||
|
'email' => 'email',
|
||||||
|
'groups' => 'group',
|
||||||
|
];
|
||||||
|
|
||||||
|
$providerConfig[$providerId] = $data;
|
||||||
|
|
||||||
|
$conf->merge(['authentication', 'providers'], $providerConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($data['options']['groupmask'])) {
|
||||||
|
$data['options']['groupmask'] = "/phraseanet_([^,]+)/i";
|
||||||
|
|
||||||
|
$providerConfig[$providerId] = $data;
|
||||||
|
|
||||||
|
$conf->merge(['authentication', 'providers'], $providerConfig);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -246,6 +246,14 @@ authentication:
|
|||||||
debug: false
|
debug: false
|
||||||
auto-logout: false
|
auto-logout: false
|
||||||
auto-connect-idp-name: null
|
auto-connect-idp-name: null
|
||||||
|
groupmask: "/phraseanet_([^,]+)/i"
|
||||||
|
fieldmap:
|
||||||
|
id: sub
|
||||||
|
login: email
|
||||||
|
firstname: given_name
|
||||||
|
lastname: family_name
|
||||||
|
email: email
|
||||||
|
groups: group
|
||||||
registration-fields:
|
registration-fields:
|
||||||
-
|
-
|
||||||
name: company
|
name: company
|
||||||
|
Reference in New Issue
Block a user