* 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:
Clément Oudot 2010-02-12 10:53:43 +00:00
parent cb7f7f8bd1
commit 71f142316f
2 changed files with 79 additions and 19 deletions

View File

@ -60,7 +60,7 @@ sub authInit {
# Load identity provider metadata # Load identity provider metadata
# IDP are listed in $self->{samlIDPMetaData} # 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 # Build IDP list for later use in extractFormInfo
foreach ( keys %{ $self->{samlIDPMetaData} } ) { foreach ( keys %{ $self->{samlIDPMetaData} } ) {
@ -70,7 +70,7 @@ sub authInit {
my $idp_metadata = Lemonldap::NG::Common::Conf::SAML::Metadata->new(); my $idp_metadata = Lemonldap::NG::Common::Conf::SAML::Metadata->new();
unless ( unless (
$idp_metadata->initializeFromConfHash( $idp_metadata->initializeFromConfHash(
$self->{samlIDPMetaData}->{$_} $self->{samlIDPMetaData}->{$_}->{metadata}
) )
) )
{ {
@ -173,7 +173,24 @@ sub extractFormInfo {
# TODO check conditions # 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 # Get NameID
my $nameid = $login->nameIdentifier; my $nameid = $login->nameIdentifier;
@ -226,8 +243,8 @@ sub extractFormInfo {
foreach ( keys %{ $self->{_idpList} } ) { foreach ( keys %{ $self->{_idpList} } ) {
$html .= $html .=
'<tr><td><input type="radio" name="idp" value="' '<tr><td><input type="radio" name="idp" value="'
. $self->{_idpList}->{$_}->{entityID} . $_
. '" /></td><td>' . '" /></td><td>'
. $self->{_idpList}->{$_}->{name} . $self->{_idpList}->{$_}->{name}
. '</td></tr>'; . '</td></tr>';
@ -266,7 +283,11 @@ sub extractFormInfo {
my $html = '<h3>' my $html = '<h3>'
. &Lemonldap::NG::Portal::_i18n::msg( PM_SAML_IDPCHOOSEN, . &Lemonldap::NG::Portal::_i18n::msg( PM_SAML_IDPCHOOSEN,
$ENV{HTTP_ACCEPT_LANGUAGE} ) $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); $self->info($html);
@ -293,10 +314,12 @@ sub extractFormInfo {
} }
# 3. Build authentication request # 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) { unless ($login) {
$self->lmLog( "Could not create authentication request on $idp", $self->lmLog( "Could not create authentication request on $IDPentityID",
'error' ); 'error' );
return PE_ERROR; return PE_ERROR;
} }
@ -319,7 +342,7 @@ sub extractFormInfo {
# Extract attributes sent in authentication statement # Extract attributes sent in authentication statement
# @return Lemonldap::NG::Portal error code # @return Lemonldap::NG::Portal error code
sub setAuthSessionInfo { sub setAuthSessionInfo {
my $self = shift; my $self = shift;
my $server = $self->{_lassoServer}; my $server = $self->{_lassoServer};
my $login = $self->{_lassoLogin}; my $login = $self->{_lassoLogin};
@ -327,7 +350,7 @@ sub setAuthSessionInfo {
# Store other informations in session # Store other informations in session
$self->{sessionInfo}->{_user} = $self->{user}; $self->{sessionInfo}->{_user} = $self->{user};
$self->{sessionInfo}->{_idp} = $login->remote_providerID; $self->{sessionInfo}->{_idp} = $self->{_idp};
# TODO adapt _utime with SessionNotOnOrAfter # TODO adapt _utime with SessionNotOnOrAfter
@ -338,7 +361,7 @@ sub setAuthSessionInfo {
# Accept SSO from IDP # Accept SSO from IDP
# @return PE_OK # @return PE_OK
sub authenticate { sub authenticate {
my $self = shift; my $self = shift;
my $server = $self->{_lassoServer}; my $server = $self->{_lassoServer};
my $login = $self->{_lassoLogin}; my $login = $self->{_lassoLogin};

View File

@ -8,12 +8,13 @@ package Lemonldap::NG::Portal::_SAML;
use strict; use strict;
use base qw(Exporter); use base qw(Exporter);
use XML::Simple; use XML::Simple;
use MIME::Base64;
our @EXPORT = qw( our @EXPORT = qw(
loadLasso checkLassoError createServer addIDP addProvider getOrganizationName loadLasso checkLassoError createServer addIDP addProvider getOrganizationName
createAuthnRequest createLogin getHttpMethod initAuthnRequest createAuthnRequest createLogin getHttpMethod initAuthnRequest
buildAuthnRequestMsg processAuthnResponseMsg getNameIdentifier buildAuthnRequestMsg processAuthnResponseMsg getNameIdentifier
createIdentity createSession acceptSSO createIdentity createSession acceptSSO extractRelayState
); );
our $VERSION = '0.01'; our $VERSION = '0.01';
@ -208,6 +209,9 @@ sub getOrganizationName {
return; return;
} }
# Return if node is empty
return unless $node;
# Extract organization name # Extract organization name
my $xs = XML::Simple->new(); my $xs = XML::Simple->new();
my $data = $xs->XMLin($node); my $data = $xs->XMLin($node);
@ -242,12 +246,15 @@ sub createAuthnRequest {
return; return;
} }
# Set urldc in RelayState # Set RelayState as key1;value1;key2;value2;... encoded in base 64
my $relaystate = $self->{urldc}; my $relaystate;
if ($relaystate) { foreach (qw /_idp urldc/) {
$login->msg_relayState($relaystate); $relaystate .= $_ . ";" . $self->{$_} . ";" if $self->{$_};
$self->lmLog( "Set $relaystate in RelayState", 'debug' );
} }
$relaystate =~ s/;$//;
$relaystate = encode_base64( $relaystate, '' );
$login->msg_relayState($relaystate);
$self->lmLog( "Set $relaystate in RelayState", 'debug' );
# Customize request # Customize request
my $request = $login->request(); my $request = $login->request();
@ -276,7 +283,7 @@ sub createLogin {
eval { $login = Lasso::Login->new($server); }; eval { $login = Lasso::Login->new($server); };
if ($@) { if ($@) {
$self->checkLassoError($@); $self->checkLassoError($@);
return; return;
} }
@ -413,6 +420,33 @@ sub acceptSSO {
return $self->checkLassoError($@); 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; 1;
__END__ __END__
@ -498,6 +532,10 @@ Create Lasso::Session object
Accept SSO from IDP Accept SSO from IDP
=head2 extractRelayState
Extract RelayState information into $self
=head1 SEE ALSO =head1 SEE ALSO
L<Lemonldap::NG::Portal::AuthSAML>, L<Lemonldap::NG::Portal::UserDBSAML> 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, 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. at your option, any later version of Perl 5 you may have available.
=cut =cut