parent
8e2418ceb8
commit
ec83414576
|
@ -23,6 +23,7 @@ has ssoUrlRe => ( is => 'rw' );
|
|||
has sloRe => ( is => 'rw' );
|
||||
has artRe => ( is => 'rw' );
|
||||
has soapSloRe => ( is => 'rw' );
|
||||
has sloRelaySoapRe => ( is => 'rw' );
|
||||
|
||||
# INITIALIZATION
|
||||
|
||||
|
@ -76,6 +77,8 @@ qr/^($saml_sso_soap_url|$saml_sso_soap_url_ret|$saml_sso_get_url|$saml_sso_get_u
|
|||
qr/^($saml_slo_soap_url|$saml_slo_soap_url_ret|$saml_slo_get_url|$saml_slo_get_url_ret|$saml_slo_post_url|$saml_slo_post_url_ret)(?:\?.*)?$/i
|
||||
);
|
||||
|
||||
$self->sloRelaySoapRe(qr#^/saml/relaySingleLogoutSOAP(?:\?.*)?$#i);
|
||||
|
||||
return (
|
||||
$self->Lemonldap::NG::Portal::Main::Issuer::init()
|
||||
|
||||
|
@ -104,7 +107,20 @@ sub _pRedirect {
|
|||
return $self->soapSloServer($req);
|
||||
}
|
||||
else {
|
||||
return $self->SUPER::_pRedirect($req);
|
||||
$req->parseBody;
|
||||
return $self->SUPER::_redirect($req);
|
||||
}
|
||||
}
|
||||
|
||||
# Override _redirect to catch SLO relay
|
||||
|
||||
sub _redirect {
|
||||
my ( $self, $req ) = @_;
|
||||
if ( $req->uri =~ $self->sloRelaySoapRe ) {
|
||||
return $self->sloRelaySoap($req);
|
||||
}
|
||||
else {
|
||||
return $self->SUPER::_redirect($req);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1461,6 +1477,105 @@ sub logout {
|
|||
return PE_OK;
|
||||
}
|
||||
|
||||
sub sloRelaySoap {
|
||||
my ( $self, $req ) = @_;
|
||||
$self->lmLog( "URL " . $req->uri . " detected as a SOAP relay service URL",
|
||||
'debug' );
|
||||
|
||||
# Check if relay parameter is present (mandatory)
|
||||
my $relayID;
|
||||
unless ( $relayID = $req->param('relay') ) {
|
||||
$self->lmLog( "No relayID detected", 'error' );
|
||||
return $self->imgnok($req);
|
||||
}
|
||||
|
||||
# Retrieve the corresponding data from samlStorage
|
||||
my $relayInfos = $self->getSamlSession($relayID);
|
||||
unless ($relayInfos) {
|
||||
$self->lmLog( "Could not get relay session $relayID", 'error' );
|
||||
return $self->imgnok($req);
|
||||
}
|
||||
|
||||
$self->lmLog( "Found relay session $relayID", 'debug' );
|
||||
|
||||
# Rebuild the logout object
|
||||
my $logout;
|
||||
unless ( $logout = $self->createLogout( $self->lassoServer ) ) {
|
||||
$self->lmLog( "Could not rebuild logout object", 'error' );
|
||||
return $self->imgnok($req);
|
||||
}
|
||||
|
||||
# Load Session and Identity if they exist
|
||||
my $session = $relayInfos->data->{_lassoSessionDump};
|
||||
my $identity = $relayInfos->data->{_lassoIdentityDump};
|
||||
my $providerID = $relayInfos->data->{_providerID};
|
||||
my $relayState = $relayInfos->data->{_relayState};
|
||||
my $spConfKey = $self->spList->{$providerID}->{confKey};
|
||||
|
||||
if ($session) {
|
||||
unless ( $self->setSessionFromDump( $logout, $session ) ) {
|
||||
$self->lmLog( "Unable to load Lasso Session", 'error' );
|
||||
return $self->imgnok($req);
|
||||
}
|
||||
$self->lmLog( "Lasso Session loaded", 'debug' );
|
||||
}
|
||||
|
||||
if ($identity) {
|
||||
unless ( $self->setIdentityFromDump( $logout, $identity ) ) {
|
||||
$self->lmLog( "Unable to load Lasso Identity", 'error' );
|
||||
return $self->imgnok($req);
|
||||
}
|
||||
$self->lmLog( "Lasso Identity loaded", 'debug' );
|
||||
}
|
||||
|
||||
# Send the logout request
|
||||
my ( $rstatus, $rmethod, $rinfo ) =
|
||||
$self->sendLogoutRequestToProvider( $req, $logout, $providerID,
|
||||
Lasso::Constants::HTTP_METHOD_SOAP );
|
||||
unless ($rstatus) {
|
||||
$self->lmLog( "Fail to process SOAP logout request to $providerID",
|
||||
'error' );
|
||||
return $self->imgnok($req);
|
||||
}
|
||||
|
||||
# Store success status for this SLO request
|
||||
my $sloStatusSessionInfos = $self->getSamlSession($relayState);
|
||||
|
||||
if ($sloStatusSessionInfos) {
|
||||
$sloStatusSessionInfos->update( { $spConfKey => 1 } );
|
||||
$self->lmLog( "Store SLO status for $spConfKey in session $relayState",
|
||||
'debug' );
|
||||
}
|
||||
else {
|
||||
$self->lmLog(
|
||||
"Unable to store SLO status for $spConfKey in session $relayState",
|
||||
'warn'
|
||||
);
|
||||
}
|
||||
|
||||
# Delete relay session
|
||||
$relayInfos->remove();
|
||||
|
||||
# SLO response is OK
|
||||
$self->lmLog( "Display OK status for SLO on $spConfKey", 'debug' );
|
||||
return $self->imgok($req);
|
||||
}
|
||||
|
||||
# INTERNAL METHODS
|
||||
|
||||
sub imgok {
|
||||
my ( $self, $req, ) = @_;
|
||||
return $self->sendImage( $req, 'ok.png' );
|
||||
}
|
||||
|
||||
sub imgnok {
|
||||
my ( $self, $req, ) = @_;
|
||||
return $self->sendImage( $req, 'warning.png' );
|
||||
}
|
||||
|
||||
sub sendImage {
|
||||
my ( $self, $req,, $img ) = @_;
|
||||
return $self->p->staticFile( $req, "common/$img", 'image/png' );
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -61,15 +61,8 @@ sub display {
|
|||
|
||||
# 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() ) {
|
||||
# 1.1 Case : there is a message to display
|
||||
if ( my $info = $req->info() ) {
|
||||
$skinfile = 'info';
|
||||
%templateParams = (
|
||||
AUTH_ERROR_TYPE => $req->error_type,
|
||||
|
@ -81,7 +74,7 @@ sub display {
|
|||
);
|
||||
}
|
||||
|
||||
# 1.3 Redirection
|
||||
# 1.2 Redirection
|
||||
elsif ( $req->{error} == PE_REDIRECT ) {
|
||||
$skinfile = "redirect";
|
||||
%templateParams = (
|
||||
|
@ -91,7 +84,7 @@ sub display {
|
|||
);
|
||||
}
|
||||
|
||||
# 1.4 Case : display menu
|
||||
# 1.3 Case : display menu
|
||||
elsif ( $req->error == PE_OK ) {
|
||||
|
||||
$skinfile = 'menu';
|
||||
|
@ -110,8 +103,8 @@ sub display {
|
|||
|
||||
# 2. Authentication not complete
|
||||
|
||||
# 2.1 A notification has to be done (session is created but hidden and unusable
|
||||
# until the user has accept the message)
|
||||
# 2.1 A notification has to be done (session is created but hidden and
|
||||
# unusable until the user has accept the message)
|
||||
elsif ( my $notif = $req->datas->{notification} ) {
|
||||
$skinfile = 'notification';
|
||||
%templateParams = (
|
||||
|
@ -344,12 +337,12 @@ sub display {
|
|||
# @param $type The content-type to use (ie: image/png)
|
||||
# @return void
|
||||
sub staticFile {
|
||||
my ( $self, $file, $type ) = @_;
|
||||
my ( $self, $req, $file, $type ) = @_;
|
||||
require Plack::Util;
|
||||
require Cwd;
|
||||
require HTTP::Date;
|
||||
open my $fh, '<:raw', $self->conf->{templatesDir} . "/$file"
|
||||
or return $self->sendError( $!, 403 );
|
||||
or return $self->sendError( $req, $!, 403 );
|
||||
my @stat = stat $file;
|
||||
Plack::Util::set_io_path( $fh, Cwd::realpath($file) );
|
||||
return [
|
||||
|
|
|
@ -127,7 +127,9 @@ sub loginInfo {
|
|||
}
|
||||
|
||||
sub info {
|
||||
print STDERR "TODO Request::info()\n";
|
||||
my ( $self, $info ) = @_;
|
||||
$self->datas->{_info} .= $info if ( defined $info );
|
||||
return $self->datas->{_info};
|
||||
}
|
||||
|
||||
# TODO: oldpassword
|
||||
|
|
|
@ -583,8 +583,8 @@ sub getFirstValue {
|
|||
}
|
||||
|
||||
sub info {
|
||||
my($self,$req,$info)=@_;
|
||||
print STDERR "####### TODO: info()\n";
|
||||
my ( $self, $req, $info ) = @_;
|
||||
return $req->info($info);
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -7,7 +7,7 @@ BEGIN {
|
|||
require 't/test-lib.pm';
|
||||
}
|
||||
|
||||
my $maintests = 28;
|
||||
my $maintests = 26;
|
||||
my $debug = 'error';
|
||||
my ( $issuer, $sp, $res );
|
||||
my %handlerOR = ( issuer => [], sp => [] );
|
||||
|
@ -220,7 +220,7 @@ sub LWP::UserAgent::request {
|
|||
$httpResp->header( $name, shift( @{ $res->[1] } ) );
|
||||
}
|
||||
$httpResp->content( join( '', @{ $res->[2] } ) );
|
||||
count(3);
|
||||
count(4);
|
||||
return $httpResp;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ BEGIN {
|
|||
require 't/test-lib.pm';
|
||||
}
|
||||
|
||||
my $maintests = 18;
|
||||
my $maintests = 21;
|
||||
my $debug = 'debug';
|
||||
my ( $issuer, $sp, $res );
|
||||
my %handlerOR = ( issuer => [], sp => [] );
|
||||
|
@ -104,17 +104,65 @@ SKIP: {
|
|||
cookie => "lemonldap=$idpId",
|
||||
accept => 'text/html'
|
||||
),
|
||||
'Query SP for logout'
|
||||
'Query IdP for logout'
|
||||
);
|
||||
ok( $res->[0] == 200, 'Return code is 200' );
|
||||
|
||||
#print STDERR Dumper($res);
|
||||
ok(
|
||||
$res->[2]->[0] =~
|
||||
m#img src="http://auth.idp.com(/saml/relaySingleLogoutSOAP)\?(relay=.*?)"#s,
|
||||
'Get image request'
|
||||
);
|
||||
|
||||
ok(
|
||||
$res = $issuer->_get(
|
||||
$1,
|
||||
query => $2,
|
||||
|
||||
#cookie => "lemonldap=$idpId",
|
||||
accept => 'text/html'
|
||||
),
|
||||
'Get image'
|
||||
);
|
||||
ok( $issuer->getHeader( $res, 'Content-Type' ) eq 'image/png',
|
||||
'Get an image' );
|
||||
|
||||
}
|
||||
|
||||
count($maintests);
|
||||
clean_sessions();
|
||||
done_testing( count() );
|
||||
|
||||
# Redefine LWP methods for tests
|
||||
sub LWP::UserAgent::request {
|
||||
my ( $self, $req ) = @_;
|
||||
ok( $req->uri =~ m#http://auth.sp.com(.*)#, 'Request from SP to IdP' );
|
||||
my $url = $1;
|
||||
my $res;
|
||||
my $s = $req->content;
|
||||
ok(
|
||||
$res = $sp->_post(
|
||||
$url, IO::String->new($s),
|
||||
length => length($s),
|
||||
type => 'application/xml',
|
||||
),
|
||||
'Execute request'
|
||||
);
|
||||
#ok( ( $res->[0] == 200 or $res->[0] == 400 ), 'Response is 200 or 400' )
|
||||
# or explain( $res->[0], "200 or 400" );
|
||||
#ok( $issuer->getHeader( $res, 'Content-Type' ) =~ m#^application/xml#,
|
||||
# 'Content is XML' )
|
||||
# or explain( $res->[1], 'Content-Type => application/xml' );
|
||||
my $httpResp = HTTP::Response->new( $res->[0], 'OK' );
|
||||
|
||||
while ( my $name = shift @{ $res->[1] } ) {
|
||||
$httpResp->header( $name, shift( @{ $res->[1] } ) );
|
||||
}
|
||||
$httpResp->content( join( '', @{ $res->[2] } ) );
|
||||
count(2);
|
||||
return $httpResp;
|
||||
}
|
||||
|
||||
sub switch {
|
||||
my $type = shift;
|
||||
@Lemonldap::NG::Handler::Main::Reload::_onReload = @{
|
||||
|
@ -127,6 +175,7 @@ sub issuer {
|
|||
{
|
||||
ini => {
|
||||
logLevel => $debug,
|
||||
templatesDir => 'site/htdocs/static',
|
||||
domain => 'idp.com',
|
||||
portal => 'http://auth.idp.com',
|
||||
authentication => 'Demo',
|
||||
|
|
Loading…
Reference in New Issue
Block a user