In progress... (#595)

This commit is contained in:
Xavier Guimard 2016-05-23 21:52:32 +00:00
parent c535422a98
commit 25365061de
7 changed files with 171 additions and 23 deletions

View File

@ -38,4 +38,8 @@ sub authLogout {
PE_OK;
}
sub getDisplayType {
return 'logo';
}
1;

View File

@ -0,0 +1,144 @@
package Lemonldap::NG::Portal::Auth::BrowserID;
use strict;
use Mouse;
use JSON;
use LWP::UserAgent;
use HTTP::Request;
use Lemonldap::NG::Portal::Main::Constants qw(PE_OK PE_ERROR PE_BADCREDENTIALS PE_FIRSTACCESS);
our $VERSION = '2.0.0';
extends 'Lemonldap::NG::Portal::Auth::Base';
## @method LWP::UserAgent ua()
# @return LWP::UserAgent object
has ua => (
is => 'rw',
lasy => 1,
builder => sub {
# TODO : LWP options to use a proxy for example
my $ua = LWP::UserAgent->new();
push @{ $ua->requests_redirectable }, 'POST';
$ua->env_proxy();
return $ua;
}
);
# Initialization: enables Browser ID (required for templates) and
# LWP::UserAgent object
sub init {
my ($self) = @_;
$self->p->{customParameters}->{browserIdEnabled} = 1;
foreach (
qw(browserIdSiteName browserIdSiteLogo browserIdBackgroundColor browserIdAutoLogin)
)
{
$self->p->{customParameters}->{$_} = $self->conf->{$_}
if ( $self->conf->{$_} );
}
return $self->ua;
}
## @apmethod int extractFormInfo()
# Get BrowserID assertion
# @return Lemonldap::NG::Portal constant
sub extractFormInfo {
my ( $self, $req ) = @_;
# Assertion should be browserIdAssertion parameter
if ( my $browserIdAssertion = $req->param('browserIdAssertion') ) {
$self->lmLog( "BrowserID Assertion found: $browserIdAssertion",
'debug' );
# Resolve assertion
my $postdata =
"assertion=$browserIdAssertion&audience=" . $self->conf->{portal};
$self->lmLog(
"Send $postdata to " . $self->conf->{browserIdVerificationURL},
'debug' );
# Prepare and launch request to BrowserID IdP
my $request = HTTP::Request->new(
'POST' => $self->conf->{browserIdVerificationURL} );
$request->content_type('application/x-www-form-urlencoded');
$request->content($postdata);
my $answer = $self->ua()->request($request);
$self->lmLog( "Verification response: " . $answer->as_string, 'debug' );
# Check if HTTP response is OK
if ( $answer->code() == "200" ) {
# Get JSON answser and decode it
my $browserIdAnswer = $answer->content;
$self->lmLog( "Received BrowserID answer: $browserIdAnswer",
'debug' );
eval { $browserIdAnswer = JSON::from_json($browserIdAnswer); };
if ($@) {
$self->lmLog( "JSON decode error: $@", 'error' );
return PE_ERROR;
}
# Then check for IdP response
if ( $browserIdAnswer->{status} eq "okay" ) {
$req->user( $browserIdAnswer->{email} );
$self->lmLog(
"Found user $req->user in BrowserID verification answer",
'debug' );
return PE_OK;
}
# Look for IdP rejection reason
else {
if ( $browserIdAnswer->{reason} ) {
$self->lmLog(
"Assertion $browserIdAssertion verification error: $browserIdAnswer->{reason}",
'error'
);
}
else {
$self->lmLog(
"Assertion $browserIdAssertion not verified by BrowserID provider",
'error'
);
}
return PE_BADCREDENTIALS;
}
}
else {
$self->lmLog(
"Fail to validate BrowserId assertion $browserIdAssertion: BrowserID server has returned a $answer->code code",
'error'
);
return PE_ERROR;
}
}
# No assertion, return to login page with BrowserID login script
$req->{customParameters}->{browserIdLoadLoginScript} = 1;
return PE_FIRSTACCESS;
}
sub authenticate {
PE_OK;
}
sub authLogout {
$_[1]->{customParameters}->{browserIdLoadLoginScript} = 1;
PE_OK;
}
sub authForce {
return PE_OK;
}
sub getDisplayType {
return 'logo';
}
1;

View File

@ -30,4 +30,12 @@ sub authLogout {
PE_OK;
}
sub getDisplayType {
return 'logo';
}
sub getDisplayType {
return '';
}
1;

View File

@ -15,7 +15,7 @@ sub display {
my $skin_dir = $self->conf->{templatesDir};
my $skinfile;
my %templateParams =
( %{ $self->customParameters }, %{ $req->customParameters } );
( %{ $self->customParameters }, %{ $req->{customParameters} // {} } );
# 0. Display error page
if ( my $http_error = $req->param('lmError') ) {
@ -97,7 +97,7 @@ sub display {
# 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->notification ) {
elsif ( my $notif = $req->{notification} ) {
$skinfile = 'notification';
%templateParams = (
AUTH_ERROR_TYPE => $req->error_type,
@ -281,7 +281,8 @@ sub display {
DISPLAY_YUBIKEY_FORM => $displayType eq "yubikeyform" ? 1
: 0,
DISPLAY_LOGO_FORM => $displayType eq "logo" ? 1 : 0,
module => $displayType eq "logo" ? $self->get_module('auth')
module => $displayType eq "logo"
? $self->getModule( $req, 'auth' )
: "",
AUTH_LOOP => [],
PORTAL_URL =>

View File

@ -119,7 +119,7 @@ sub checkLogout {
}
sub authLogout {
my $self = shift;
my ( $self, $req ) = @_;
return $self->_authentication->authLogout(@_);
}
@ -215,18 +215,18 @@ sub checkXSSAttack {
# -------------------------------------------------------
sub extractFormInfo {
my $self = shift;
return $self->_authentication->extractFormInfo(@_);
my ( $self, $req ) = @_;
return $self->_authentication->extractFormInfo($req);
}
sub getUser {
my $self = shift;
return $self->_userDB->getUser(@_);
my ( $self, $req ) = @_;
return $self->_userDB->getUser($req);
}
sub authenticate {
my $self = shift;
return $self->_authentication->authenticate(@_);
my ( $self, $req ) = @_;
return $self->_authentication->authenticate($req);
}
# Third block: Session data providing
@ -288,7 +288,7 @@ sub setMacros {
sub setGroups {
my ( $self, $req ) = @_;
return $self->_userDB->setGroups(@_);
return $self->_userDB->setGroups($req);
}
sub setPersistentSessionInfo {
@ -396,8 +396,6 @@ sub buildCookie {
expires => $self->conf->{cookieExpiration},
);
if ( $self->conf->{securedCookie} >= 2 ) {
shift;
shift;
push @{ $req->respHeaders },
'Set-Cookie' => $self->cookie(
name => $self->conf->{cookieName} . "http",
@ -407,7 +405,6 @@ sub buildCookie {
secure => 0,
HttpOnly => $self->conf->{httpOnly},
expires => $self->conf->{cookieExpiration},
@_,
);
}
PE_OK;

View File

@ -31,7 +31,7 @@ extends 'Lemonldap::NG::Common::PSGI::Request';
has steps => ( is => 'rw' );
# Datas shared between methods
has datas => ( is => 'rw', default => sub { {} } );
has datas => ( is => 'rw' );
# Session datas when created
has id => ( is => 'rw' );
@ -45,7 +45,7 @@ has respCookies => ( is => 'rw' );
has template => ( is => 'rw' );
# Custom template parameters
has customParameters => ( is => 'rw', default => sub { {} } );
has customParameters => ( is => 'rw' );
# Boolean to indicate that response must be a redirection
has mustRedirect => ( is => 'rw' );
@ -62,12 +62,6 @@ has info => ( is => 'rw' );
# Menu error
has menuError => ( is => 'rw' );
# Notification
has notification => ( is => 'rw' );
has _authChoice => ( is => 'rw' );
has _openidPortal => ( is => 'rw' );
# Error type
sub error_type {
my $req = shift;

View File

@ -112,7 +112,7 @@ my $id;
ok( $id = getCookies($res)->{lemonldap}, 'Get LLNG cookie' )
or explain( $res, 'Set-Cookie: something' );
count(4);
count(3);
while ( defined( my $url = shift(@tests) ) ) {
last if ( $url eq 'LOGOUT' );