lemonldap-ng/lemonldap-ng-portal/lib/Lemonldap/NG/Portal/Lib/OpenID/SREG.pm

246 lines
7.4 KiB
Perl
Raw Normal View History

2010-09-26 10:16:56 +02:00
## @file
2017-01-05 09:59:05 +01:00
# OpenID SREG extension for Lemonldap::NG::Portal::Issuer::OpenID class
2010-09-26 10:16:56 +02:00
## @class
2017-01-05 09:59:05 +01:00
# OpenID SREG extension for Lemonldap::NG::Portal::Issuer::OpenID class
2010-09-26 10:16:56 +02:00
2017-01-05 09:59:05 +01:00
package Lemonldap::NG::Portal::Lib::OpenID::SREG;
2010-09-26 10:16:56 +02:00
use strict;
use Lemonldap::NG::Common::Regexp;
## @method protected hash sregHook(hash prm)
# Hook called to add SREG parameters to the OpenID response
# @return Hash containing wanted parameters
sub sregHook {
2017-01-05 12:55:46 +01:00
my ( $self, $req, $u, $trust_root, $is_id, $is_trusted, $prm ) = @_;
2010-09-28 18:26:35 +02:00
my ( @req, @opt );
2010-09-26 10:16:56 +02:00
2010-09-29 08:42:48 +02:00
# Refuse federation if rejected by user
2017-01-06 07:02:52 +01:00
if ( $req->param('confirm') and $req->param('confirm') == -1 ) {
my %h;
$h{$_} = undef foreach (
qw(fullname nickname language postcode timezone country gender email dob)
);
2017-01-05 12:55:46 +01:00
$self->p->updatePersistentSession( \%h );
return 0;
}
2010-09-29 12:09:04 +02:00
# If identity is not trusted, does nothing
return ( 0, $prm ) unless ( $is_id and $is_trusted );
2010-09-26 10:16:56 +02:00
2010-09-28 18:26:35 +02:00
$self->lmLog( "SREG start", 'debug' );
2010-09-26 10:16:56 +02:00
my $accepted = 1;
2010-09-29 12:09:04 +02:00
# Check all parameters
2010-09-26 10:16:56 +02:00
while ( my ( $k, $v ) = each %$prm ) {
2010-09-29 12:09:04 +02:00
# Store policy if provided
2010-09-26 10:16:56 +02:00
if ( $k eq 'policy_url' ) {
if ( $v =~ Lemonldap::NG::Common::Regexp::HTTP_URI ) {
2017-01-05 12:55:46 +01:00
$req->datas->{_openIdTrustExtMsg} .=
'<dl><dt trspan="openidPA">' . "&nbsp;:</dt><dd><a href=\"$v\">$v</a></dd></dl>";
2010-09-28 18:26:35 +02:00
2010-09-29 12:09:04 +02:00
# Question: is it important to notify policy changes ?
# if yes, uncomment this
2010-09-28 18:26:35 +02:00
#my $p =
2017-01-05 12:55:46 +01:00
# $req->{sessionInfo}->{"_openidTrust$trust_root\_Policy"};
2010-09-28 18:26:35 +02:00
#$accepted = 0 unless ( $p and $p eq $v );
2010-09-26 10:16:56 +02:00
}
else {
$self->lmLog( "Bad policy url", 'error' );
}
}
2010-09-29 12:09:04 +02:00
# Parse required attributes
2010-09-26 10:16:56 +02:00
elsif ( $k eq 'required' ) {
2010-09-28 18:26:35 +02:00
$self->lmLog( "Required attr $v", 'debug' );
2010-09-26 10:16:56 +02:00
push @req, split( /,/, $v );
}
2010-09-29 12:09:04 +02:00
# Parse optional attributes
2010-09-26 10:16:56 +02:00
elsif ( $k eq 'optional' ) {
2010-09-28 18:26:35 +02:00
$self->lmLog( "Optional attr $v", 'debug' );
2017-01-05 12:55:46 +01:00
push @opt, grep { defined $self->conf->{"openIdSreg_$trust_root$_"} }
split( /,/, $v );
2010-09-26 10:16:56 +02:00
}
else {
$self->lmLog( "Unknown OpenID SREG request $k", 'error' );
}
}
# Check if required keys are valid SREG requests
2010-09-29 12:09:04 +02:00
# Question: reject bad SREG request ? Not done yet
2010-09-28 18:26:35 +02:00
@req = sregfilter( $self, @req );
@opt = sregfilter( $self, @opt );
2010-10-01 17:05:06 +02:00
# Return if nothing is asked
return ( 1, {} ) unless ( @req or @opt );
2010-09-26 10:16:56 +02:00
# If a required data is not available, returns nothing
foreach my $k (@req) {
2017-01-05 12:55:46 +01:00
unless ( $self->conf->{"openIdSreg_$k"} ) {
2010-09-26 10:16:56 +02:00
$self->lmLog(
2010-09-28 18:26:35 +02:00
"Parameter $k is required by $trust_root but not defined in configuration",
2010-09-26 10:16:56 +02:00
'notice'
);
2017-01-05 12:55:46 +01:00
$self->info( qq'<h3 trspan="openidRpns,$k"></h3>');
2010-09-26 10:16:56 +02:00
return ( 0, {} );
}
}
2010-09-26 15:09:46 +02:00
2010-09-28 18:26:35 +02:00
# Now set datas
2010-10-08 18:14:06 +02:00
my ( %r, %msg, %ag, %toStore );
2010-09-28 18:26:35 +02:00
# Requested parameters: check if already agreed or confirm is set
foreach my $k (@req) {
2017-01-05 12:55:46 +01:00
my $agree = $req->{sessionInfo}->{"_openidTrust$trust_root\_$k"};
2010-09-28 18:26:35 +02:00
if ($accepted) {
2017-01-05 12:55:46 +01:00
unless ( $req->param('confirm') or $agree ) {
2010-09-28 18:26:35 +02:00
$accepted = 0;
}
elsif ( !$agree ) {
2010-10-08 18:14:06 +02:00
$toStore{"_openidTrust$trust_root\_$k"} = 1;
2010-09-28 18:26:35 +02:00
}
}
2017-01-05 12:55:46 +01:00
my $tmp = $self->conf->{"openIdSreg_$k"};
$tmp =~ s/^\$//;
2010-09-28 18:26:35 +02:00
$msg{req}->{$k} = $r{$k} =
2017-01-05 12:55:46 +01:00
$req->{sessionInfo}->{ $self->{"openIdSreg_$k"} } || '';
2010-09-26 10:16:56 +02:00
}
2010-09-28 18:26:35 +02:00
# Optional parameters:
foreach my $k (@opt) {
2017-01-05 12:55:46 +01:00
my $tmp = $self->conf->{"openIdSreg_$k"};
$tmp =~ s/^\$//;
my $agree = $req->{sessionInfo}->{"_openidTrust$trust_root\_$k"};
2010-09-28 18:26:35 +02:00
if ($accepted) {
# First, check if already accepted
2017-01-05 12:55:46 +01:00
unless ( $req->param('confirm') or defined($agree) ) {
2010-09-28 18:26:35 +02:00
$accepted = 0;
2017-01-05 12:55:46 +01:00
$r{$k} = $req->{sessionInfo}->{$tmp}
2010-09-28 18:26:35 +02:00
|| '';
}
# If confirmation is returned, check the value for this field
2017-01-05 12:55:46 +01:00
elsif ( $req->param('confirm') == 1 ) {
2010-09-29 08:42:48 +02:00
my $ck = 0;
2017-01-05 12:55:46 +01:00
if ( defined( $req->param("sreg_$k") ) ) {
$ck = ( $req->param("sreg_$k") eq 'OK' ) || 0;
2010-09-28 18:26:35 +02:00
}
2010-09-29 08:42:48 +02:00
# Store the value returned
if ( !defined($agree) or $agree != $ck ) {
2010-10-08 18:14:06 +02:00
$toStore{"_openidTrust$trust_root\_$k"} = $ck;
2010-09-29 08:42:48 +02:00
$agree = $ck;
2010-09-28 18:26:35 +02:00
}
}
}
2017-01-05 12:55:46 +01:00
$msg{opt}->{$k} = $req->{sessionInfo}->{$tmp} || '';
2010-09-28 18:26:35 +02:00
# Store the value only if user agree it
if ($agree) {
$r{$k} = $msg{opt}->{$k};
$ag{$k} = 1;
}
2010-09-29 12:09:04 +02:00
elsif ( !defined($agree) ) {
$ag{$k} = 1;
}
2010-09-28 18:26:35 +02:00
else {
$ag{$k} = 0;
}
}
2017-01-05 12:55:46 +01:00
$self->p->updatePersistentSession( \%toStore ) if (%toStore);
2010-09-28 18:26:35 +02:00
# Check if user has agreed request
if ($accepted) {
2017-01-05 12:55:46 +01:00
$self->p->userInfo(
$req->{sessionInfo}->{ $self->conf->{whatToTrace} }
2010-09-28 18:26:35 +02:00
. " has accepted OpenID SREG exchange with $trust_root" );
return ( 1, \%r );
}
# else build message and return 0
else {
2017-01-05 12:55:46 +01:00
$req->datas->{_openIdTrustExtMsg} .= qq'<h3 trspan="openidAp"></h3>';
2017-01-05 12:55:46 +01:00
$req->datas->{_openIdTrustExtMsg} .= "<table class=\"openidsreg\">\n";
# No choice for requested parameters: just an information
2010-09-28 18:26:35 +02:00
foreach my $k (@req) {
utf8::decode( $msg{req}->{$k} );
2017-01-05 12:55:46 +01:00
$req->datas->{_openIdTrustExtMsg} .=
"<tr class=\"required\">\n" . "<td>"
. "<input type=\"checkbox\" disabled=\"disabled\" checked=\"checked\"/>"
. "</td>\n"
. "<td>$k</td>\n" . "<td>"
. $msg{req}->{$k}
. "</td>\n"
. "</tr>\n";
2010-09-28 18:26:35 +02:00
}
# For optional parameters: checkboxes are displayed
foreach my $k (@opt) {
utf8::decode( $msg{opt}->{$k} );
2017-01-05 12:55:46 +01:00
$req->datas->{_openIdTrustExtMsg} .=
2014-06-08 12:04:50 +02:00
"<tr class=\"optional\">\n"
. "<td>\n"
. "<input type=\"checkbox\" value=\"OK\""
2010-09-28 18:26:35 +02:00
. ( $ag{$k} ? 'checked="checked"' : '' )
. " name=\"sreg_$k\" />"
. "</td>\n"
. "<td>$k</td>\n" . "<td>"
. $msg{opt}->{$k}
. "</td>\n"
. "</tr>\n";
2010-09-28 18:26:35 +02:00
}
2017-01-05 12:55:46 +01:00
$req->datas->{_openIdTrustExtMsg} .= "</table>\n";
2010-09-28 18:26:35 +02:00
$self->lmLog( 'Building validation form', 'debug' );
return ( 0, $prm );
}
2010-09-26 10:16:56 +02:00
}
2010-09-29 12:09:04 +02:00
## @method private array sregfilter(array attr)
# Filter the arguments passed as parameters by checking their compliance with
# SREG.
# @return fitered datas
2010-09-28 18:26:35 +02:00
sub sregfilter {
my ( $self, @attr ) = @_;
2010-09-28 18:26:35 +02:00
my ( @ret, @rej );
# Browse attributes
2010-09-28 18:26:35 +02:00
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;
}
}
# Warn if some parameters are rejected
2010-10-04 19:27:32 +02:00
if (@rej) {
$self->lmLog(
"Requested parameter(s) "
. join( ',', @rej )
. "is(are) not valid OpenID SREG parameter(s)",
'warn'
2010-10-04 19:27:32 +02:00
);
}
# Return valid SREG parameters
2010-10-04 19:27:32 +02:00
return @ret;
2010-09-28 18:26:35 +02:00
}
2010-09-26 10:16:56 +02:00
1;