SAML:
* IDP metadata are in metadata key * Use IDP internal ID instead of entityID to keep choosen IDP information * Use base64 encoding for RelayState value
This commit is contained in:
parent
cb7f7f8bd1
commit
71f142316f
@ -60,7 +60,7 @@ sub authInit {
|
||||
|
||||
# Load identity provider metadata
|
||||
# IDP are listed in $self->{samlIDPMetaData}
|
||||
# Each key is the IDP name and value is the metadata
|
||||
# Each key is the IDP name and value is the metadata key
|
||||
# Build IDP list for later use in extractFormInfo
|
||||
foreach ( keys %{ $self->{samlIDPMetaData} } ) {
|
||||
|
||||
@ -70,7 +70,7 @@ sub authInit {
|
||||
my $idp_metadata = Lemonldap::NG::Common::Conf::SAML::Metadata->new();
|
||||
unless (
|
||||
$idp_metadata->initializeFromConfHash(
|
||||
$self->{samlIDPMetaData}->{$_}
|
||||
$self->{samlIDPMetaData}->{$_}->{metadata}
|
||||
)
|
||||
)
|
||||
{
|
||||
@ -173,7 +173,24 @@ sub extractFormInfo {
|
||||
|
||||
# TODO check conditions
|
||||
|
||||
# TODO get urldc in RelayState
|
||||
# Extract RelayState information
|
||||
if ( $self->extractRelayState($login) ) {
|
||||
$self->lmLog( "RelayState found in authentication assertion",
|
||||
'debug' );
|
||||
}
|
||||
|
||||
# Check IDP
|
||||
my $idp = $self->{_idp};
|
||||
unless ($idp) {
|
||||
$self->lmLog( "IDP was not found in RelayState", 'error' );
|
||||
return PE_ERROR;
|
||||
}
|
||||
|
||||
$self->lmLog( "IDP $idp found in RelayState", 'debug' );
|
||||
|
||||
# Force redirection to portal if no urldc found
|
||||
# (avoid displaying the whole SAML URL in user browser URL field)
|
||||
$self->{mustRedirect} = 1 unless ( $self->{urldc} );
|
||||
|
||||
# Get NameID
|
||||
my $nameid = $login->nameIdentifier;
|
||||
@ -226,8 +243,8 @@ sub extractFormInfo {
|
||||
|
||||
foreach ( keys %{ $self->{_idpList} } ) {
|
||||
$html .=
|
||||
'<tr><td><input type="radio" name="idp" value="'
|
||||
. $self->{_idpList}->{$_}->{entityID}
|
||||
'<tr><td><input type="radio" name="idp" value="'
|
||||
. $_
|
||||
. '" /></td><td>'
|
||||
. $self->{_idpList}->{$_}->{name}
|
||||
. '</td></tr>';
|
||||
@ -266,7 +283,11 @@ sub extractFormInfo {
|
||||
my $html = '<h3>'
|
||||
. &Lemonldap::NG::Portal::_i18n::msg( PM_SAML_IDPCHOOSEN,
|
||||
$ENV{HTTP_ACCEPT_LANGUAGE} )
|
||||
. "</h3>\n<h4>$idp</h4>\n<input type=\"hidden\" name=\"idp\" value=\"$idp\" />\n";
|
||||
. "</h3>\n"
|
||||
. "<h4>$idp</h4>\n" . "<h5>("
|
||||
. $self->{_idpList}->{$idp}->{entityID}
|
||||
. ")</h5>\n"
|
||||
. "<input type=\"hidden\" name=\"idp\" value=\"$idp\" />\n";
|
||||
|
||||
$self->info($html);
|
||||
|
||||
@ -293,10 +314,12 @@ sub extractFormInfo {
|
||||
}
|
||||
|
||||
# 3. Build authentication request
|
||||
$login = $self->createAuthnRequest( $server, $idp );
|
||||
$self->{_idp} = $idp;
|
||||
my $IDPentityID = $self->{_idpList}->{$idp}->{entityID};
|
||||
$login = $self->createAuthnRequest( $server, $IDPentityID );
|
||||
|
||||
unless ($login) {
|
||||
$self->lmLog( "Could not create authentication request on $idp",
|
||||
$self->lmLog( "Could not create authentication request on $IDPentityID",
|
||||
'error' );
|
||||
return PE_ERROR;
|
||||
}
|
||||
@ -319,7 +342,7 @@ sub extractFormInfo {
|
||||
# Extract attributes sent in authentication statement
|
||||
# @return Lemonldap::NG::Portal error code
|
||||
sub setAuthSessionInfo {
|
||||
my $self = shift;
|
||||
my $self = shift;
|
||||
my $server = $self->{_lassoServer};
|
||||
my $login = $self->{_lassoLogin};
|
||||
|
||||
@ -327,7 +350,7 @@ sub setAuthSessionInfo {
|
||||
|
||||
# Store other informations in session
|
||||
$self->{sessionInfo}->{_user} = $self->{user};
|
||||
$self->{sessionInfo}->{_idp} = $login->remote_providerID;
|
||||
$self->{sessionInfo}->{_idp} = $self->{_idp};
|
||||
|
||||
# TODO adapt _utime with SessionNotOnOrAfter
|
||||
|
||||
@ -338,7 +361,7 @@ sub setAuthSessionInfo {
|
||||
# Accept SSO from IDP
|
||||
# @return PE_OK
|
||||
sub authenticate {
|
||||
my $self = shift;
|
||||
my $self = shift;
|
||||
my $server = $self->{_lassoServer};
|
||||
my $login = $self->{_lassoLogin};
|
||||
|
||||
|
@ -8,12 +8,13 @@ package Lemonldap::NG::Portal::_SAML;
|
||||
use strict;
|
||||
use base qw(Exporter);
|
||||
use XML::Simple;
|
||||
use MIME::Base64;
|
||||
|
||||
our @EXPORT = qw(
|
||||
loadLasso checkLassoError createServer addIDP addProvider getOrganizationName
|
||||
createAuthnRequest createLogin getHttpMethod initAuthnRequest
|
||||
buildAuthnRequestMsg processAuthnResponseMsg getNameIdentifier
|
||||
createIdentity createSession acceptSSO
|
||||
createIdentity createSession acceptSSO extractRelayState
|
||||
);
|
||||
|
||||
our $VERSION = '0.01';
|
||||
@ -208,6 +209,9 @@ sub getOrganizationName {
|
||||
return;
|
||||
}
|
||||
|
||||
# Return if node is empty
|
||||
return unless $node;
|
||||
|
||||
# Extract organization name
|
||||
my $xs = XML::Simple->new();
|
||||
my $data = $xs->XMLin($node);
|
||||
@ -242,12 +246,15 @@ sub createAuthnRequest {
|
||||
return;
|
||||
}
|
||||
|
||||
# Set urldc in RelayState
|
||||
my $relaystate = $self->{urldc};
|
||||
if ($relaystate) {
|
||||
$login->msg_relayState($relaystate);
|
||||
$self->lmLog( "Set $relaystate in RelayState", 'debug' );
|
||||
# Set RelayState as key1;value1;key2;value2;... encoded in base 64
|
||||
my $relaystate;
|
||||
foreach (qw /_idp urldc/) {
|
||||
$relaystate .= $_ . ";" . $self->{$_} . ";" if $self->{$_};
|
||||
}
|
||||
$relaystate =~ s/;$//;
|
||||
$relaystate = encode_base64( $relaystate, '' );
|
||||
$login->msg_relayState($relaystate);
|
||||
$self->lmLog( "Set $relaystate in RelayState", 'debug' );
|
||||
|
||||
# Customize request
|
||||
my $request = $login->request();
|
||||
@ -276,7 +283,7 @@ sub createLogin {
|
||||
eval { $login = Lasso::Login->new($server); };
|
||||
|
||||
if ($@) {
|
||||
$self->checkLassoError($@);
|
||||
$self->checkLassoError($@);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -413,6 +420,33 @@ sub acceptSSO {
|
||||
return $self->checkLassoError($@);
|
||||
}
|
||||
|
||||
## @method boolean extractRelayState(Lasso::Login login)
|
||||
# Extract RelayState information into $self
|
||||
## @param login Lasso::Login object
|
||||
## @return result
|
||||
sub extractRelayState {
|
||||
my ( $self, $login ) = splice @_;
|
||||
|
||||
# Get relayState in assertion
|
||||
my $relaystate = $login->msg_relayState;
|
||||
|
||||
return 0 unless $relaystate;
|
||||
|
||||
# Decode base64
|
||||
$relaystate = decode_base64($relaystate);
|
||||
|
||||
# Recover values
|
||||
my @values = split( /;/, $relaystate );
|
||||
|
||||
# Push values in $self
|
||||
my $i;
|
||||
for ( $i = 0, $i < $#values, $i++ ) {
|
||||
$self->{ $values[$i] } = $values[ $i++ ];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
@ -498,6 +532,10 @@ Create Lasso::Session object
|
||||
|
||||
Accept SSO from IDP
|
||||
|
||||
=head2 extractRelayState
|
||||
|
||||
Extract RelayState information into $self
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Lemonldap::NG::Portal::AuthSAML>, L<Lemonldap::NG::Portal::UserDBSAML>
|
||||
@ -515,5 +553,4 @@ This library is free software; you can redistribute it and/or modify
|
||||
it under the same terms as Perl itself, either Perl version 5.10.0 or,
|
||||
at your option, any later version of Perl 5 you may have available.
|
||||
|
||||
|
||||
=cut
|
||||
|
Loading…
Reference in New Issue
Block a user