StayConnected plugin (#1131)

TODO: - check fingerprint back
      - insert "stayconnected" param in login.tpl
This commit is contained in:
Xavier Guimard 2017-03-07 22:20:51 +00:00
parent 4cf3762f38
commit 57189c1fb6
13 changed files with 203 additions and 3 deletions

View File

@ -2827,6 +2827,9 @@ qr/^(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-
'staticPrefix' => {
'type' => 'text'
},
'stayConnected' => {
'type' => 'bool'
},
'storePassword' => {
'default' => 0,
'type' => 'bool'

View File

@ -333,6 +333,10 @@ sub attributes {
default => '; ',
documentation => 'Separator for multiple values',
},
stayConnected => {
type => 'bool',
documentation => 'Enable StayConnected plugin',
},
# Manager
protection => {

View File

@ -510,6 +510,7 @@ sub tree {
{
title => 'plugins',
nodes => [
'stayConnected',
'portalStatus',
{
title => 'portalServers',

View File

@ -628,6 +628,7 @@
"SSLVar": "Extracted certificate field",
"SSLVarIf": "Conditional extracted certificate field",
"startTime": "Creation date",
"stayConnected": "Persistent connections",
"successfullySaved": "Successfully saved",
"storePassword": "Store user password in session datas",
"successLoginNumber": "Number of registered logins",

View File

@ -628,6 +628,7 @@
"SSLVar": "Champ extrait du certificat",
"SSLVarIf": "Champ conditionnel extrait du certificat",
"startTime": "Date de création",
"stayConnected": "Connexions persistantes",
"successfullySaved": "Sauvegarde effectuée",
"storePassword": "Stocke le mot de passe de l'utilisateur en session",
"successLoginNumber": "Nombre de connexions mémorisées",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -22,7 +22,7 @@ our @pList = (
u2fSelfRegistration => '::Register::U2F',
notification => '::Plugins::Notifications',
portalCheckLogins => '::Plugins::History',
sTokenService => '::Plugins::ServiceTokenServer',
stayConnected => '::Plugins::StayConnected',
);
##@method list enabledPlugins

View File

@ -0,0 +1,144 @@
# Plugin to enable "stay connected on this device" feature
package Lemonldap::NG::Portal::Plugins::StayConnected;
use 5.16.0;
use strict;
use Mouse;
use Lemonldap::NG::Portal::Main::Constants qw(
PE_OK
PE_SENDRESPONSE
);
our $VERSION = '2.0.0';
extends 'Lemonldap::NG::Portal::Main::Plugin';
# INTERFACE
use constant afterDatas => 'newDevice';
use constant beforeAuth => 'check';
# INITIALIZATION
has ott => (
is => 'rw',
default => sub {
my $ott =
$_[0]->{p}->loadModule('Lemonldap::NG::Portal::Lib::OneTimeToken');
$ott->timeout( $_[0]->conf->{formTimeout} );
return $ott;
}
);
sub init {
my ($self) = @_;
$self->addAuthRoute( registerbrowser => 'storeBrowser', ['POST'] );
}
# RUNNING METHODS
sub newDevice {
my ( $self, $req ) = @_;
if ( $req->param('stayconnected') ) {
my $token = $self->ott->createToken(
{
name => $req->sessionInfo->{ $self->conf->{whatToTrace} }
}
);
print STDERR Data::Dumper::Dumper($token);
use Data::Dumper;
$req->response(
$self->p->sendHtml(
$req,
'../common/registerBrowser',
params => {
URL => $req->urldc,
TOKEN => $token,
}
)
);
return PE_SENDRESPONSE;
}
return PE_OK;
}
sub storeBrowser {
my ( $self, $req ) = @_;
$req->urldc( $req->param('url') );
$req->mustRedirect(1);
if ( my $token = $req->param('token') ) {
if ( my $tmp = $self->ott->getToken($token) ) {
my $uid = $req->userData->{ $self->conf->{whatToTrace} };
if ( $tmp->{name} eq $uid ) {
if ( my $fg = $req->param('fg') ) {
my $ps = Lemonldap::NG::Common::Session->new(
storageModule => $self->conf->{persistentStorage},
storageModuleOptions =>
$self->conf->{persistentStorageOptions},
kind => "Persistent",
info => {
_session_uid => $uid,
_connectedSince => time,
dataKeep => $req->datas->{dataToKeep},
},
);
$req->addCookie(
$self->p->cookie(
name => 'llngconnexion',
value => $ps->id,
expires => '+1M',
)
);
}
else {
$self->logger->warn("Browser hasn't return fingerprint");
}
}
else {
$self->userLogger->error(
"StayConnected: mismatch UID: $tmp->{name} / $uid");
}
}
else {
$self->userLogger->error("StayConnected call with expired token");
}
}
else {
$self->userLogger->error('StayConnected call without token');
}
# Deliver cookie llngbrowser
return $self->p->do( $req, [ sub { PE_OK } ] );
}
sub check {
my ( $self, $req ) = @_;
if ( my $cid = $req->cookies->{llngconnexion} ) {
my $ps = Lemonldap::NG::Common::Session->new(
storageModule => $self->conf->{persistentStorage},
storageModuleOptions => $self->conf->{persistentStorageOptions},
kind => "Persistent",
id => $cid,
);
# TODO: verify fingerprint
if ( $ps and my $uid = $ps->data->{uid} ) {
$req->user($uid);
if ( $ps->data->{dataKeep} ) {
$req->data( $ps->data->{dataKeep} ) :;
}
my @steps =
grep { !ref $_ or $_ !~ /^(?:extractFormInfo|authenticate)$/ }
@{ $req->steps };
$req->steps( \@steps );
$self->userLogger->notice("$uid connected by StayConnected cookie");
return PE_OK;
}
}
return PE_OK;
}
1;

View File

@ -0,0 +1,4 @@
$(document).ready ->
new Fingerprint2().get (result, components) ->
$('#fg').attr "value", result
$('#form').submit()

View File

@ -0,0 +1,10 @@
// Generated by CoffeeScript 1.10.0
(function() {
$(document).ready(function() {
return new Fingerprint2().get(function(result, components) {
$('#fg').attr("value", result);
return $('#form').submit();
});
});
}).call(this);

View File

@ -0,0 +1 @@
(function(){$(document).ready(function(){return new Fingerprint2().get(function(a,b){$("#fg").attr("value",a);return $("#form").submit()})})}).call(this);

View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Register browser</title>
</head>
<body>
<p>Please wait...</p>
<form id="form" method="post" action="/registerbrowser">
<input type="hidden" name="token" value="<TMPL_VAR NAME="TOKEN">" />
<input type="hidden" name="url" value="<TMPL_VAR NAME="URL">" />
<input type="hidden" name="fg" id="fg" value="" />
</form>
<!-- //if:usedebianlibs
<script type="text/javascript" src="/javascript/jquery/jquery.min.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">bwr/fingerprintjs2/fingerprint2.min.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/registerbrowser.min.js"></script>
//elsif:useexternallibs
<script type="text/javascript" src="http://code.jquery.com/jquery-2.2.0.min.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">bwr/fingerprintjs2/fingerprint2.min.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/registerbrowser.min.js"></script>
//elsif:jsminified
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">bwr/jquery/dist/jquery.min.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">bwr/fingerprintjs2/fingerprint2.min.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/registerbrowser.min.js"></script>
//else -->
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">bwr/jquery/dist/jquery.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">bwr/fingerprintjs2/fingerprint2.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">common/js/registerbrowser.js"></script>
<!-- //endif -->
</body>
</html>