Merge branch '2775' into 'v2.0'
Allow to continue notification process with JSON response See merge request lemonldap-ng/lemonldap-ng!279
This commit is contained in:
commit
fede7f01d3
|
@ -515,3 +515,14 @@ connect with any user, the message will be prompted.
|
|||
.. |image1| image:: /documentation/portal-notification.png
|
||||
:class: align-center
|
||||
|
||||
|
||||
JSON response
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
If a notification is pending, JSON response fields are:
|
||||
|
||||
- ``result``: ``0``
|
||||
- ``error``: ``36``
|
||||
- ``ciphered_id``: a ciphered session id is returned in this field.
|
||||
This id can be used to forward and continue the notification process if you call the REST ``/notifback`` endpoint
|
||||
with a LL::NG cookie built with this id.
|
||||
|
|
|
@ -5,7 +5,7 @@ use Mouse;
|
|||
use JSON qw(from_json);
|
||||
use POSIX qw(strftime);
|
||||
|
||||
our $VERSION = '2.0.12';
|
||||
our $VERSION = '2.0.15';
|
||||
|
||||
no warnings 'redefine';
|
||||
|
||||
|
@ -178,9 +178,8 @@ sub getNotifBack {
|
|||
|
||||
# Search for Lemonldap::NG cookie (ciphered)
|
||||
my $id;
|
||||
unless ( $id = $req->cookies->{ $self->{conf}->{cookieName} } ) {
|
||||
return $self->p->sendError( $req, 'No cookie found', 401 );
|
||||
}
|
||||
return $self->p->sendError( $req, 'No cookie found', 401 )
|
||||
unless ( $id = $req->cookies->{ $self->{conf}->{cookieName} } );
|
||||
|
||||
if ( $req->param('cancel') ) {
|
||||
$self->logger->debug('Cancel called -> remove ciphered cookie');
|
||||
|
@ -197,12 +196,13 @@ sub getNotifBack {
|
|||
return $self->p->do( $req, [] );
|
||||
}
|
||||
|
||||
# Look if all notifications have been accepted. If not, redirect to
|
||||
# portal
|
||||
# Look if all notifications have been accepted.
|
||||
# If not, redirect to Portal
|
||||
|
||||
# Try to decrypt Lemonldap::NG ciphered cookie
|
||||
$id = $self->p->HANDLER->tsv->{cipher}->decrypt($id)
|
||||
or return $self->p->sendError( $req, 'Unable to decrypt', 400 );
|
||||
or
|
||||
return $self->p->sendError( $req, 'Unable to decrypt ciphered id', 400 );
|
||||
|
||||
# Check that session exists
|
||||
$req->userData( $self->p->HANDLER->retrieveSession( $req, $id ) )
|
||||
|
|
|
@ -236,9 +236,8 @@ sub getNotifBack {
|
|||
|
||||
# Search for Lemonldap::NG cookie (ciphered)
|
||||
my $id;
|
||||
unless ( $id = $req->cookies->{ $self->{conf}->{cookieName} } ) {
|
||||
return $self->p->sendError( $req, 'No cookie found', 401 );
|
||||
}
|
||||
return $self->p->sendError( $req, 'No cookie found', 401 )
|
||||
unless ( $id = $req->cookies->{ $self->{conf}->{cookieName} } );
|
||||
|
||||
if ( $req->param('cancel') ) {
|
||||
$self->logger->debug('Cancel called -> remove ciphered cookie');
|
||||
|
@ -255,12 +254,12 @@ sub getNotifBack {
|
|||
return $self->p->do( $req, [] );
|
||||
}
|
||||
|
||||
# Look if all notifications have been accepted. If not, redirect to
|
||||
# portal
|
||||
# Look if all notifications have been accepted.
|
||||
# If not, redirect to Portal
|
||||
|
||||
# Try to decrypt Lemonldap::NG ciphered cookie
|
||||
$id = $self->p->HANDLER->tsv->{cipher}->decrypt($id)
|
||||
or return $self->sendError( $req, 'Unable to decrypt', 500 );
|
||||
or return $self->sendError( $req, 'Unable to decrypt ciphered id', 400 );
|
||||
|
||||
# Check that session exists
|
||||
$req->userData( $self->p->HANDLER->retrieveSession( $req, $id ) )
|
||||
|
@ -381,7 +380,6 @@ sub getNotifBack {
|
|||
|
||||
# One pending notification has been found and not accepted,
|
||||
# restart process to display pending notifications
|
||||
# TODO: is it a good idea to launch all 'endAuth' subs ?
|
||||
$self->logger->debug(
|
||||
'Pending notification has been found and not accepted');
|
||||
return $self->p->do( $req, [ @{ $self->p->endAuth } ] );
|
||||
|
|
|
@ -40,7 +40,7 @@ sub process {
|
|||
}
|
||||
}
|
||||
$self->logger->debug( "Returned " . $self->_formatProcessResult($err) )
|
||||
if ($err);
|
||||
if $err;
|
||||
return $err;
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ sub _formatProcessResult {
|
|||
sub restoreArgs {
|
||||
my ( $self, $req ) = @_;
|
||||
$req->mustRedirect(1);
|
||||
PE_OK;
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
sub importHandlerData {
|
||||
|
@ -87,7 +87,7 @@ sub importHandlerData {
|
|||
$req->{sessionInfo} = $req->userData;
|
||||
$req->id( $req->sessionInfo->{_session_id} );
|
||||
$req->user( $req->sessionInfo->{ $self->conf->{whatToTrace} } );
|
||||
PE_OK;
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
# Verify url and confirm parameter
|
||||
|
@ -191,7 +191,7 @@ sub controlUrl {
|
|||
$req->data->{_url} = $req->pdata->{_url} =
|
||||
encode_base64( $req->{urldc}, '' ); # Avoid \n or \r
|
||||
}
|
||||
PE_OK;
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
sub checkLogout {
|
||||
|
@ -200,7 +200,7 @@ sub checkLogout {
|
|||
$req->steps(
|
||||
[ @{ $self->beforeLogout }, 'authLogout', 'deleteSession' ] );
|
||||
}
|
||||
PE_OK;
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
sub checkUnauthLogout {
|
||||
|
@ -221,7 +221,7 @@ sub checkUnauthLogout {
|
|||
);
|
||||
$req->steps( [ sub { PE_LOGOUT_OK } ] );
|
||||
}
|
||||
PE_OK;
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
sub authLogout {
|
||||
|
@ -461,7 +461,6 @@ sub setSessionInfo {
|
|||
|
||||
# Call UserDB setSessionInfo
|
||||
return $self->_userDB->setSessionInfo($req);
|
||||
PE_OK;
|
||||
}
|
||||
|
||||
sub setMacros {
|
||||
|
@ -470,7 +469,7 @@ sub setMacros {
|
|||
$req->{sessionInfo}->{$_} =
|
||||
$self->_macros->{$_}->( $req, $req->sessionInfo );
|
||||
}
|
||||
PE_OK;
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
sub setGroups {
|
||||
|
@ -488,7 +487,6 @@ sub setPersistentSessionInfo {
|
|||
return PE_OK unless ( $key and length($key) );
|
||||
|
||||
my $persistentSession = $self->getPersistentSession($key);
|
||||
|
||||
if ($persistentSession) {
|
||||
$self->logger->debug("Persistent session found for $key");
|
||||
foreach my $k ( keys %{ $persistentSession->data } ) {
|
||||
|
@ -500,7 +498,7 @@ sub setPersistentSessionInfo {
|
|||
}
|
||||
}
|
||||
}
|
||||
PE_OK;
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
sub setLocalGroups {
|
||||
|
@ -520,7 +518,7 @@ sub setLocalGroups {
|
|||
$req->{sessionInfo}->{groups} =~
|
||||
s/^$self->{conf}->{multiValuesSeparator}//o;
|
||||
}
|
||||
PE_OK;
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
sub store {
|
||||
|
@ -547,11 +545,10 @@ sub store {
|
|||
foreach my $k ( keys %{ $req->{sessionInfo} } ) {
|
||||
next unless defined $req->{sessionInfo}->{$k};
|
||||
my $displayValue = $req->{sessionInfo}->{$k};
|
||||
if ( $self->conf->{hiddenAttributes}
|
||||
and $self->conf->{hiddenAttributes} =~ /\b$k\b/ )
|
||||
{
|
||||
$displayValue = '****';
|
||||
}
|
||||
$displayValue = '****'
|
||||
if ( $self->conf->{hiddenAttributes}
|
||||
and $self->conf->{hiddenAttributes} =~ /\b$k\b/ );
|
||||
|
||||
$self->logger->debug("Store $displayValue in session key $k");
|
||||
$self->_dump($displayValue) if ref($displayValue);
|
||||
$infos->{$k} = $req->{sessionInfo}->{$k};
|
||||
|
@ -563,7 +560,7 @@ sub store {
|
|||
force => $req->{force},
|
||||
info => $infos
|
||||
);
|
||||
return PE_APACHESESSIONERROR unless ($session);
|
||||
return PE_APACHESESSIONERROR unless $session;
|
||||
|
||||
# Update current request
|
||||
$req->id( $session->id );
|
||||
|
@ -582,7 +579,7 @@ sub store {
|
|||
. $req->{sessionInfo}->{_httpSession} );
|
||||
}
|
||||
$req->refresh(0);
|
||||
PE_OK;
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
sub buildCookie {
|
||||
|
@ -616,7 +613,7 @@ sub buildCookie {
|
|||
. $ref->{ $self->conf->{whatToTrace} }
|
||||
. " successfully authenticated at level $ref->{authenticationLevel}"
|
||||
);
|
||||
PE_OK;
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
sub secondFactor {
|
||||
|
@ -629,7 +626,7 @@ sub storeHistory {
|
|||
if ( $self->conf->{loginHistoryEnabled} ) {
|
||||
$self->registerLogin($req);
|
||||
}
|
||||
PE_OK;
|
||||
return PE_OK;
|
||||
}
|
||||
|
||||
1;
|
||||
|
|
|
@ -208,13 +208,10 @@ sub refresh {
|
|||
if (/^_/) {
|
||||
|
||||
# But not OIDC tokens, which can be refreshed
|
||||
if (
|
||||
delete $data{$_}
|
||||
if (
|
||||
/^(_oidc_access_token|_oidc_refresh_token|_oidc_access_token_eol)$/
|
||||
)
|
||||
{
|
||||
delete $data{$_};
|
||||
}
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
# Other variables should be refreshed
|
||||
|
@ -306,14 +303,10 @@ sub do {
|
|||
}
|
||||
|
||||
# Update history
|
||||
if ( $err == PE_SENDRESPONSE ) {
|
||||
return $req->response;
|
||||
}
|
||||
return $req->response if $err == PE_SENDRESPONSE;
|
||||
|
||||
# Remove userData if authentication fails
|
||||
if ( $err == PE_BADCREDENTIALS or $err == PE_BADOTP ) {
|
||||
$req->userData( {} );
|
||||
}
|
||||
$req->userData( {} ) if ( $err == PE_BADCREDENTIALS or $err == PE_BADOTP );
|
||||
|
||||
if ( !$self->conf->{noAjaxHook} and $req->wantJSON ) {
|
||||
$self->logger->debug('Processing to JSON response');
|
||||
|
@ -342,7 +335,15 @@ sub do {
|
|||
elsif ( $err > 0 and $err != PE_PASSWORD_OK and $err != PE_LOGOUT_OK ) {
|
||||
return $self->sendJSONresponse(
|
||||
$req,
|
||||
{ result => 0, error => $err },
|
||||
{
|
||||
result => 0,
|
||||
error => $err,
|
||||
(
|
||||
$err == PE_NOTIFICATION && $req->id
|
||||
? ( ciphered_id => $req->id )
|
||||
: ()
|
||||
)
|
||||
},
|
||||
code => 400
|
||||
);
|
||||
}
|
||||
|
@ -956,7 +957,6 @@ sub sendHtml {
|
|||
{
|
||||
$self->logger->debug(
|
||||
"Add SAML Discovery Protocol URL in CSP form-action");
|
||||
|
||||
$csp .= " " . $self->conf->{samlDiscoveryProtocolURL};
|
||||
}
|
||||
$csp .= ';';
|
||||
|
@ -1168,12 +1168,11 @@ sub _sumUpSession {
|
|||
$withoutUser
|
||||
? {}
|
||||
: { user => $session->{ $self->conf->{whatToTrace} } };
|
||||
$res->{$_} = $session->{$_}
|
||||
foreach (
|
||||
$res->{$_} = $session->{$_} foreach (
|
||||
"_utime", "ipAddr",
|
||||
keys %{ $self->conf->{sessionDataToRemember} },
|
||||
keys %{ $self->pluginSessionDataToRemember }
|
||||
);
|
||||
);
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use Test::More;
|
||||
use strict;
|
||||
use IO::String;
|
||||
use JSON;
|
||||
|
||||
require 't/test-lib.pm';
|
||||
|
||||
my $res;
|
||||
my $json;
|
||||
my $file = "$main::tmpDir/20160530_dwho_dGVzdHJlZg==.json";
|
||||
|
||||
open F, "> $file" or die($!);
|
||||
|
@ -33,9 +35,39 @@ my $client = LLNG::Manager::Test->new( {
|
|||
}
|
||||
}
|
||||
);
|
||||
use Lemonldap::NG::Portal::Main::Constants 'PE_NOTIFICATION';
|
||||
|
||||
# Try to authenticate
|
||||
# -------------------
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/',
|
||||
IO::String->new(
|
||||
'user=dwho&password=dwho&url=aHR0cDovL3Rlc3QxLmV4YW1wbGUuY29tLw=='),
|
||||
length => 64,
|
||||
),
|
||||
'Auth query (JSON required)'
|
||||
);
|
||||
ok( $json = eval { from_json( $res->[2]->[0] ) }, 'Response is JSON' )
|
||||
or print STDERR "$@\n" . Dumper($res);
|
||||
ok( $json->{result} == 0, ' Good result' )
|
||||
or explain( $json, 'result => 0' );
|
||||
ok( $json->{error} == PE_NOTIFICATION, ' Notificationtion is pending' )
|
||||
or explain( $json, 'error => 36' );
|
||||
my $id = $json->{ciphered_id};
|
||||
|
||||
# Verify that cookie can be deciphered (ciphered_id is valid)
|
||||
ok(
|
||||
$res = $client->_get(
|
||||
'/notifback',
|
||||
accept => 'text/html',
|
||||
cookie => "lemonldap=$id"
|
||||
),
|
||||
'Test received Id'
|
||||
);
|
||||
count(5);
|
||||
expectForm( $res, undef, '/notifback', 'reference1x1', 'url' );
|
||||
|
||||
ok(
|
||||
$res = $client->_post(
|
||||
'/',
|
||||
|
@ -48,7 +80,7 @@ ok(
|
|||
);
|
||||
count(1);
|
||||
expectOK($res);
|
||||
my $id = expectCookie($res);
|
||||
$id = expectCookie($res);
|
||||
expectForm( $res, undef, '/notifback', 'reference1x1', 'url' );
|
||||
|
||||
# Verify that cookie is ciphered (session invalid)
|
||||
|
@ -58,7 +90,7 @@ ok(
|
|||
query => 'url=aHR0cDovL3Rlc3QxLmV4YW1wbGUuY29tLw==',
|
||||
cookie => "lemonldap=$id",
|
||||
),
|
||||
'Test cookie received'
|
||||
'Test received cookie'
|
||||
);
|
||||
count(1);
|
||||
expectReject($res);
|
||||
|
|
Loading…
Reference in New Issue