OpenID Connect relaying parties in Manager (#184)

This commit is contained in:
Clément Oudot 2015-01-28 16:28:41 +00:00
parent 70281de82d
commit d2423d1a6c
7 changed files with 251 additions and 104 deletions

View File

@ -126,6 +126,8 @@ sub unserialize {
|oidcOPMetaDataJSON |oidcOPMetaDataJSON
|oidcOPMetaDataJWKS |oidcOPMetaDataJWKS
|oidcOPMetaDataOptions |oidcOPMetaDataOptions
|oidcRPMetaDataExportedVars
|oidcRPMetaDataOptions
|openIdExportedVars |openIdExportedVars
|persistentStorageOptions |persistentStorageOptions
|portalSkinRules |portalSkinRules

View File

@ -100,6 +100,27 @@ has 'oidcOPMetaDataOptionsTokenEndpointAuthMethod' => (
documentation => "OIDC OP scope", 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 ## P
has 'post' => ( has 'post' => (

View File

@ -465,6 +465,7 @@ function display(div, title) {
$('#newpostr,#delpost').hide(); $('#newpostr,#delpost').hide();
$('#newpostdatar,#delpostdata').hide(); $('#newpostdatar,#delpostdata').hide();
$('#newoidcopb,#deloidcopb').hide(); $('#newoidcopb,#deloidcopb').hide();
$('#newoidcrpb,#deloidcrpb').hide();
// Resize (or hide) Help window // Resize (or hide) Help window
resizeHelp(); resizeHelp();
} }
@ -497,6 +498,11 @@ function oidcOPRoot(id) {
display('default', ''); display('default', '');
$('#newoidcopb').show(); $('#newoidcopb').show();
} }
function oidcRPRoot(id) {
currentId = id;
display('default', '');
$('#newoidcrpb').show();
}
/* @function splitModuleAndOptions(string data) /* @function splitModuleAndOptions(string data)
* Split module and options from authentication or userDB string * Split module and options from authentication or userDB string
* @return module, options * @return module, options
@ -847,6 +853,17 @@ function oidcOPMetaData(id) {
} }
$('#newoidcopb').show(); $('#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) { function samlService(id) {
currentId = id; currentId = id;
var t = lmdata(id).split(';'); var t = lmdata(id).split(';');
@ -1123,6 +1140,24 @@ function delOidcOp(id) {
oidcOPMetaData(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; var cfgAttrDone = 0;
function uploadConf(f) { function uploadConf(f) {
if (! (f == 1)) f = 0; if (! (f == 1)) f = 0;

View File

@ -53,6 +53,7 @@
var text4newCondition='<lang en="New Condition" fr="Nouvelle Condition" />'; var text4newCondition='<lang en="New Condition" fr="Nouvelle Condition" />';
var lang='<TMPL_VAR NAME="LANG">'; var lang='<TMPL_VAR NAME="LANG">';
var text4newOidcOp='<lang en="Provider name" fr="Nom du fournisseur" />'; var text4newOidcOp='<lang en="Provider name" fr="Nom du fournisseur" />';
var text4newOidcRp='<lang en="Relaying party name" fr="Nom du relai" />';
//]]></script> //]]></script>
<script src="<TMPL_VAR NAME="DIR">/js/manager.js" type="text/JavaScript"></script> <script src="<TMPL_VAR NAME="DIR">/js/manager.js" type="text/JavaScript"></script>
</head> </head>
@ -266,6 +267,16 @@
<lang en="Delete provider" fr="Supprimer le fournisseur" /> <lang en="Delete provider" fr="Supprimer le fournisseur" />
</button> </button>
<button id="newoidcrpb" style="display:none;" onclick="newOidcRp();return false;" class="btn btn-success">
<i class=" glyphicon glyphicon-plus-sign"></i>
<lang en="New relaying party" fr="Nouveau relai" />
</button>
<button id="deloidcrpb" style="display:none;" onclick="delOidcRp(currentId);" class="btn btn-danger">
<i class=" glyphicon glyphicon-minus-sign"></i>
<lang en="Delete relaying party" fr="Supprimer le relai" />
</button>
</div> </div>
<!-- Buttons --> <!-- Buttons -->

View File

@ -43,6 +43,7 @@ sub confUpload {
my $catid; my $catid;
my $postname; my $postname;
my $opname; my $opname;
my $rpname;
# 1. ANALYSE DATAS # 1. ANALYSE DATAS
@ -117,6 +118,12 @@ s/^text_(NewID_)?li_([\w\/\+\=]+)(\d)(?:_\d+)?$/decode_base64($2.'='x $3)/e;
$opname = $name; $opname = $name;
} }
# Get OIDC RP name
if ( $id =~ /oidcRPMetaDataExportedVars\/([^\/]*)?$/ ) {
$self->lmLog( "Entering RP $name", 'debug' );
$rpname = $name;
}
# Set menu category and application flags # Set menu category and application flags
if ( $id =~ /applicationList/ ) { if ( $id =~ /applicationList/ ) {
if ( $value =~ /^(.*)?\|(.*)?\|(.*)?\|(.*)?\|(.*?)$/ ) { 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 # Special case: avoid bug with node created from parent node
if ( $id =~ 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)", $self->lmLog( "Special trigger for $id (attribute $name)",
@ -168,6 +175,10 @@ s/^samlSPMetaDataNode\/([^\/]*)?.*/samlSPMetaDataExportedAttributes\/$1\/$name/;
$id =~ $id =~
s/^oidcOPMetaDataNode\/([^\/]*)?.*/oidcOPMetaDataExportedVars\/$1\/$name/; s/^oidcOPMetaDataNode\/([^\/]*)?.*/oidcOPMetaDataExportedVars\/$1\/$name/;
# OIDC RP attribute
$id =~
s/^oidcRPMetaDataNode\/([^\/]*)?.*/oidcRPMetaDataExportedVars\/$1\/$name/;
# Authentication choice # Authentication choice
$id =~ $id =~
s/^generalParameters\/authParams\/choiceParams\/([^\/]*)?.*/authChoiceModules\/$name/; s/^generalParameters\/authParams\/choiceParams\/([^\/]*)?.*/authChoiceModules\/$name/;
@ -213,13 +224,17 @@ s/^(samlSPMetaDataXML|samlSPMetaDataExportedAttributes|samlSPMetaDataOptions)\/(
$id =~ $id =~
s/^(oidcOPMetaDataJSON|oidcOPMetaDataJWKS|oidcOPMetaDataExportedVars|oidcOPMetaDataOptions)\/([^\/]*)?\/(.*)$/$1\/$opname\/$3/; 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 # Set current POST URL name
$id =~ s/^(post)\/([^\/]*)?\/(.*)$/$1\/$vhostname\/$postname/; $id =~ s/^(post)\/([^\/]*)?\/(.*)$/$1\/$vhostname\/$postname/;
$self->lmLog( "id transformed into $id", 'debug' ); $self->lmLog( "id transformed into $id", 'debug' );
if ( $id =~ if ( $id =~
/^(generalParameters|variables|virtualHosts|samlIDPMetaDataNode|samlSPMetaDataNode|oidcOPMetaDataNode)/ /^(generalParameters|variables|virtualHosts|samlIDPMetaDataNode|samlSPMetaDataNode|oidcOPMetaDataNode|oidcRPMetaDataNode)/
) )
{ {
$self->lmLog( "Ignoring attribute $name (id $id)", 'debug' ); $self->lmLog( "Ignoring attribute $name (id $id)", 'debug' );

View File

@ -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; return $h;
} }
@ -322,7 +347,7 @@ sub struct {
my $self = shift; my $self = shift;
return { return {
_nodes => [ _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', _help => 'default',
@ -1573,6 +1598,15 @@ sub struct {
_js => 'oidcOPRoot', _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() ## @method hashref subDefaultConf()

View File

@ -284,77 +284,82 @@ sub en {
oidcOPMetaDataOptionsScope => 'Scope', oidcOPMetaDataOptionsScope => 'Scope',
oidcOPMetaDataOptionsTokenEndpointAuthMethod => oidcOPMetaDataOptionsTokenEndpointAuthMethod =>
'Token endpoint authentication method', 'Token endpoint authentication method',
oidcParams => 'OpenID Connect parameters', oidcParams => 'OpenID Connect parameters',
oidcRPCallbackGetParam => 'Callback GET parameter', oidcRPCallbackGetParam => 'Callback GET parameter',
oidcRPStateTimeout => 'State session timeout', oidcRPMetaDataExportedVars => 'Exported attributes',
oidcServiceMetaData => 'OpenID Connect Service', oidcRPMetaDataNode => 'OpenID Connect Relaying Parties',
oidcServiceMetaDataAuthorizeURI => 'Autorization', oidcRPMetaDataOptions => 'Options',
oidcServiceMetaDataEndPoints => 'End points', oidcRPMetaDataOptionsClientID => 'Client ID',
oidcServiceMetaDataIssuer => 'Issuer identifier', oidcRPMetaDataOptionsClientSecret => 'Client secret',
oidcServiceMetaDataTokenURI => 'Token', oidcRPStateTimeout => 'State session timeout',
openIdAttr => 'OpenID login', oidcServiceMetaData => 'OpenID Connect Service',
openIdAuthnLevel => 'Authentication level', oidcServiceMetaDataAuthorizeURI => 'Autorization',
openIdExportedVars => 'Exported variables', oidcServiceMetaDataEndPoints => 'End points',
openIdIDPList => 'Authorizated domains', oidcServiceMetaDataIssuer => 'Issuer identifier',
openIdIssuerSecret => 'Secret token', oidcServiceMetaDataTokenURI => 'Token',
openIdParams => 'OpenID parameters', openIdAttr => 'OpenID login',
openIdSecret => 'Secret token', openIdAuthnLevel => 'Authentication level',
openIdSreg => 'SREG mapping', openIdExportedVars => 'Exported variables',
openIdSreg_fullname => 'Full name', openIdIDPList => 'Authorizated domains',
openIdSreg_nickname => 'Nick name', openIdIssuerSecret => 'Secret token',
openIdSreg_language => 'Language', openIdParams => 'OpenID parameters',
openIdSreg_postcode => 'Postal code', openIdSecret => 'Secret token',
openIdSreg_timezone => 'Timezone', openIdSreg => 'SREG mapping',
openIdSreg_country => 'Country', openIdSreg_fullname => 'Full name',
openIdSreg_gender => 'Gender', openIdSreg_nickname => 'Nick name',
openIdSreg_email => 'Email', openIdSreg_language => 'Language',
openIdSreg_dob => 'Date of birth', openIdSreg_postcode => 'Postal code',
openIdSPList => 'Authorizated domains', openIdSreg_timezone => 'Timezone',
passwordDB => 'Password module', openIdSreg_country => 'Country',
passwordManagement => 'Password management', openIdSreg_gender => 'Gender',
persistentSessions => 'Persistent sessions', openIdSreg_email => 'Email',
persistentStorage => 'Apache::Session module', openIdSreg_dob => 'Date of birth',
persistentStorageOptions => 'Apache::Session module parameters', openIdSPList => 'Authorizated domains',
port => 'Port', passwordDB => 'Password module',
portal => 'URL', passwordManagement => 'Password management',
portalAntiFrame => 'Anti frame protection', persistentSessions => 'Persistent sessions',
portalAutocomplete => 'Auto complete', persistentStorage => 'Apache::Session module',
portalButtons => 'Buttons on login page', persistentStorageOptions => 'Apache::Session module parameters',
portalCaptcha => 'Captcha', port => 'Port',
portalCheckLogins => 'Check last logins', portal => 'URL',
portalCustomization => 'Customization', portalAntiFrame => 'Anti frame protection',
portalDisplayAppslist => 'Applications list', portalAutocomplete => 'Auto complete',
portalDisplayChangePassword => 'Password change', portalButtons => 'Buttons on login page',
portalDisplayLoginHistory => 'Login History', portalCaptcha => 'Captcha',
portalDisplayLogout => 'Logout', portalCheckLogins => 'Check last logins',
portalDisplayRegister => 'Register new account', portalCustomization => 'Customization',
portalDisplayResetPassword => 'Reset password', portalDisplayAppslist => 'Applications list',
portalForceAuthn => 'Force authentication', portalDisplayChangePassword => 'Password change',
portalMenu => 'Menu', portalDisplayLoginHistory => 'Login History',
portalModules => 'Modules activation', portalDisplayLogout => 'Logout',
portalOpenLinkInNewWindow => 'New window', portalDisplayRegister => 'Register new account',
portalOther => 'Other', portalDisplayResetPassword => 'Reset password',
portalParams => 'Portal', portalForceAuthn => 'Force authentication',
portalPingInterval => 'Ping Interval', portalMenu => 'Menu',
portalRedirection => 'Portal redirections', portalModules => 'Modules activation',
portalRequireOldPassword => 'Require old password', portalOpenLinkInNewWindow => 'New window',
portalSkin => 'Default Skin', portalOther => 'Other',
portalSkinBackground => 'Background image', portalParams => 'Portal',
portalSkinRules => 'Skin display rules', portalPingInterval => 'Ping Interval',
portalUserAttr => 'User attribute', portalRedirection => 'Portal redirections',
post => 'Form replay', portalRequireOldPassword => 'Require old password',
proxyParams => 'Proxy parameters', portalSkin => 'Default Skin',
purgeNotification => 'Delete notification definitely', portalSkinBackground => 'Background image',
radiusAuthnLevel => 'Authentication level', portalSkinRules => 'Skin display rules',
radiusParams => 'Radius parameters', portalUserAttr => 'User attribute',
radiusSecret => 'Shared secret', post => 'Form replay',
radiusServer => 'Server hostname', proxyParams => 'Proxy parameters',
randomPasswordRegexp => 'Regexp for password generation', purgeNotification => 'Delete notification definitely',
redirection => 'Handler redirections', radiusAuthnLevel => 'Authentication level',
register => 'Register new account', radiusParams => 'Radius parameters',
registerConfirmSubject => 'Subject for confirmation mail', radiusSecret => 'Shared secret',
registerDB => 'Module', radiusServer => 'Server hostname',
registerDoneSubject => 'Subject for done mail', 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', registerTimeout => 'Validity time of a register request',
registerUrl => 'Page URL', registerUrl => 'Page URL',
reloadUrls => 'Configuration reload', reloadUrls => 'Configuration reload',
@ -828,36 +833,41 @@ sub fr {
oidcOPMetaDataOptionsScope => 'Étendue', oidcOPMetaDataOptionsScope => 'Étendue',
oidcOPMetaDataOptionsTokenEndpointAuthMethod => oidcOPMetaDataOptionsTokenEndpointAuthMethod =>
'Méthode d\'authentification pour l\'accès aux jetons', 'Méthode d\'authentification pour l\'accès aux jetons',
oidcParams => 'Paramètres OpenID Connect', oidcParams => 'Paramètres OpenID Connect',
oidcRPCallbackGetParam => 'Paramètre GET callback', oidcRPCallbackGetParam => 'Paramètre GET callback',
oidcRPStateTimeout => 'Durée d\'une session state', oidcRPMetaDataExportedVars => 'Attributs exportés',
oidcServiceMetaData => "Service OpenID Connect", oidcRPMetaDataNode => 'Relais OpenID Connect',
oidcServiceMetaDataAuthorizeURI => "Autorisation", oidcRPMetaDataOptions => 'Options',
oidcServiceMetaDataEndPoints => "Points d'accès", oidcRPMetaDataOptionsClientID => 'Identifiant',
oidcServiceMetaDataIssuer => "Identifiant du fournisseur", oidcRPMetaDataOptionsClientSecret => 'Mot de passe',
oidcServiceMetaDataTokenURI => "Jeton", oidcRPStateTimeout => 'Durée d\'une session state',
openIdAttr => 'Identifiant OpenID', oidcServiceMetaData => "Service OpenID Connect",
openIdAuthnLevel => 'Niveau d\'authentification', oidcServiceMetaDataAuthorizeURI => "Autorisation",
openIdExportedVars => 'Variables exportées', oidcServiceMetaDataEndPoints => "Points d'accès",
openIdIDPList => 'Domaines autorisés', oidcServiceMetaDataIssuer => "Identifiant du fournisseur",
openIdIssuerSecret => 'Jeton secret', oidcServiceMetaDataTokenURI => "Jeton",
openIdParams => 'Paramètres OpenID', openIdAttr => 'Identifiant OpenID',
openIdSecret => 'Jeton secret', openIdAuthnLevel => 'Niveau d\'authentification',
openIdSreg => 'Associations SREG', openIdExportedVars => 'Variables exportées',
openIdSreg_fullname => 'Nom complet', openIdIDPList => 'Domaines autorisés',
openIdSreg_nickname => 'Surnom', openIdIssuerSecret => 'Jeton secret',
openIdSreg_language => 'Langage', openIdParams => 'Paramètres OpenID',
openIdSreg_postcode => 'Code postal', openIdSecret => 'Jeton secret',
openIdSreg_timezone => 'Zone horaire', openIdSreg => 'Associations SREG',
openIdSreg_country => 'Pays', openIdSreg_fullname => 'Nom complet',
openIdSreg_gender => 'Genre', openIdSreg_nickname => 'Surnom',
openIdSreg_email => 'Email', openIdSreg_language => 'Langage',
openIdSreg_dob => 'Date de naissance', openIdSreg_postcode => 'Code postal',
openIdSPList => 'Domaines autorisés', openIdSreg_timezone => 'Zone horaire',
passwordDB => 'Module de mot de passe', openIdSreg_country => 'Pays',
passwordManagement => 'Gestion des mots de passe', openIdSreg_gender => 'Genre',
persistentSessions => 'Sessions persistantes', openIdSreg_email => 'Email',
persistentStorage => 'Module Apache::Session', 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', persistentStorageOptions => 'Paramètres du module Apache::Session',
port => 'Port', port => 'Port',
portal => 'URL', portal => 'URL',