diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Serializer.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Serializer.pm
index 7a653150b..b498682f1 100644
--- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Serializer.pm
+++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/Serializer.pm
@@ -126,6 +126,8 @@ sub unserialize {
|oidcOPMetaDataJSON
|oidcOPMetaDataJWKS
|oidcOPMetaDataOptions
+ |oidcRPMetaDataExportedVars
+ |oidcRPMetaDataOptions
|openIdExportedVars
|persistentStorageOptions
|portalSkinRules
diff --git a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/SubAttributes.pm b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/SubAttributes.pm
index 91ed5817c..14f6759a7 100644
--- a/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/SubAttributes.pm
+++ b/lemonldap-ng-common/lib/Lemonldap/NG/Common/Conf/SubAttributes.pm
@@ -100,6 +100,27 @@ has 'oidcOPMetaDataOptionsTokenEndpointAuthMethod' => (
documentation => "OIDC OP scope",
);
+has 'oidcRPMetaDataExportedVars' => (
+ is => 'rw',
+ isa => 'HashRef',
+ default => sub { return { 'sub' => 'uid' }; },
+ documentation => "Exported vars for a RP",
+);
+
+has 'oidcRPMetaDataOptionsClientID' => (
+ is => 'rw',
+ isa => 'Str|Undef',
+ default => undef,
+ documentation => "OIDC RP client ID",
+);
+
+has 'oidcRPMetaDataOptionsClientSecret' => (
+ is => 'rw',
+ isa => 'Str|Undef',
+ default => undef,
+ documentation => "OIDC RP client Secret",
+);
+
## P
has 'post' => (
diff --git a/lemonldap-ng-manager/example/skins/default/js/manager.js b/lemonldap-ng-manager/example/skins/default/js/manager.js
index 4c531b8a2..bbc26f138 100644
--- a/lemonldap-ng-manager/example/skins/default/js/manager.js
+++ b/lemonldap-ng-manager/example/skins/default/js/manager.js
@@ -465,6 +465,7 @@ function display(div, title) {
$('#newpostr,#delpost').hide();
$('#newpostdatar,#delpostdata').hide();
$('#newoidcopb,#deloidcopb').hide();
+ $('#newoidcrpb,#deloidcrpb').hide();
// Resize (or hide) Help window
resizeHelp();
}
@@ -497,6 +498,11 @@ function oidcOPRoot(id) {
display('default', '');
$('#newoidcopb').show();
}
+function oidcRPRoot(id) {
+ currentId = id;
+ display('default', '');
+ $('#newoidcrpb').show();
+}
/* @function splitModuleAndOptions(string data)
* Split module and options from authentication or userDB string
* @return module, options
@@ -847,6 +853,17 @@ function oidcOPMetaData(id) {
}
$('#newoidcopb').show();
}
+function oidcRPMetaData(id) {
+ currentId = id;
+ $('#oidcRPMetaData').val(lmtext(id));
+ display('oidcRPMetaData', lmtext(id));
+ if ($('#li_' + myB64('/oidcRPMetaDataNode')).find('span').size() == 1) {
+ $('#deloidcrpb').hide();
+ } else {
+ $('#deloidcrpb').show();
+ }
+ $('#newoidcrpb').show();
+}
function samlService(id) {
currentId = id;
var t = lmdata(id).split(';');
@@ -1123,6 +1140,24 @@ function delOidcOp(id) {
oidcOPMetaData(id);
}
}
+function newOidcRp() {
+ var name = prompt(text4newOidcRp, 'rp-example');
+ if (!name) {
+ return false;
+ }
+ var rpId = 'li_' + myB64('/oidcRPMetaDataExportedVars/' + name);
+ simpleTreeCollection[0].newAjaxNodeIn($('#li_L29pZGNSUE1ldGFEYXRhTm9kZQ2'), rpId, name, scriptname + '?type=new&node=/oidcRPMetaDataNode/' + name, function(d, s) {
+ $('>span', s).attr('name', name).attr('help', 'default').attr('id', 'text_' + rpId).attr('onclick', 'oidcRPMetaData(\'' + rpId + '\')');
+ oidcRPMetaData(rpId);
+ });
+}
+function delOidcRp(id) {
+ var rpname = lmtext(id);
+ if (confirm('Delete ' + rpname + ' ?')) {
+ delKey(id);
+ oidcRPMetaData(id);
+ }
+}
var cfgAttrDone = 0;
function uploadConf(f) {
if (! (f == 1)) f = 0;
diff --git a/lemonldap-ng-manager/example/skins/default/manager.tpl b/lemonldap-ng-manager/example/skins/default/manager.tpl
index 1cf9dd1ef..708992913 100644
--- a/lemonldap-ng-manager/example/skins/default/manager.tpl
+++ b/lemonldap-ng-manager/example/skins/default/manager.tpl
@@ -53,6 +53,7 @@
var text4newCondition='';
var lang='';
var text4newOidcOp='';
+ var text4newOidcRp='';
//]]>
@@ -266,6 +267,16 @@
+
+
+
+
diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Uploader.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Uploader.pm
index 5daf1e67f..8c7d458a9 100644
--- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Uploader.pm
+++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Uploader.pm
@@ -43,6 +43,7 @@ sub confUpload {
my $catid;
my $postname;
my $opname;
+ my $rpname;
# 1. ANALYSE DATAS
@@ -117,6 +118,12 @@ s/^text_(NewID_)?li_([\w\/\+\=]+)(\d)(?:_\d+)?$/decode_base64($2.'='x $3)/e;
$opname = $name;
}
+ # Get OIDC RP name
+ if ( $id =~ /oidcRPMetaDataExportedVars\/([^\/]*)?$/ ) {
+ $self->lmLog( "Entering RP $name", 'debug' );
+ $rpname = $name;
+ }
+
# Set menu category and application flags
if ( $id =~ /applicationList/ ) {
if ( $value =~ /^(.*)?\|(.*)?\|(.*)?\|(.*)?\|(.*?)$/ ) {
@@ -139,7 +146,7 @@ s/^text_(NewID_)?li_([\w\/\+\=]+)(\d)(?:_\d+)?$/decode_base64($2.'='x $3)/e;
# Special case: avoid bug with node created from parent node
if ( $id =~
-/^(virtualHosts|samlIDPMetaDataNode|samlSPMetaDataNode|oidcOPMetaDataNode|generalParameters\/authParams\/choiceParams)/
+/^(virtualHosts|samlIDPMetaDataNode|samlSPMetaDataNode|oidcOPMetaDataNode|oidcRPMetaDataNode|generalParameters\/authParams\/choiceParams)/
)
{
$self->lmLog( "Special trigger for $id (attribute $name)",
@@ -168,6 +175,10 @@ s/^samlSPMetaDataNode\/([^\/]*)?.*/samlSPMetaDataExportedAttributes\/$1\/$name/;
$id =~
s/^oidcOPMetaDataNode\/([^\/]*)?.*/oidcOPMetaDataExportedVars\/$1\/$name/;
+ # OIDC RP attribute
+ $id =~
+s/^oidcRPMetaDataNode\/([^\/]*)?.*/oidcRPMetaDataExportedVars\/$1\/$name/;
+
# Authentication choice
$id =~
s/^generalParameters\/authParams\/choiceParams\/([^\/]*)?.*/authChoiceModules\/$name/;
@@ -213,13 +224,17 @@ s/^(samlSPMetaDataXML|samlSPMetaDataExportedAttributes|samlSPMetaDataOptions)\/(
$id =~
s/^(oidcOPMetaDataJSON|oidcOPMetaDataJWKS|oidcOPMetaDataExportedVars|oidcOPMetaDataOptions)\/([^\/]*)?\/(.*)$/$1\/$opname\/$3/;
+ # Set current OIDC RP name
+ $id =~
+s/^(oidcRPMetaDataExportedVars|oidcRPMetaDataOptions)\/([^\/]*)?\/(.*)$/$1\/$rpname\/$3/;
+
# Set current POST URL name
$id =~ s/^(post)\/([^\/]*)?\/(.*)$/$1\/$vhostname\/$postname/;
$self->lmLog( "id transformed into $id", 'debug' );
if ( $id =~
-/^(generalParameters|variables|virtualHosts|samlIDPMetaDataNode|samlSPMetaDataNode|oidcOPMetaDataNode)/
+/^(generalParameters|variables|virtualHosts|samlIDPMetaDataNode|samlSPMetaDataNode|oidcOPMetaDataNode|oidcRPMetaDataNode)/
)
{
$self->lmLog( "Ignoring attribute $name (id $id)", 'debug' );
diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_Struct.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_Struct.pm
index ee249460b..3a1dc0a17 100644
--- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_Struct.pm
+++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_Struct.pm
@@ -311,6 +311,31 @@ sub cstruct {
},
);
}
+ elsif ( $k1 =~ /^oidcRPMetaDataNode/i ) {
+ %$h = (
+ %$h,
+ oidcRPMetaDataNode => {
+ $k2 => {
+ _nodes =>
+ [qw(oidcRPMetaDataExportedVars oidcRPMetaDataOptions)],
+ oidcRPMetaDataExportedVars => {
+ _nodes =>
+ ["hash:/oidcRPMetaDataExportedVars/$k2:vars:btext"],
+ _js => 'hashRoot',
+ },
+ oidcRPMetaDataOptions => {
+ _nodes => [
+ qw(oidcRPMetaDataOptionsClientID oidcRPMetaDataOptionsClientSecret)
+ ],
+ oidcRPMetaDataOptionsClientID =>
+"text:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsClientID",
+ oidcRPMetaDataOptionsClientSecret =>
+"password:/oidcRPMetaDataOptions/$k2/oidcRPMetaDataOptionsClientSecret",
+ },
+ },
+ },
+ );
+ }
return $h;
}
@@ -322,7 +347,7 @@ sub struct {
my $self = shift;
return {
_nodes => [
- qw(n:generalParameters n:variables n:virtualHosts n:samlServiceMetaData n:samlIDPMetaDataNode n:samlSPMetaDataNode n:oidcServiceMetaData n:oidcOPMetaDataNode)
+ qw(n:generalParameters n:variables n:virtualHosts n:samlServiceMetaData n:samlIDPMetaDataNode n:samlSPMetaDataNode n:oidcServiceMetaData n:oidcOPMetaDataNode n:oidcRPMetaDataNode)
],
_help => 'default',
@@ -1573,6 +1598,15 @@ sub struct {
_js => 'oidcOPRoot',
},
+ oidcRPMetaDataNode => {
+ _nodes => [
+'nhash:/oidcRPMetaDataExportedVars:oidcRPMetaDataNode:oidcRPMetaData'
+ ],
+ _upload => ['/oidcRPMetaDataOptions'],
+ _help => 'oidcRP',
+ _js => 'oidcRPRoot',
+ },
+
};
}
@@ -2327,6 +2361,25 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
},
},
+ # OIDC RP
+ oidcRPMetaDataExportedVars => {
+ keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
+ keyMsgFail => 'Bad metadata name',
+ '*' => {
+ keyTest => qr/^\w([\w\-]*\w)?$/,
+ keyMsgFail => 'Bad attribute name',
+ test => sub { return 1; },
+ },
+ },
+ oidcRPMetaDataOptions => {
+ keyTest => qr/^[a-zA-Z](?:[\w\-\.]*\w)?$/,
+ keyMsgFail => 'Bad metadata name',
+ '*' => {
+ test => sub { return 1; },
+ keyTest => sub { return 1; },
+ },
+ },
+
};
}
## @method hashref subDefaultConf()
diff --git a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_i18n.pm b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_i18n.pm
index fcebc4bdf..84f1faf32 100644
--- a/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_i18n.pm
+++ b/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/_i18n.pm
@@ -284,77 +284,82 @@ sub en {
oidcOPMetaDataOptionsScope => 'Scope',
oidcOPMetaDataOptionsTokenEndpointAuthMethod =>
'Token endpoint authentication method',
- oidcParams => 'OpenID Connect parameters',
- oidcRPCallbackGetParam => 'Callback GET parameter',
- oidcRPStateTimeout => 'State session timeout',
- oidcServiceMetaData => 'OpenID Connect Service',
- oidcServiceMetaDataAuthorizeURI => 'Autorization',
- oidcServiceMetaDataEndPoints => 'End points',
- oidcServiceMetaDataIssuer => 'Issuer identifier',
- oidcServiceMetaDataTokenURI => 'Token',
- openIdAttr => 'OpenID login',
- openIdAuthnLevel => 'Authentication level',
- openIdExportedVars => 'Exported variables',
- openIdIDPList => 'Authorizated domains',
- openIdIssuerSecret => 'Secret token',
- openIdParams => 'OpenID parameters',
- openIdSecret => 'Secret token',
- openIdSreg => 'SREG mapping',
- openIdSreg_fullname => 'Full name',
- openIdSreg_nickname => 'Nick name',
- openIdSreg_language => 'Language',
- openIdSreg_postcode => 'Postal code',
- openIdSreg_timezone => 'Timezone',
- openIdSreg_country => 'Country',
- openIdSreg_gender => 'Gender',
- openIdSreg_email => 'Email',
- openIdSreg_dob => 'Date of birth',
- openIdSPList => 'Authorizated domains',
- passwordDB => 'Password module',
- passwordManagement => 'Password management',
- persistentSessions => 'Persistent sessions',
- persistentStorage => 'Apache::Session module',
- persistentStorageOptions => 'Apache::Session module parameters',
- port => 'Port',
- portal => 'URL',
- portalAntiFrame => 'Anti frame protection',
- portalAutocomplete => 'Auto complete',
- portalButtons => 'Buttons on login page',
- portalCaptcha => 'Captcha',
- portalCheckLogins => 'Check last logins',
- portalCustomization => 'Customization',
- portalDisplayAppslist => 'Applications list',
- portalDisplayChangePassword => 'Password change',
- portalDisplayLoginHistory => 'Login History',
- portalDisplayLogout => 'Logout',
- portalDisplayRegister => 'Register new account',
- portalDisplayResetPassword => 'Reset password',
- portalForceAuthn => 'Force authentication',
- portalMenu => 'Menu',
- portalModules => 'Modules activation',
- portalOpenLinkInNewWindow => 'New window',
- portalOther => 'Other',
- portalParams => 'Portal',
- portalPingInterval => 'Ping Interval',
- portalRedirection => 'Portal redirections',
- portalRequireOldPassword => 'Require old password',
- portalSkin => 'Default Skin',
- portalSkinBackground => 'Background image',
- portalSkinRules => 'Skin display rules',
- portalUserAttr => 'User attribute',
- post => 'Form replay',
- proxyParams => 'Proxy parameters',
- purgeNotification => 'Delete notification definitely',
- radiusAuthnLevel => 'Authentication level',
- radiusParams => 'Radius parameters',
- radiusSecret => 'Shared secret',
- radiusServer => 'Server hostname',
- randomPasswordRegexp => 'Regexp for password generation',
- redirection => 'Handler redirections',
- register => 'Register new account',
- registerConfirmSubject => 'Subject for confirmation mail',
- registerDB => 'Module',
- registerDoneSubject => 'Subject for done mail',
+ oidcParams => 'OpenID Connect parameters',
+ oidcRPCallbackGetParam => 'Callback GET parameter',
+ oidcRPMetaDataExportedVars => 'Exported attributes',
+ oidcRPMetaDataNode => 'OpenID Connect Relaying Parties',
+ oidcRPMetaDataOptions => 'Options',
+ oidcRPMetaDataOptionsClientID => 'Client ID',
+ oidcRPMetaDataOptionsClientSecret => 'Client secret',
+ oidcRPStateTimeout => 'State session timeout',
+ oidcServiceMetaData => 'OpenID Connect Service',
+ oidcServiceMetaDataAuthorizeURI => 'Autorization',
+ oidcServiceMetaDataEndPoints => 'End points',
+ oidcServiceMetaDataIssuer => 'Issuer identifier',
+ oidcServiceMetaDataTokenURI => 'Token',
+ openIdAttr => 'OpenID login',
+ openIdAuthnLevel => 'Authentication level',
+ openIdExportedVars => 'Exported variables',
+ openIdIDPList => 'Authorizated domains',
+ openIdIssuerSecret => 'Secret token',
+ openIdParams => 'OpenID parameters',
+ openIdSecret => 'Secret token',
+ openIdSreg => 'SREG mapping',
+ openIdSreg_fullname => 'Full name',
+ openIdSreg_nickname => 'Nick name',
+ openIdSreg_language => 'Language',
+ openIdSreg_postcode => 'Postal code',
+ openIdSreg_timezone => 'Timezone',
+ openIdSreg_country => 'Country',
+ openIdSreg_gender => 'Gender',
+ openIdSreg_email => 'Email',
+ openIdSreg_dob => 'Date of birth',
+ openIdSPList => 'Authorizated domains',
+ passwordDB => 'Password module',
+ passwordManagement => 'Password management',
+ persistentSessions => 'Persistent sessions',
+ persistentStorage => 'Apache::Session module',
+ persistentStorageOptions => 'Apache::Session module parameters',
+ port => 'Port',
+ portal => 'URL',
+ portalAntiFrame => 'Anti frame protection',
+ portalAutocomplete => 'Auto complete',
+ portalButtons => 'Buttons on login page',
+ portalCaptcha => 'Captcha',
+ portalCheckLogins => 'Check last logins',
+ portalCustomization => 'Customization',
+ portalDisplayAppslist => 'Applications list',
+ portalDisplayChangePassword => 'Password change',
+ portalDisplayLoginHistory => 'Login History',
+ portalDisplayLogout => 'Logout',
+ portalDisplayRegister => 'Register new account',
+ portalDisplayResetPassword => 'Reset password',
+ portalForceAuthn => 'Force authentication',
+ portalMenu => 'Menu',
+ portalModules => 'Modules activation',
+ portalOpenLinkInNewWindow => 'New window',
+ portalOther => 'Other',
+ portalParams => 'Portal',
+ portalPingInterval => 'Ping Interval',
+ portalRedirection => 'Portal redirections',
+ portalRequireOldPassword => 'Require old password',
+ portalSkin => 'Default Skin',
+ portalSkinBackground => 'Background image',
+ portalSkinRules => 'Skin display rules',
+ portalUserAttr => 'User attribute',
+ post => 'Form replay',
+ proxyParams => 'Proxy parameters',
+ purgeNotification => 'Delete notification definitely',
+ radiusAuthnLevel => 'Authentication level',
+ radiusParams => 'Radius parameters',
+ radiusSecret => 'Shared secret',
+ radiusServer => 'Server hostname',
+ randomPasswordRegexp => 'Regexp for password generation',
+ redirection => 'Handler redirections',
+ register => 'Register new account',
+ registerConfirmSubject => 'Subject for confirmation mail',
+ registerDB => 'Module',
+ registerDoneSubject => 'Subject for done mail',
registerTimeout => 'Validity time of a register request',
registerUrl => 'Page URL',
reloadUrls => 'Configuration reload',
@@ -828,36 +833,41 @@ sub fr {
oidcOPMetaDataOptionsScope => 'Étendue',
oidcOPMetaDataOptionsTokenEndpointAuthMethod =>
'Méthode d\'authentification pour l\'accès aux jetons',
- oidcParams => 'Paramètres OpenID Connect',
- oidcRPCallbackGetParam => 'Paramètre GET callback',
- oidcRPStateTimeout => 'Durée d\'une session state',
- oidcServiceMetaData => "Service OpenID Connect",
- oidcServiceMetaDataAuthorizeURI => "Autorisation",
- oidcServiceMetaDataEndPoints => "Points d'accès",
- oidcServiceMetaDataIssuer => "Identifiant du fournisseur",
- oidcServiceMetaDataTokenURI => "Jeton",
- openIdAttr => 'Identifiant OpenID',
- openIdAuthnLevel => 'Niveau d\'authentification',
- openIdExportedVars => 'Variables exportées',
- openIdIDPList => 'Domaines autorisés',
- openIdIssuerSecret => 'Jeton secret',
- openIdParams => 'Paramètres OpenID',
- openIdSecret => 'Jeton secret',
- openIdSreg => 'Associations SREG',
- openIdSreg_fullname => 'Nom complet',
- openIdSreg_nickname => 'Surnom',
- openIdSreg_language => 'Langage',
- openIdSreg_postcode => 'Code postal',
- openIdSreg_timezone => 'Zone horaire',
- openIdSreg_country => 'Pays',
- openIdSreg_gender => 'Genre',
- openIdSreg_email => 'Email',
- openIdSreg_dob => 'Date de naissance',
- openIdSPList => 'Domaines autorisés',
- passwordDB => 'Module de mot de passe',
- passwordManagement => 'Gestion des mots de passe',
- persistentSessions => 'Sessions persistantes',
- persistentStorage => 'Module Apache::Session',
+ oidcParams => 'Paramètres OpenID Connect',
+ oidcRPCallbackGetParam => 'Paramètre GET callback',
+ oidcRPMetaDataExportedVars => 'Attributs exportés',
+ oidcRPMetaDataNode => 'Relais OpenID Connect',
+ oidcRPMetaDataOptions => 'Options',
+ oidcRPMetaDataOptionsClientID => 'Identifiant',
+ oidcRPMetaDataOptionsClientSecret => 'Mot de passe',
+ oidcRPStateTimeout => 'Durée d\'une session state',
+ oidcServiceMetaData => "Service OpenID Connect",
+ oidcServiceMetaDataAuthorizeURI => "Autorisation",
+ oidcServiceMetaDataEndPoints => "Points d'accès",
+ oidcServiceMetaDataIssuer => "Identifiant du fournisseur",
+ oidcServiceMetaDataTokenURI => "Jeton",
+ openIdAttr => 'Identifiant OpenID',
+ openIdAuthnLevel => 'Niveau d\'authentification',
+ openIdExportedVars => 'Variables exportées',
+ openIdIDPList => 'Domaines autorisés',
+ openIdIssuerSecret => 'Jeton secret',
+ openIdParams => 'Paramètres OpenID',
+ openIdSecret => 'Jeton secret',
+ openIdSreg => 'Associations SREG',
+ openIdSreg_fullname => 'Nom complet',
+ openIdSreg_nickname => 'Surnom',
+ openIdSreg_language => 'Langage',
+ openIdSreg_postcode => 'Code postal',
+ openIdSreg_timezone => 'Zone horaire',
+ openIdSreg_country => 'Pays',
+ openIdSreg_gender => 'Genre',
+ openIdSreg_email => 'Email',
+ openIdSreg_dob => 'Date de naissance',
+ openIdSPList => 'Domaines autorisés',
+ passwordDB => 'Module de mot de passe',
+ passwordManagement => 'Gestion des mots de passe',
+ persistentSessions => 'Sessions persistantes',
+ persistentStorage => 'Module Apache::Session',
persistentStorageOptions => 'Paramètres du module Apache::Session',
port => 'Port',
portal => 'URL',