SAML in progress (#595)
This commit is contained in:
parent
b1f2ac6a73
commit
fb741f9bea
|
@ -361,6 +361,7 @@ t/90-translations.t
|
||||||
t/99-pod.t
|
t/99-pod.t
|
||||||
t/lmConf-1.js
|
t/lmConf-1.js
|
||||||
t/sessions/lock/.exists
|
t/sessions/lock/.exists
|
||||||
|
t/sessions/saml/lock/.exists
|
||||||
t/sessions2/6e30af4ffa5689b3e49a104d1b160d316db2b2161a0f45776994eed19dbdc101
|
t/sessions2/6e30af4ffa5689b3e49a104d1b160d316db2b2161a0f45776994eed19dbdc101
|
||||||
t/sessions2/lock/Apache-Session-6e30af4ffa5689b3e49a104d1b160d316db2b2161a0f45776994eed19dbdc101.lock
|
t/sessions2/lock/Apache-Session-6e30af4ffa5689b3e49a104d1b160d316db2b2161a0f45776994eed19dbdc101.lock
|
||||||
t/test-lib.pm
|
t/test-lib.pm
|
||||||
|
|
|
@ -60,55 +60,52 @@ sub display {
|
||||||
}
|
}
|
||||||
|
|
||||||
# 1. Good authentication
|
# 1. Good authentication
|
||||||
|
|
||||||
|
# 1.1 Image mode
|
||||||
|
if ( $req->{error} == PE_IMG_OK || $req->{error} == PE_IMG_NOK ) {
|
||||||
|
$self->lmLog( 'Request for file', 'debug' );
|
||||||
|
return staticFile( "common/"
|
||||||
|
. ( $req->{error} == PE_IMG_OK ? 'ok.png' : 'warning.png' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1.2 Case : there is a message to display
|
||||||
|
elsif ( my $info = $req->info() ) {
|
||||||
|
$skinfile = 'info';
|
||||||
|
%templateParams = (
|
||||||
|
AUTH_ERROR_TYPE => $req->error_type,
|
||||||
|
MSG => $info,
|
||||||
|
URL => $req->{urldc},
|
||||||
|
HIDDEN_INPUTS => $self->buildHiddenForm(),
|
||||||
|
ACTIVE_TIMER => $self->conf->{activeTimer},
|
||||||
|
FORM_METHOD => $self->conf->{infoFormMethod},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1.3 Redirection
|
||||||
|
elsif ( $req->{error} == PE_REDIRECT ) {
|
||||||
|
$skinfile = "redirect";
|
||||||
|
%templateParams = (
|
||||||
|
URL => $req->{urldc},
|
||||||
|
HIDDEN_INPUTS => $self->buildHiddenForm($req),
|
||||||
|
FORM_METHOD => $req->datas->{redirectFormMethod} || 'get',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1.4 Case : display menu
|
||||||
elsif ( $req->error == PE_OK ) {
|
elsif ( $req->error == PE_OK ) {
|
||||||
|
|
||||||
# 1.1 Image mode
|
$skinfile = 'menu';
|
||||||
if ( $req->{error} == PE_IMG_OK || $req->{error} == PE_IMG_NOK ) {
|
|
||||||
$self->lmLog( 'Request for file', 'debug' );
|
|
||||||
return staticFile( "common/"
|
|
||||||
. ( $req->{error} == PE_IMG_OK ? 'ok.png' : 'warning.png' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
# 1.2 Case : there is a message to display
|
#utf8::decode($auth_user);
|
||||||
elsif ( my $info = $req->info() ) {
|
|
||||||
$skinfile = 'info';
|
|
||||||
%templateParams = (
|
|
||||||
AUTH_ERROR_TYPE => $req->error_type,
|
|
||||||
MSG => $info,
|
|
||||||
URL => $req->{urldc},
|
|
||||||
HIDDEN_INPUTS => $self->buildHiddenForm(),
|
|
||||||
ACTIVE_TIMER => $self->conf->{activeTimer},
|
|
||||||
FORM_METHOD => $self->conf->{infoFormMethod},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
# 1.3 Redirection
|
%templateParams = (
|
||||||
elsif ( $req->{error} == PE_REDIRECT ) {
|
AUTH_USER => $req->{sessionInfo}->{ $self->conf->{portalUserAttr} },
|
||||||
$skinfile = "redirect";
|
NEWWINDOW => $self->conf->{portalOpenLinkInNewWindow},
|
||||||
%templateParams = (
|
LOGOUT_URL => $self->conf->{portal} . "?logout=1",
|
||||||
URL => $req->{urldc},
|
APPSLIST_ORDER => $req->{sessionInfo}->{'appsListOrder'},
|
||||||
HIDDEN_INPUTS => $self->buildHiddenForm(),
|
PING => $self->conf->{portalPingInterval},
|
||||||
FORM_METHOD => $req->datas->{redirectFormMethod} || 'get',
|
$self->menu->params($req),
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
# 1.4 Case : display menu
|
|
||||||
else {
|
|
||||||
|
|
||||||
$skinfile = 'menu';
|
|
||||||
|
|
||||||
#utf8::decode($auth_user);
|
|
||||||
|
|
||||||
%templateParams = (
|
|
||||||
AUTH_USER =>
|
|
||||||
$req->{sessionInfo}->{ $self->conf->{portalUserAttr} },
|
|
||||||
NEWWINDOW => $self->conf->{portalOpenLinkInNewWindow},
|
|
||||||
LOGOUT_URL => $self->conf->{portal} . "?logout=1",
|
|
||||||
APPSLIST_ORDER => $req->{sessionInfo}->{'appsListOrder'},
|
|
||||||
PING => $self->conf->{portalPingInterval},
|
|
||||||
$self->menu->params($req),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# 2. Authentication not complete
|
# 2. Authentication not complete
|
||||||
|
@ -120,7 +117,7 @@ sub display {
|
||||||
%templateParams = (
|
%templateParams = (
|
||||||
AUTH_ERROR_TYPE => $req->error_type,
|
AUTH_ERROR_TYPE => $req->error_type,
|
||||||
NOTIFICATION => $notif,
|
NOTIFICATION => $notif,
|
||||||
HIDDEN_INPUTS => $self->buildHiddenForm(),
|
HIDDEN_INPUTS => $self->buildHiddenForm($req),
|
||||||
AUTH_URL => $req->{datas}->{_url},
|
AUTH_URL => $req->{datas}->{_url},
|
||||||
CHOICE_PARAM => $self->conf->{authChoiceParam},
|
CHOICE_PARAM => $self->conf->{authChoiceParam},
|
||||||
CHOICE_VALUE => $req->{_authChoice},
|
CHOICE_VALUE => $req->{_authChoice},
|
||||||
|
@ -136,7 +133,7 @@ sub display {
|
||||||
AUTH_ERROR_TYPE => $req->error_type,
|
AUTH_ERROR_TYPE => $req->error_type,
|
||||||
AUTH_URL => $req->{datas}->{_url},
|
AUTH_URL => $req->{datas}->{_url},
|
||||||
MSG => $req->info,
|
MSG => $req->info,
|
||||||
HIDDEN_INPUTS => $self->buildHiddenForm(),
|
HIDDEN_INPUTS => $self->buildHiddenForm($req),
|
||||||
ACTIVE_TIMER => $self->conf->{activeTimer},
|
ACTIVE_TIMER => $self->conf->{activeTimer},
|
||||||
FORM_METHOD => $self->conf->{confirmFormMethod},
|
FORM_METHOD => $self->conf->{confirmFormMethod},
|
||||||
CHOICE_PARAM => $self->conf->{authChoiceParam},
|
CHOICE_PARAM => $self->conf->{authChoiceParam},
|
||||||
|
@ -158,7 +155,7 @@ sub display {
|
||||||
AUTH_ERROR_TYPE => $req->error_type,
|
AUTH_ERROR_TYPE => $req->error_type,
|
||||||
MSG => $info,
|
MSG => $info,
|
||||||
URL => $req->{urldc},
|
URL => $req->{urldc},
|
||||||
HIDDEN_INPUTS => $self->buildHiddenForm(),
|
HIDDEN_INPUTS => $self->buildHiddenForm($req),
|
||||||
ACTIVE_TIMER => $self->conf->{activeTimer},
|
ACTIVE_TIMER => $self->conf->{activeTimer},
|
||||||
FORM_METHOD => $self->conf->{infoFormMethod},
|
FORM_METHOD => $self->conf->{infoFormMethod},
|
||||||
CHOICE_PARAM => $self->conf->{authChoiceParam},
|
CHOICE_PARAM => $self->conf->{authChoiceParam},
|
||||||
|
@ -201,7 +198,7 @@ sub display {
|
||||||
DISPLAY_REGISTER => $self->conf->{portalDisplayRegister},
|
DISPLAY_REGISTER => $self->conf->{portalDisplayRegister},
|
||||||
MAIL_URL => $self->conf->{mailUrl},
|
MAIL_URL => $self->conf->{mailUrl},
|
||||||
REGISTER_URL => $self->conf->{registerUrl},
|
REGISTER_URL => $self->conf->{registerUrl},
|
||||||
HIDDEN_INPUTS => $self->buildHiddenForm(),
|
HIDDEN_INPUTS => $self->buildHiddenForm($req),
|
||||||
);
|
);
|
||||||
|
|
||||||
# Display captcha if it's enabled
|
# Display captcha if it's enabled
|
||||||
|
@ -367,16 +364,15 @@ sub staticFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub buildHiddenForm {
|
sub buildHiddenForm {
|
||||||
my ($self) = @_;
|
my ( $self, $req ) = @_;
|
||||||
my @keys = keys %{ $self->conf->{portalHiddenFormValues} };
|
my @keys = keys %{ $req->{portalHiddenFormValues} };
|
||||||
my $val = '';
|
my $val = '';
|
||||||
|
|
||||||
foreach (@keys) {
|
foreach (@keys) {
|
||||||
|
|
||||||
# Check XSS attacks
|
# Check XSS attacks
|
||||||
next
|
next
|
||||||
if $self->checkXSSAttack( $_,
|
if $self->checkXSSAttack( $_, $req->{portalHiddenFormValues}->{$_} );
|
||||||
$self->conf->{portalHiddenFormValues}->{$_} );
|
|
||||||
|
|
||||||
# Build hidden input HTML code
|
# Build hidden input HTML code
|
||||||
$val .= qq{<input type="hidden" name="$_" id="$_" value="}
|
$val .= qq{<input type="hidden" name="$_" id="$_" value="}
|
||||||
|
|
|
@ -153,7 +153,16 @@ sub do {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( $err and $err != PE_LOGOUT_OK and $err != PE_REDIRECT ) {
|
if (
|
||||||
|
$err
|
||||||
|
and $err != PE_LOGOUT_OK
|
||||||
|
and (
|
||||||
|
$err != PE_REDIRECT
|
||||||
|
or ( $err == PE_REDIRECT
|
||||||
|
and $req->datas->{redirectFormMethod} eq 'post' )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
my ( $tpl, $prms ) = $self->display($req);
|
my ( $tpl, $prms ) = $self->display($req);
|
||||||
return $self->sendHtml( $req, $tpl, params => $prms );
|
return $self->sendHtml( $req, $tpl, params => $prms );
|
||||||
}
|
}
|
||||||
|
@ -488,7 +497,7 @@ sub autoPost {
|
||||||
return PE_INFO;
|
return PE_INFO;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{redirectFormMethod} = "post";
|
$req->datas->{redirectFormMethod} = "post";
|
||||||
return PE_REDIRECT;
|
return PE_REDIRECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,26 +572,4 @@ sub clearHiddenFormValue {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
##@method public string buildHiddenForm()
|
|
||||||
# Return an HTML representation of hidden values.
|
|
||||||
# @return HTML code
|
|
||||||
sub buildHiddenForm {
|
|
||||||
my ( $self, $req ) = @_;
|
|
||||||
my @keys = keys %{ $req->{portalHiddenFormValues} // {} };
|
|
||||||
my $val = '';
|
|
||||||
|
|
||||||
foreach (@keys) {
|
|
||||||
|
|
||||||
# Check XSS attacks
|
|
||||||
next
|
|
||||||
if $self->checkXSSAttack( $_, $req->{portalHiddenFormValues}->{$_} );
|
|
||||||
|
|
||||||
# Build hidden input HTML code
|
|
||||||
$val .= qq{<input type="hidden" name="$_" id="$_" value="}
|
|
||||||
. $req->{portalHiddenFormValues}->{$_} . '" />';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $val;
|
|
||||||
}
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -4,7 +4,7 @@ use IO::String;
|
||||||
|
|
||||||
require 't/test-lib.pm';
|
require 't/test-lib.pm';
|
||||||
|
|
||||||
my $maintests = 7;
|
my $maintests = 9;
|
||||||
my $debug = 'debug';
|
my $debug = 'debug';
|
||||||
my $res;
|
my $res;
|
||||||
my %handlerOR = ( issuer => [], sp => [] );
|
my %handlerOR = ( issuer => [], sp => [] );
|
||||||
|
@ -40,7 +40,7 @@ SKIP: {
|
||||||
defined( $cookies->{lemonldapidp} )
|
defined( $cookies->{lemonldapidp} )
|
||||||
and $cookies->{lemonldapidp} == 0
|
and $cookies->{lemonldapidp} == 0
|
||||||
),
|
),
|
||||||
'IDP cookie defined'
|
'IDP cookie deleted'
|
||||||
)
|
)
|
||||||
or explain( $res->[1],
|
or explain( $res->[1],
|
||||||
'Set-Cookie => lemonldapidp=0; domain=.sp.com; path=/; expires=-1d' );
|
'Set-Cookie => lemonldapidp=0; domain=.sp.com; path=/; expires=-1d' );
|
||||||
|
@ -63,13 +63,26 @@ SKIP: {
|
||||||
"confirm=$confirm&idp=https://auth.idp.com/saml/metadata"),
|
"confirm=$confirm&idp=https://auth.idp.com/saml/metadata"),
|
||||||
accept => 'text/html',
|
accept => 'text/html',
|
||||||
length => length($confirm) + 47,
|
length => length($confirm) + 47,
|
||||||
cookie => 'lemonldapidp=0',
|
|
||||||
),
|
),
|
||||||
'Select IDP'
|
'Select IDP'
|
||||||
);
|
);
|
||||||
|
ok( $res->[0] == 200, 'Return code is 200' );
|
||||||
|
$cookies = $sp->getCookies($res);
|
||||||
|
ok(
|
||||||
|
(
|
||||||
|
defined( $cookies->{lemonldapidp} )
|
||||||
|
and $cookies->{lemonldapidp} eq 'https://auth.idp.com/saml/metadata'
|
||||||
|
),
|
||||||
|
'IDP cookie defined'
|
||||||
|
)
|
||||||
|
or explain(
|
||||||
|
$res->[1],
|
||||||
|
'Set-Cookie => lemonldapidp=https://auth.idp.com/saml/metadata; domain=.sp.com; path=/'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
count($maintests);
|
count($maintests);
|
||||||
|
clean_sessions();
|
||||||
done_testing( count() );
|
done_testing( count() );
|
||||||
|
|
||||||
sub switch {
|
sub switch {
|
||||||
|
@ -346,7 +359,7 @@ sub sp {
|
||||||
samlIDPMetaDataOptions => {
|
samlIDPMetaDataOptions => {
|
||||||
idp => {
|
idp => {
|
||||||
samlIDPMetaDataOptionsEncryptionMode => 'none',
|
samlIDPMetaDataOptionsEncryptionMode => 'none',
|
||||||
samlIDPMetaDataOptionsSSOBinding => 'POST',
|
samlIDPMetaDataOptionsSSOBinding => 'POST',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
samlIDPMetaDataXML => {
|
samlIDPMetaDataXML => {
|
||||||
|
|
|
@ -56,8 +56,8 @@
|
||||||
"portal": "http://auth.example.com/",
|
"portal": "http://auth.example.com/",
|
||||||
"samlStorage": "Apache::Session::File",
|
"samlStorage": "Apache::Session::File",
|
||||||
"samlStorageOptions": {
|
"samlStorageOptions": {
|
||||||
"Directory": "t/sessions",
|
"Directory": "t/sessions/saml",
|
||||||
"LockDirectory": "t/sessions/lock",
|
"LockDirectory": "t/sessions/saml/lock",
|
||||||
"generateModule": "Lemonldap::NG::Common::Apache::Session::Generate::SHA256"
|
"generateModule": "Lemonldap::NG::Common::Apache::Session::Generate::SHA256"
|
||||||
},
|
},
|
||||||
"reloadUrls": {},
|
"reloadUrls": {},
|
||||||
|
|
0
lemonldap-ng-portal/t/sessions/saml/lock/.exists
Normal file
0
lemonldap-ng-portal/t/sessions/saml/lock/.exists
Normal file
|
@ -28,9 +28,13 @@ sub clean_sessions {
|
||||||
foreach ( grep { /^[^\.]/ } readdir(D) ) {
|
foreach ( grep { /^[^\.]/ } readdir(D) ) {
|
||||||
unlink "t/sessions/$_", "t/sessions/lock/Apache-Session-$_.lock";
|
unlink "t/sessions/$_", "t/sessions/lock/Apache-Session-$_.lock";
|
||||||
}
|
}
|
||||||
opendir D, 't/sessions/lock' or die $!;
|
foreach my $dir (qw(t/sessions/lock t/sessions/saml/lock t/sessions/saml)) {
|
||||||
foreach ( grep { /^[^\.]/ } readdir(D) ) {
|
if ( -d $dir ) {
|
||||||
unlink "t/sessions/lock/$_";
|
opendir D, $dir or die $!;
|
||||||
|
foreach ( grep { /^[^\.]/ } readdir(D) ) {
|
||||||
|
unlink "$dir/$_";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user