## @file # OpenID SREG extension for Lemonldap::NG::Portal::IssuerOpenID class ## @class # OpenID SREG extension for Lemonldap::NG::Portal::IssuerOpenID class package Lemonldap::NG::Portal::OpenID::SREG; use strict; use Lemonldap::NG::Common::Regexp; use Lemonldap::NG::Portal::Simple; ## @method protected hash sregHook(hash prm) # Hook called to add SREG parameters to the OpenID response # @return Hash containing wanted parameters sub sregHook { my ( $self, $u, $trust_root, $is_id, $is_trusted, $prm ) = splice @_; my ( @req, @opt ); # Refuse federation if rejected by user return 0 if ( $self->param('confirm') == -1 ); # If identity is not trusted, does nothing return ( 0, $prm ) unless ($is_id); $self->lmLog( "SREG start", 'debug' ); my $accepted = 1; # Check all parameters while ( my ( $k, $v ) = each %$prm ) { # Store policy if provided if ( $k eq 'policy_url' ) { if ( $v =~ Lemonldap::NG::Common::Regexp::HTTP_URI ) { $self->{_openIdTrustExtMsg} .= '
' . &Lemonldap::NG::Portal::_i18n::msg(PM_OPENID_PA) . " :
$v
"; # Question: is it important to notify policy changes ? # if yes, uncomment this #my $p = # $self->{sessionInfo}->{"_openidTrust$trust_root\_Policy"}; #$accepted = 0 unless ( $p and $p eq $v ); } else { $self->lmLog( "Bad policy url", 'error' ); } } # Parse required attributes elsif ( $k eq 'required' ) { $self->lmLog( "Required attr $v", 'debug' ); push @req, split( /,/, $v ); } # Parse optional attributes elsif ( $k eq 'optional' ) { $self->lmLog( "Optional attr $v", 'debug' ); push @opt, grep { defined $self->{"openIdSreg_$_"} } split( /,/, $v ); } else { $self->lmLog( "Unknown OpenID SREG request $k", 'error' ); } } # Check if required keys are valid SREG requests # Question: reject bad SREG request ? Not done yet @req = sregfilter( $self, @req ); @opt = sregfilter( $self, @opt ); # If nothing is asked, return ( 1, {} ) unless ( @req and @opt ); # If a required data is not available, returns nothing foreach my $k (@req) { unless ( $self->{"openIdSreg_$k"} ) { $self->lmLog( "Parameter $k is required by $trust_root but not defined in configuration", 'notice' ); $self->info( '

' . sprintf( &Lemonldap::NG::Portal::_i18n::msg(PM_OPENID_RPNS), $k ) . '

' ); return ( 0, {} ); } } # Now set datas my ( %r, %msg, %ag ); # Requested parameters: check if already agreed or confirm is set foreach my $k (@req) { my $agree = $self->{sessionInfo}->{"_openidTrust$trust_root\_$k"}; if ($accepted) { unless ( $self->param('confirm') or $agree ) { $accepted = 0; } elsif ( !$agree ) { $self->updateSession( { "_openidTrust$trust_root\_$k" => 1 } ); } } $self->{"openIdSreg_$k"} =~ s/^\$//; $msg{req}->{$k} = $r{$k} = $self->{sessionInfo}->{ $self->{"openIdSreg_$k"} } || ''; } # Optional parameters: foreach my $k (@opt) { $self->{"openIdSreg_$k"} =~ s/^\$//; my $agree = $self->{sessionInfo}->{"_openidTrust$trust_root\_$k"}; if ($accepted) { # First, check if already accepted unless ( $self->param('confirm') or defined($agree) ) { $accepted = 0; $r{$k} = $self->{sessionInfo}->{ $self->{"openIdSreg_$k"} } || ''; } # If confirmation is returned, check the value for this field elsif ( $self->param('confirm') == 1 ) { my $ck = 0; if ( defined( $self->param("sreg_$k") ) ) { $ck = ( $self->param("sreg_$k") == 'OK' ) || 0; } # Store the value returned if ( !defined($agree) or $agree != $ck ) { $self->updateSession( { "_openidTrust$trust_root\_$k" => $ck } ); $agree = $ck; } } } # TODO: updateSession() $msg{opt}->{$k} = $self->{sessionInfo}->{ $self->{"openIdSreg_$k"} } || ''; # Store the value only if user agree it if ($agree) { $r{$k} = $msg{opt}->{$k}; $ag{$k} = 1; } elsif ( !defined($agree) ) { $ag{$k} = 1; } else { $ag{$k} = 0; } } # Check if user has agreed request if ($accepted) { $self->_sub( 'userInfo', $self->{sessionInfo}->{ $self->{whatToTrace} } . " has accepted OpenID SREG exchange with $trust_root" ); return ( 1, \%r ); } # else build message and return 0 else { # No choice for requested parameters: just an information $self->{_openIdTrustExtMsg} .= "

" . &Lemonldap::NG::Portal::_i18n::msg(PM_OPENID_AP) . "

'; foreach my $k (@opt) { $self->{_openIdTrustExtMsg} .= qq# $k: $r{$k}
#; } $self->lmLog( 'Building validation form', 'debug' ); return ( 0, $prm ); } } ## @method private array sregfilter(array attr) # Filter the arguments passed as parameters by checking their compliance with # SREG. # @return fitered datas sub sregfilter { my ( $self, @attr ) = splice @_; my ( @ret, @rej ); foreach my $s (@attr) { if ( $s =~ /^(?:(?:(?:full|nick)nam|languag|postcod|timezon)e|country|gender|email|dob)$/ ) { push @ret, $s; } else { $s =~ s/\W/\./sg; push @rej, $s; } if (@rej) { $self->lmLog( "Requested parameter(s) " . join( ',', @rej ) . "is(are) not valid OpenID SREG parameter(s)", 'error' ); } return @ret; } } 1;