Merge branch 'v2.0'
This commit is contained in:
commit
1212cd9ba2
7
Makefile
7
Makefile
|
@ -35,6 +35,7 @@ UNCOMPRESS=tar xzf
|
|||
LISTCOMPRESSED=tar tzf
|
||||
COMPRESSSUFFIX=tar.gz
|
||||
NGINX=/usr/sbin/nginx
|
||||
UGLIFYJSVERSION:=$(shell uglifyjs --version|perl -pe 's/^[^\d]*(\d).*$$/$$1/')
|
||||
|
||||
# Default directories install
|
||||
# ---------------------------
|
||||
|
@ -311,7 +312,11 @@ $(SRCMANAGERDIR)/site/htdocs/static/js/%.js: $(SRCMANAGERDIR)/site/coffee/%.coff
|
|||
|
||||
%.min.js: %.js
|
||||
@echo "Compressing $*.js"
|
||||
@uglifyjs $*.js --compress --mangle --comments='/Copyr/i' --source-map $*.min.js.map -o $*.min.js
|
||||
if test "$(UGLIFYJSVERSION)" = 2; then \
|
||||
uglifyjs $*.js --compress --mangle --comments='/Copyr/i' --source-map $*.min.js.map -o $*.min.js; \
|
||||
else \
|
||||
uglifyjs $*.js --compress --mangle --comments='/Copyr/i' --source-map -o $*.min.js; \
|
||||
fi
|
||||
|
||||
fastcgi-server/man/llng-fastcgi-server.1p: fastcgi-server/sbin/llng-fastcgi-server
|
||||
@echo Update FastCGI server man page
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
# To insert LLNG user id in Apache logs, declare this format and use it in
|
||||
# CustomLog directive
|
||||
#LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O" llng
|
||||
#LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O %{Lm-Remote-Custom}o" llng
|
||||
|
||||
# Manager virtual host (manager.__DNSDOMAIN__)
|
||||
<VirtualHost __VHOSTLISTEN__>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
# To insert LLNG user id in Apache logs, declare this format and use it in
|
||||
# CustomLog directive
|
||||
#LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O" llng
|
||||
#LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O %{Lm-Remote-Custom}o" llng
|
||||
|
||||
# Manager virtual host (manager.__DNSDOMAIN__)
|
||||
<VirtualHost __VHOSTLISTEN__>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
# To insert LLNG user id in Apache logs, declare this format and use it in
|
||||
# CustomLog directive
|
||||
#LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O" llng
|
||||
#LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O %{Lm-Remote-Custom}o" llng
|
||||
|
||||
# Manager virtual host (manager.__DNSDOMAIN__)
|
||||
<VirtualHost __VHOSTLISTEN__>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
log_format lm_combined '$remote_addr - $lmremote_user [$time_local] '
|
||||
'"$request" $status $body_bytes_sent '
|
||||
'"$http_referer" "$http_user_agent"';
|
||||
'"$http_referer" "$http_user_agent" $lmremote_custom';
|
||||
log_format lm_app '$remote_addr - $upstream_http_lm_remote_user [$time_local] '
|
||||
'"$request" $status $body_bytes_sent '
|
||||
'"$http_referer" "$http_user_agent"';
|
||||
'"$http_referer" "$http_user_agent" $lmremote_custom';
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
# To insert LLNG user id in Apache logs, declare this format and use it in
|
||||
# CustomLog directive
|
||||
#LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O" llng
|
||||
#LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O %{Lm-Remote-Custom}o" llng
|
||||
|
||||
# Portal Virtual Host (auth.__DNSDOMAIN__)
|
||||
<VirtualHost __VHOSTLISTEN__>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
# To insert LLNG user id in Apache logs, declare this format and use it in
|
||||
# CustomLog directive
|
||||
#LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O" llng
|
||||
#LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O %{Lm-Remote-Custom}o" llng
|
||||
|
||||
# Portal Virtual Host (auth.__DNSDOMAIN__)
|
||||
<VirtualHost __VHOSTLISTEN__>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
# To insert LLNG user id in Apache logs, declare this format and use it in
|
||||
# CustomLog directive
|
||||
#LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O" llng
|
||||
#LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O %{Lm-Remote-Custom}o" llng
|
||||
|
||||
# Portal Virtual Host (auth.__DNSDOMAIN__)
|
||||
<VirtualHost __VHOSTLISTEN__>
|
||||
|
|
|
@ -58,6 +58,7 @@ server {
|
|||
##################################
|
||||
auth_request /lmauth;
|
||||
auth_request_set $lmremote_user $upstream_http_lm_remote_user;
|
||||
auth_request_set $lmremote_custom $upstream_http_lm_remote_custom;
|
||||
auth_request_set $lmlocation $upstream_http_location;
|
||||
# If CDA is used, uncomment this
|
||||
#auth_request_set $cookie_value $upstream_http_set_cookie;
|
||||
|
@ -88,8 +89,9 @@ server {
|
|||
# Uncomment this if you use https only
|
||||
#add_header Strict-Transport-Security "max-age=15768000";
|
||||
|
||||
# Set REMOTE_USER (for FastCGI apps only)
|
||||
# Set REMOTE_USER and REMOTE_CUSTOM (for FastCGI apps only)
|
||||
#fastcgi_param REMOTE_USER $lmremote_user;
|
||||
#fastcgi_param REMOTE_CUSTOM $lmremote_custom;
|
||||
}
|
||||
|
||||
# Handle test CGI
|
||||
|
@ -100,6 +102,7 @@ server {
|
|||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_split_path_info ^(.*\.pl)(/.+)$;
|
||||
fastcgi_param REMOTE_USER $lmremote_user;
|
||||
fastcgi_param REMOTE_CUSTOM $lmremote_custom;
|
||||
|
||||
# Or with uWSGI
|
||||
#include /etc/nginx/uwsgi_params;
|
||||
|
|
|
@ -25,7 +25,7 @@ LoadModule headers_module /usr/lib/apache2/modules/mod_headers.so
|
|||
</Directory>
|
||||
LogFormat "%v:%p %h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||
LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O" llng
|
||||
LogFormat "%v:%p %h %l %{Lm-Remote-User}o %t \"%r\" %>s %O %{Lm-Remote-Custom}o" llng
|
||||
ErrorLog conf/apache2.log
|
||||
CustomLog conf/apache2.log vhost_combined
|
||||
|
||||
|
|
|
@ -207,5 +207,6 @@
|
|||
"sessionDataToRemember": {},
|
||||
"timeout": 72000,
|
||||
"userDB": "Same",
|
||||
"whatToTrace": "_whatToTrace"
|
||||
"whatToTrace": "_whatToTrace",
|
||||
"customToTrace": "mail"
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ server {
|
|||
try_files $uri $uri/ =404;
|
||||
auth_request /lmauth;
|
||||
auth_request_set $lmremote_user $upstream_http_lm_remote_user;
|
||||
auth_request_set $lmremote_custom $upstream_http_lm_remote_custom;
|
||||
auth_request_set $lmlocation $upstream_http_location;
|
||||
error_page 401 $lmlocation;
|
||||
include conf/nginx-lua-headers.conf;
|
||||
|
|
|
@ -372,10 +372,11 @@ languages = fr, en, it, vi, ar
|
|||
; Manager modules enabled
|
||||
; Set here the list of modules you want to see in manager interface
|
||||
; The first will be used as default module displayed
|
||||
enabledModules = conf, sessions, notifications, 2ndFA, viewer
|
||||
;enabledModules = conf, sessions, notifications, 2ndFA, viewer
|
||||
enabledModules = conf, sessions, notifications, 2ndFA
|
||||
|
||||
; To avoid restricted users to edit configuration, defaulModule MUST be different than 'conf'
|
||||
; 'viewer' is set by default
|
||||
; 'conf' is set by default
|
||||
;defaultModule = viewer
|
||||
|
||||
; Viewer module allows us to edit configuration in read-only mode
|
||||
|
@ -384,7 +385,7 @@ enabledModules = conf, sessions, notifications, 2ndFA, viewer
|
|||
;viewerAllowDiff = $uid ne 'dwho'
|
||||
;
|
||||
; Viewer options - Default values
|
||||
;viewerHiddenKeys = samlIDPMetaDataNodes samlSPMetaDataNodes
|
||||
;viewerHiddenKeys = samlIDPMetaDataNodes samlSPMetaDataNodes managerPassword ManagerDn globalStorageOptions persistentStorageOptions
|
||||
;viewerAllowBrowser = 0
|
||||
;viewerAllowDiff = 0
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ sub defaultValues {
|
|||
'ldapVersion' => 3,
|
||||
'linkedInAuthnLevel' => 1,
|
||||
'linkedInFields' => 'id,first-name,last-name,email-address',
|
||||
'linkedInScope' => 'r_basicprofile r_emailaddress',
|
||||
'linkedInScope' => 'r_liteprofile r_emailaddress',
|
||||
'linkedInUserField' => 'emailAddress',
|
||||
'localSessionStorage' => 'Cache::FileCache',
|
||||
'localSessionStorageOptions' => {
|
||||
|
|
|
@ -276,11 +276,11 @@ sub getMod {
|
|||
my ( $self, $req ) = @_;
|
||||
my ( $s, $m );
|
||||
unless ( $s = $req->params('sessionType') ) {
|
||||
$self->error('Session type is required');
|
||||
$self->error($req->error('Session type is required'));
|
||||
return ();
|
||||
}
|
||||
unless ( $m = $self->sessionTypes->{$s} ) {
|
||||
$self->error('Unknown (or unconfigured) session type');
|
||||
$self->error($req->error('Unknown (or unconfigured) session type'));
|
||||
return ();
|
||||
}
|
||||
if ( my $kind = $req->params('kind') ) {
|
||||
|
|
|
@ -92,6 +92,10 @@ sub handler {
|
|||
if ( $hdrs{'Lm-Remote-User'} ) {
|
||||
$r->user( $hdrs{'Lm-Remote-User'} );
|
||||
}
|
||||
if ( $hdrs{'Lm-Remote-Custom'} ) {
|
||||
$r->subprocess_env( REMOTE_CUSTOM => $hdrs{'Lm-Remote-Custom'} );
|
||||
}
|
||||
|
||||
my $i = 1;
|
||||
while ( $hdrs{"Headername$i"} ) {
|
||||
$r->headers_in->set( $hdrs{"Headername$i"} => $hdrs{"Headervalue$i"} )
|
||||
|
|
|
@ -81,6 +81,15 @@ sub set_user {
|
|||
$request->env->{'psgi.r'}->user($user);
|
||||
}
|
||||
|
||||
## @method void set_custom(string custom)
|
||||
# sets remote_custom
|
||||
# @param custom string custom_header
|
||||
sub set_custom {
|
||||
my ( $class, $request, $custom ) = @_;
|
||||
$request->env->{'psgi.r'}->subprocess_env( REMOTE_CUSTOM => $custom )
|
||||
if defined $custom;
|
||||
}
|
||||
|
||||
## @method void set_header_in(hash headers)
|
||||
# sets or modifies request headers
|
||||
# @param headers hash containing header names => header value
|
||||
|
|
|
@ -176,6 +176,13 @@ sub user {
|
|||
|| _whatToTrace => 'anonymous' };
|
||||
}
|
||||
|
||||
## @method hashRef custom()
|
||||
# @return hash of custom data
|
||||
sub custom {
|
||||
my ( $self, $req ) = @_;
|
||||
return { $Lemonldap::NG::Handler::Main::tsv->{customToTrace} };
|
||||
}
|
||||
|
||||
## @method string userId()
|
||||
# @return user identifier to log
|
||||
sub userId {
|
||||
|
@ -195,7 +202,7 @@ sub group {
|
|||
}
|
||||
|
||||
## @method PSGI::Response sendError($req,$err,$code)
|
||||
# Add user di to $err before calling Lemonldap::NG::Common::PSGI::sendError()
|
||||
# Add user id to $err before calling Lemonldap::NG::Common::PSGI::sendError()
|
||||
# @param $req Lemonldap::NG::Common::PSGI::Request
|
||||
# @param $err String to push
|
||||
# @code int HTTP error code (default to 500)
|
||||
|
|
|
@ -197,7 +197,7 @@ sub defaultValuesInit {
|
|||
securedCookie timeout timeoutActivity
|
||||
timeoutActivityInterval useRedirectOnError useRedirectOnForbidden
|
||||
useSafeJail whatToTrace handlerInternalCache
|
||||
handlerServiceTokenTTL
|
||||
handlerServiceTokenTTL customToTrace
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -147,6 +147,7 @@ sub run {
|
|||
|
||||
# ACCOUNTING (1. Inform web server)
|
||||
$class->set_user( $req, $session->{ $class->tsv->{whatToTrace} } );
|
||||
$class->set_custom( $req, $session->{ $class->tsv->{customToTrace} } );
|
||||
|
||||
# AUTHORIZATION
|
||||
return ( $class->forbidden( $req, $session ), $session )
|
||||
|
|
|
@ -41,6 +41,15 @@ sub set_user {
|
|||
push @{ $req->{respHeaders} }, 'Lm-Remote-User' => $user;
|
||||
}
|
||||
|
||||
## @method void set_custom(string custom)
|
||||
# sets remote_custom in response headers
|
||||
# @param custom string custom_value
|
||||
sub set_custom {
|
||||
my ( $class, $req, $custom ) = @_;
|
||||
push @{ $req->{respHeaders} }, 'Lm-Remote-Custom' => $custom
|
||||
if defined $custom;
|
||||
}
|
||||
|
||||
## @method void set_header_in(hash headers)
|
||||
# sets or modifies request headers
|
||||
# @param headers hash containing header names => header value
|
||||
|
|
|
@ -39,6 +39,7 @@ sub unset_header_in {
|
|||
*setServerSignature = *Lemonldap::NG::Handler::PSGI::Main::setServerSignature;
|
||||
*thread_share = *Lemonldap::NG::Handler::PSGI::Main::thread_share;
|
||||
*set_user = *Lemonldap::NG::Handler::PSGI::Main::set_user;
|
||||
*set_custom = *Lemonldap::NG::Handler::PSGI::Main::set_custom;
|
||||
*set_header_out = *Lemonldap::NG::Handler::PSGI::Main::set_header_out;
|
||||
*is_initial_req = *Lemonldap::NG::Handler::PSGI::Main::is_initial_req;
|
||||
*print = *Lemonldap::NG::Handler::PSGI::Main::print;
|
||||
|
|
|
@ -72,7 +72,7 @@ sub handler {
|
|||
my $i = 0;
|
||||
while ( my $k = shift @$hdrs ) {
|
||||
my $v = shift @$hdrs;
|
||||
if ( $k =~ /^(?:Lm-Remote-User|Cookie)$/ ) {
|
||||
if ( $k =~ /^(?:Lm-Remote-(?:User|Custom)|Cookie)$/ ) {
|
||||
push @convertedHdrs, $k, $v;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -52,7 +52,7 @@ sub init {
|
|||
return 0;
|
||||
}
|
||||
|
||||
$self->{enabledModules} ||= "conf, sessions, notifications, 2ndFA, viewer";
|
||||
$self->{enabledModules} ||= "conf, sessions, notifications, 2ndFA";
|
||||
my @links;
|
||||
my @enabledModules =
|
||||
map { push @links, $_; "Lemonldap::NG::Manager::" . ucfirst($_) }
|
||||
|
@ -88,10 +88,10 @@ sub init {
|
|||
);
|
||||
|
||||
# Avoid restricted users to access configuration by default route
|
||||
my $defaultMod = $self->{defaultModule} || 'viewer';
|
||||
my $defaultMod = $self->{defaultModule} || 'conf';
|
||||
$self->logger->debug("Default module -> $defaultMod");
|
||||
my ($index) =
|
||||
grep { $working[$_] =~ /::$defaultMod$/ } ( 0 .. $#working );
|
||||
grep { $working[$_] =~ /::$defaultMod$/i } ( 0 .. $#working );
|
||||
$index //= $#working;
|
||||
$self->logger->debug("Default index -> $index");
|
||||
$self->defaultRoute( $working[$index]->defaultRoute );
|
||||
|
|
|
@ -1022,6 +1022,9 @@ qr/(?:(?:https?):\/\/(?:(?:(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.]
|
|||
'customRegister' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
'customToTrace' => {
|
||||
'type' => 'lmAttrOrMacro'
|
||||
},
|
||||
'customUserDB' => {
|
||||
'type' => 'text'
|
||||
},
|
||||
|
@ -1555,7 +1558,7 @@ m[^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
|||
'type' => 'text'
|
||||
},
|
||||
'linkedInScope' => {
|
||||
'default' => 'r_basicprofile r_emailaddress',
|
||||
'default' => 'r_liteprofile r_emailaddress',
|
||||
'type' => 'text'
|
||||
},
|
||||
'linkedInUserField' => {
|
||||
|
|
|
@ -891,6 +891,11 @@ sub attributes {
|
|||
documentation => 'Session parameter used to fill REMOTE_USER',
|
||||
flags => 'hp',
|
||||
},
|
||||
customToTrace => {
|
||||
type => 'lmAttrOrMacro',
|
||||
documentation => 'Session parameter used to fill REMOTE_CUSTOM',
|
||||
flags => 'hp',
|
||||
},
|
||||
lwpOpts => {
|
||||
type => 'keyTextContainer',
|
||||
documentation => 'Options given to LWP::UserAgent',
|
||||
|
@ -3163,7 +3168,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
|
|||
},
|
||||
linkedInUserField => { type => 'text', default => 'emailAddress' },
|
||||
linkedInScope =>
|
||||
{ type => 'text', default => 'r_basicprofile r_emailaddress' },
|
||||
{ type => 'text', default => 'r_liteprofile r_emailaddress' },
|
||||
|
||||
# WebID
|
||||
webIDAuthnLevel => {
|
||||
|
|
|
@ -250,7 +250,9 @@ sub cTrees {
|
|||
]
|
||||
},
|
||||
],
|
||||
casAppMetaDataNode => [ {
|
||||
casAppMetaDataNode => [
|
||||
'casAppMetaDataExportedVars',
|
||||
{
|
||||
title => 'casAppMetaDataOptions',
|
||||
form => 'simpleInputContainer',
|
||||
nodes => [
|
||||
|
@ -259,7 +261,6 @@ sub cTrees {
|
|||
'casAppMetaDataOptionsRule'
|
||||
]
|
||||
},
|
||||
'casAppMetaDataExportedVars',
|
||||
],
|
||||
};
|
||||
}
|
||||
|
|
|
@ -511,7 +511,7 @@ sub tree {
|
|||
title => 'logParams',
|
||||
help => 'logs.html',
|
||||
form => 'simpleInputContainer',
|
||||
nodes => [ 'whatToTrace', 'hiddenAttributes' ]
|
||||
nodes => [ 'whatToTrace', 'customToTrace', 'hiddenAttributes' ]
|
||||
},
|
||||
{
|
||||
title => 'cookieParams',
|
||||
|
|
|
@ -383,6 +383,7 @@ sub _scanNodes {
|
|||
}
|
||||
elsif ($h) {
|
||||
hdebug(' opened');
|
||||
$self->confChanged(1);
|
||||
$self->set( $target, $key, $leaf->{title},
|
||||
$leaf->{data} );
|
||||
}
|
||||
|
@ -451,6 +452,7 @@ sub _scanNodes {
|
|||
}
|
||||
elsif ($h) {
|
||||
hdebug(' opened');
|
||||
$self->confChanged(1);
|
||||
$self->set( $target, $key, $leaf->{title},
|
||||
$leaf->{data} );
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Generated by CoffeeScript 1.12.7
|
||||
// Generated by CoffeeScript 1.12.8
|
||||
|
||||
/*
|
||||
* 2ndFA Session explorer
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -10,28 +10,6 @@ function templates(tpl,key) {
|
|||
switch(tpl){
|
||||
case 'casAppMetaDataNode':
|
||||
return [
|
||||
{
|
||||
"_nodes" : [
|
||||
{
|
||||
"get" : tpl+"s/"+key+"/"+"casAppMetaDataOptionsService",
|
||||
"id" : tpl+"s/"+key+"/"+"casAppMetaDataOptionsService",
|
||||
"title" : "casAppMetaDataOptionsService"
|
||||
},
|
||||
{
|
||||
"get" : tpl+"s/"+key+"/"+"casAppMetaDataOptionsUserAttribute",
|
||||
"id" : tpl+"s/"+key+"/"+"casAppMetaDataOptionsUserAttribute",
|
||||
"title" : "casAppMetaDataOptionsUserAttribute"
|
||||
},
|
||||
{
|
||||
"get" : tpl+"s/"+key+"/"+"casAppMetaDataOptionsRule",
|
||||
"id" : tpl+"s/"+key+"/"+"casAppMetaDataOptionsRule",
|
||||
"title" : "casAppMetaDataOptionsRule"
|
||||
}
|
||||
],
|
||||
"id" : "casAppMetaDataOptions",
|
||||
"title" : "casAppMetaDataOptions",
|
||||
"type" : "simpleInputContainer"
|
||||
},
|
||||
{
|
||||
"cnodes" : tpl+"s/"+key+"/"+"casAppMetaDataExportedVars",
|
||||
"default" : [
|
||||
|
@ -57,6 +35,28 @@ function templates(tpl,key) {
|
|||
"id" : tpl+"s/"+key+"/"+"casAppMetaDataExportedVars",
|
||||
"title" : "casAppMetaDataExportedVars",
|
||||
"type" : "keyTextContainer"
|
||||
},
|
||||
{
|
||||
"_nodes" : [
|
||||
{
|
||||
"get" : tpl+"s/"+key+"/"+"casAppMetaDataOptionsService",
|
||||
"id" : tpl+"s/"+key+"/"+"casAppMetaDataOptionsService",
|
||||
"title" : "casAppMetaDataOptionsService"
|
||||
},
|
||||
{
|
||||
"get" : tpl+"s/"+key+"/"+"casAppMetaDataOptionsUserAttribute",
|
||||
"id" : tpl+"s/"+key+"/"+"casAppMetaDataOptionsUserAttribute",
|
||||
"title" : "casAppMetaDataOptionsUserAttribute"
|
||||
},
|
||||
{
|
||||
"get" : tpl+"s/"+key+"/"+"casAppMetaDataOptionsRule",
|
||||
"id" : tpl+"s/"+key+"/"+"casAppMetaDataOptionsRule",
|
||||
"title" : "casAppMetaDataOptionsRule"
|
||||
}
|
||||
],
|
||||
"id" : "casAppMetaDataOptions",
|
||||
"title" : "casAppMetaDataOptions",
|
||||
"type" : "simpleInputContainer"
|
||||
}
|
||||
]
|
||||
;
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
// Generated by CoffeeScript 1.12.7
|
||||
// Generated by CoffeeScript 1.12.8
|
||||
|
||||
/*
|
||||
LemonLDAP::NG Manager client
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
// Generated by CoffeeScript 1.12.7
|
||||
// Generated by CoffeeScript 1.12.8
|
||||
|
||||
/*
|
||||
* Sessions explorer
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,4 +1,4 @@
|
|||
// Generated by CoffeeScript 1.12.7
|
||||
// Generated by CoffeeScript 1.12.8
|
||||
|
||||
/*
|
||||
LemonLDAP::NG Viewer client
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -205,6 +205,7 @@
|
|||
"customPassword":"وحدة كلمة المرورالمخصصة",
|
||||
"customPortalSkin":"غلاف البوابة مخصص",
|
||||
"customRegister":"وحدة تسجيل مخصص",
|
||||
"customToTrace":"REMOTE_CUSTOM",
|
||||
"customUserDB":"وحدة قاعدة البيانات المخصصة",
|
||||
"date":"تاريخ",
|
||||
"dbiAuthChain":"سلسلة",
|
||||
|
|
|
@ -205,6 +205,7 @@
|
|||
"customPassword":"Custom password module",
|
||||
"customPortalSkin":"Custom portal skin",
|
||||
"customRegister":"Custom register module",
|
||||
"customToTrace":"REMOTE_CUSTOM",
|
||||
"customUserDB":"Custom user DB module",
|
||||
"date":"Datum",
|
||||
"dbiAuthChain":"Chain",
|
||||
|
|
|
@ -205,6 +205,7 @@
|
|||
"customPassword":"Custom password module",
|
||||
"customPortalSkin":"Custom portal skin",
|
||||
"customRegister":"Custom register module",
|
||||
"customToTrace":"REMOTE_CUSTOM",
|
||||
"customUserDB":"Custom user DB module",
|
||||
"date":"Date",
|
||||
"dbiAuthChain":"Chain",
|
||||
|
|
|
@ -205,6 +205,7 @@
|
|||
"customPassword":"Module de mots-de-passe personnalisé",
|
||||
"customPortalSkin":"Style personnalisé du portail",
|
||||
"customRegister":"Module d'enregistrement personnalisé",
|
||||
"customToTrace":"REMOTE_CUSTOM",
|
||||
"customUserDB":"Module BD utilisateurs personnalisé",
|
||||
"date":"Date",
|
||||
"dbiAuthChain":"Chaîne",
|
||||
|
|
|
@ -205,6 +205,7 @@
|
|||
"customPassword":"Personalizza il modulo password",
|
||||
"customPortalSkin":"Personalizza faccia del portale ",
|
||||
"customRegister":"Personalizza modulo di registro",
|
||||
"customToTrace":"REMOTE_CUSTOM",
|
||||
"customUserDB":"Personalizza modulo utente DB",
|
||||
"date":"Data",
|
||||
"dbiAuthChain":"Catena",
|
||||
|
|
|
@ -205,6 +205,7 @@
|
|||
"customPassword":"Mô đun mật khẩu tùy chỉnh",
|
||||
"customPortalSkin":"Tùy chỉnh giao diện cổng thông tin",
|
||||
"customRegister":"Module đăng ký tùy chỉnh",
|
||||
"customToTrace":"REMOTE_CUSTOM",
|
||||
"customUserDB":"Mô đun DB người dùng tùy chỉnh",
|
||||
"date":"Ngày",
|
||||
"dbiAuthChain":"Chuỗi",
|
||||
|
|
|
@ -205,6 +205,7 @@
|
|||
"customPassword":"Custom password module",
|
||||
"customPortalSkin":"Custom portal skin",
|
||||
"customRegister":"Custom register module",
|
||||
"customToTrace":"REMOTE_CUSTOM",
|
||||
"customUserDB":"Custom user DB module",
|
||||
"date":"日期",
|
||||
"dbiAuthChain":"Chain",
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -21,7 +21,7 @@
|
|||
<!-- Last buttons, available languages -->
|
||||
</div>
|
||||
<ul class="hidden-xs nav navbar-nav" role="grid">
|
||||
<li ng-repeat="l in links" id="l in links"><a href="{{l.target}}" role="row" ng-mouseup="clickStyle={color: '#ffb84d'}"><strong><i ng-if="activeModule == l.title" ng-style="myStyle" class="glyphicon glyphicon-{{l.icon}}"></i><i ng-if="activeModule != l.title" class="glyphicon glyphicon-{{l.icon}}" ng-style="clickStyle"></i> <span ng-if="activeModule == l.title" ng-style="myStyle" ng-bind="translate(l.title)"></span><span ng-if="activeModule != l.title" ng-bind="translate(l.title)" ng-style="clickStyle"></span></strong></a></li>
|
||||
<li ng-repeat="l in links" id="l in links"><a href="{{l.target}}" role="row"><strong><i ng-if="activeModule == l.title" ng-style="myStyle" class="glyphicon glyphicon-{{l.icon}}"></i><i ng-if="activeModule != l.title" class="glyphicon glyphicon-{{l.icon}}" ng-style="clickStyle"></i> <span ng-if="activeModule == l.title" ng-style="myStyle" ng-bind="translate(l.title)"></span><span ng-if="activeModule != l.title" ng-bind="translate(l.title)" ng-style="clickStyle"></span></strong></a></li>
|
||||
</ul>
|
||||
<ul class="hidden-xs nav navbar-nav navbar-right">
|
||||
<li uib-dropdown>
|
||||
|
|
|
@ -119,13 +119,6 @@ sub getForm {
|
|||
return [ split /[, ]\s*/, $self->conf->{combinationForms} ]
|
||||
if ( $self->conf->{combinationForms} );
|
||||
|
||||
if ( $req->{error} > PE_OK ) {
|
||||
$self->logger->notice('Start over combination schema');
|
||||
my $stack = $self->stackSub->( $req->env );
|
||||
my ( $res, $name ) = $stack->[0]->[0]->( 'getForm', $req );
|
||||
return $res;
|
||||
}
|
||||
|
||||
my ( $nb, $stack ) = (
|
||||
$req->data->{dataKeep}->{combinationTry},
|
||||
$req->data->{combinationStack}
|
||||
|
@ -198,6 +191,7 @@ sub try {
|
|||
|
||||
# If more than 1 scheme is available
|
||||
my ( $res, $name );
|
||||
|
||||
if ( $nb < @$stack - 1 ) {
|
||||
|
||||
# TODO: change logLevel for userLog()
|
||||
|
|
|
@ -50,7 +50,16 @@ has linkedInPeopleEndpoint => (
|
|||
lazy => 1,
|
||||
default => sub {
|
||||
$_[0]->conf->{linkedInPeopleEndpoint}
|
||||
|| 'https://api.linkedin.com/v1/people/';
|
||||
|| 'https://api.linkedin.com/v2/me';
|
||||
}
|
||||
);
|
||||
|
||||
has linkedInEmailEndpoint => (
|
||||
is => 'ro',
|
||||
lazy => 1,
|
||||
default => sub {
|
||||
$_[0]->conf->{linkedInEmailEndpoint}
|
||||
|| 'https://api.linkedin.com/v2/emailAddress?q=members&projection=(elements*(handle~))';
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -123,13 +132,11 @@ sub extractFormInfo {
|
|||
|
||||
$self->logger->debug("Get access token $access_token from LinkedIn");
|
||||
|
||||
# Build People EndPoint URI
|
||||
my $linkedInPeopleEndpoint =
|
||||
$self->linkedInPeopleEndpoint . "~:("
|
||||
. $self->conf->{linkedInFields}
|
||||
. ")?format=json";
|
||||
# Call People EndPoint URI
|
||||
$self->logger->debug(
|
||||
"Call LinkedIn People Endpoint " . $self->linkedInPeopleEndpoint );
|
||||
|
||||
my $people_response = $self->ua->get( $linkedInPeopleEndpoint,
|
||||
my $people_response = $self->ua->get( $self->linkedInPeopleEndpoint,
|
||||
"Authorization" => "Bearer $access_token" );
|
||||
|
||||
if ( $people_response->is_error ) {
|
||||
|
@ -141,6 +148,9 @@ sub extractFormInfo {
|
|||
|
||||
my $people_content = $people_response->decoded_content;
|
||||
|
||||
$self->logger->debug(
|
||||
"Response from LinkedIn People API: $people_content");
|
||||
|
||||
eval {
|
||||
$json_hash = from_json( $people_content, { allow_nonref => 1 } );
|
||||
};
|
||||
|
@ -153,6 +163,39 @@ sub extractFormInfo {
|
|||
$req->data->{linkedInData}->{$_} = $json_hash->{$_};
|
||||
}
|
||||
|
||||
# Call Email EndPoint URI
|
||||
if ( $self->conf->{linkedInScope} =~ /r_emailaddress/ ) {
|
||||
|
||||
$self->logger->debug( "Call LinkedIn Email Endpoint "
|
||||
. $self->linkedInEmailEndpoint );
|
||||
|
||||
my $email_response = $self->ua->get( $self->linkedInEmailEndpoint,
|
||||
"Authorization" => "Bearer $access_token" );
|
||||
|
||||
if ( $email_response->is_error ) {
|
||||
$self->logger->error(
|
||||
"Bad authorization response: " . $email_response->message );
|
||||
$self->logger->debug( $email_response->content );
|
||||
return PE_ERROR;
|
||||
}
|
||||
|
||||
my $email_content = $email_response->decoded_content;
|
||||
|
||||
$self->logger->debug(
|
||||
"Response from LinkedIn Email API: $email_content");
|
||||
|
||||
eval {
|
||||
$json_hash = from_json( $email_content, { allow_nonref => 1 } );
|
||||
};
|
||||
if ($@) {
|
||||
$self->logger->error("Unable to decode JSON $email_content");
|
||||
return PE_ERROR;
|
||||
}
|
||||
|
||||
$req->data->{linkedInData}->{"emailAddress"} =
|
||||
$json_hash->{"elements"}->[0]{"handle~"}->{"emailAddress"};
|
||||
}
|
||||
|
||||
$req->user(
|
||||
$req->data->{linkedInData}->{ $self->conf->{linkedInUserField} } );
|
||||
|
||||
|
|
|
@ -38,6 +38,14 @@ sub authenticate {
|
|||
$self->setSecurity($req);
|
||||
return PE_ERROR;
|
||||
}
|
||||
$self->logger->debug( "REST result:" . ( $res->{result} || 'undef' ) );
|
||||
if ( $res->{info} ) {
|
||||
eval {
|
||||
$self->logger->debug(" $_ => $res->{info}->{$_}")
|
||||
foreach ( keys %{ $res->{info} } );
|
||||
};
|
||||
}
|
||||
$self->logger->error( 'No "info": ' . $@ ) if ($@);
|
||||
unless ( $res->{result} ) {
|
||||
$self->userLogger->warn(
|
||||
"Bad credentials for " . $req->user . ' (' . $req->address . ')' );
|
||||
|
|
|
@ -46,6 +46,10 @@ sub setAuthSessionInfo {
|
|||
PE_OK;
|
||||
}
|
||||
|
||||
sub getDisplayType {
|
||||
return "logo";
|
||||
}
|
||||
|
||||
sub authLogout {
|
||||
my ( $self, $req ) = @_;
|
||||
PE_OK;
|
||||
|
|
|
@ -605,14 +605,13 @@ sub run {
|
|||
if ( $flow eq "authorizationcode" ) {
|
||||
|
||||
# Store data in session
|
||||
my $codeSession = $self->getOpenIDConnectSession(
|
||||
undef,
|
||||
my $codeSession = $self->newAuthorizationCode(
|
||||
$rp,
|
||||
{
|
||||
redirect_uri => $oidc_request->{'redirect_uri'},
|
||||
scope => $oidc_request->{'scope'},
|
||||
client_id => $client_id,
|
||||
user_session_id => $req->id,
|
||||
_utime => time,
|
||||
nonce => $oidc_request->{'nonce'},
|
||||
code_challenge => $oidc_request->{'code_challenge'},
|
||||
code_challenge_method =>
|
||||
|
@ -648,13 +647,12 @@ sub run {
|
|||
|
||||
# Store data in access token
|
||||
# Generate access_token
|
||||
my $accessTokenSession = $self->getOpenIDConnectSession(
|
||||
undef,
|
||||
my $accessTokenSession = $self->newAccessToken(
|
||||
$rp,
|
||||
{
|
||||
scope => $oidc_request->{'scope'},
|
||||
rp => $rp,
|
||||
user_session_id => $req->id,
|
||||
_utime => time,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -774,14 +772,13 @@ sub run {
|
|||
my ($hash_level) = ( $alg =~ /(?:\w{2})(\d{3})/ );
|
||||
|
||||
# Store data in session
|
||||
my $codeSession = $self->getOpenIDConnectSession(
|
||||
undef,
|
||||
my $codeSession = $self->newAuthorizationCode(
|
||||
$rp,
|
||||
{
|
||||
redirect_uri => $oidc_request->{'redirect_uri'},
|
||||
client_id => $client_id,
|
||||
scope => $oidc_request->{'scope'},
|
||||
user_session_id => $req->id,
|
||||
_utime => time,
|
||||
nonce => $oidc_request->{'nonce'},
|
||||
}
|
||||
);
|
||||
|
@ -798,13 +795,12 @@ sub run {
|
|||
if ( $response_type =~ /\btoken\b/ ) {
|
||||
|
||||
# Generate access_token
|
||||
my $accessTokenSession = $self->getOpenIDConnectSession(
|
||||
undef,
|
||||
my $accessTokenSession = $self->newAccessToken(
|
||||
$rp,
|
||||
{
|
||||
scope => $oidc_request->{'scope'},
|
||||
rp => $rp,
|
||||
user_session_id => $req->id,
|
||||
_utime => time,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1056,7 +1052,7 @@ sub token {
|
|||
|
||||
$self->logger->debug("OpenID Connect Code: $code");
|
||||
|
||||
my $codeSession = $self->getOpenIDConnectSession($code);
|
||||
my $codeSession = $self->getAuthorizationCode($code);
|
||||
|
||||
unless ($codeSession) {
|
||||
$self->logger->error("Unable to find OIDC session $code");
|
||||
|
@ -1115,13 +1111,12 @@ sub token {
|
|||
$self->logger->debug("Found corresponding user: $user_id");
|
||||
|
||||
# Generate access_token
|
||||
my $accessTokenSession = $self->getOpenIDConnectSession(
|
||||
undef,
|
||||
my $accessTokenSession = $self->newAccessToken(
|
||||
$rp,
|
||||
{
|
||||
scope => $codeSession->data->{scope},
|
||||
rp => $rp,
|
||||
user_session_id => $apacheSession->id,
|
||||
_utime => time,
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -1210,7 +1205,7 @@ sub userInfo {
|
|||
|
||||
$self->logger->debug("Received Access Token $access_token");
|
||||
|
||||
my $accessTokenSession = $self->getOpenIDConnectSession($access_token);
|
||||
my $accessTokenSession = $self->getAccessToken($access_token);
|
||||
|
||||
unless ($accessTokenSession) {
|
||||
$self->userLogger->error(
|
||||
|
|
|
@ -630,15 +630,65 @@ sub decodeJSON {
|
|||
return $json_hash;
|
||||
}
|
||||
|
||||
# Create a new Authorization Code
|
||||
# @param info hashref of session info
|
||||
# @return new Lemonldap::NG::Common::Session object
|
||||
|
||||
sub newAuthorizationCode {
|
||||
my ( $self, $rp, $info ) = @_;
|
||||
|
||||
return $self->getOpenIDConnectSession( undef, "authorization_code", undef,
|
||||
$info );
|
||||
}
|
||||
|
||||
# Get existing Authorization Code
|
||||
# @param id
|
||||
# @return new Lemonldap::NG::Common::Session object
|
||||
|
||||
sub getAuthorizationCode {
|
||||
my ( $self, $id ) = @_;
|
||||
|
||||
return $self->getOpenIDConnectSession( $id, "authorization_code" );
|
||||
}
|
||||
|
||||
# Create a new Access Token
|
||||
# @param info hashref of session info
|
||||
# @return new Lemonldap::NG::Common::Session object
|
||||
|
||||
sub newAccessToken {
|
||||
my ( $self, $rp, $info ) = @_;
|
||||
|
||||
return $self->getOpenIDConnectSession(
|
||||
undef,
|
||||
"access_token",
|
||||
$self->conf->{oidcRPMetaDataOptions}->{$rp}
|
||||
->{oidcRPMetaDataOptionsAccessTokenExpiration},
|
||||
$info
|
||||
);
|
||||
}
|
||||
|
||||
# Get existing Access Token
|
||||
# @param id
|
||||
# @return new Lemonldap::NG::Common::Session object
|
||||
|
||||
sub getAccessToken {
|
||||
my ( $self, $id ) = @_;
|
||||
|
||||
return $self->getOpenIDConnectSession( $id, "access_token" );
|
||||
}
|
||||
|
||||
# Try to recover the OpenID Connect session corresponding to id and return session
|
||||
# If id is set to undef, return a new session
|
||||
# @return Lemonldap::NG::Common::Session object
|
||||
sub getOpenIDConnectSession {
|
||||
my ( $self, $id, $info ) = @_;
|
||||
my ( $self, $id, $type, $ttl, $info ) = @_;
|
||||
my %storage = (
|
||||
storageModule => $self->conf->{oidcStorage},
|
||||
storageModuleOptions => $self->conf->{oidcStorageOptions},
|
||||
);
|
||||
|
||||
$ttl ||= $self->conf->{timeout};
|
||||
|
||||
unless ( $storage{storageModule} ) {
|
||||
%storage = (
|
||||
storageModule => $self->conf->{globalStorage},
|
||||
|
@ -652,7 +702,17 @@ sub getOpenIDConnectSession {
|
|||
cacheModuleOptions => $self->conf->{localSessionStorageOptions},
|
||||
id => $id,
|
||||
kind => $self->sessionKind,
|
||||
( $info ? ( info => $info ) : () ),
|
||||
(
|
||||
$info
|
||||
? (
|
||||
info => {
|
||||
_type => $type,
|
||||
_utime => time + $ttl - $self->conf->{timeout},
|
||||
%{$info}
|
||||
}
|
||||
)
|
||||
: ()
|
||||
),
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -668,6 +728,26 @@ sub getOpenIDConnectSession {
|
|||
return undef;
|
||||
}
|
||||
|
||||
if ($id) {
|
||||
my $storedType = $oidcSession->{data}->{_type};
|
||||
|
||||
# Only check if a type is set in DB, for backward compatibility
|
||||
if ( $storedType and $type ne $storedType ) {
|
||||
$self->logger->error( "Wrong OpenID session type: "
|
||||
. $oidcSession->{data}->{_type}
|
||||
. ". Expected: "
|
||||
. $type );
|
||||
return undef;
|
||||
}
|
||||
}
|
||||
|
||||
# Make sure the token is still valid, we already compensated for
|
||||
# different TTLs when storing _utime
|
||||
if ( time > ( $oidcSession->{data}->{_utime} + $self->conf->{timeout} ) ) {
|
||||
$self->logger->error("Session $id has expired");
|
||||
return undef;
|
||||
}
|
||||
|
||||
return $oidcSession;
|
||||
}
|
||||
|
||||
|
@ -980,8 +1060,8 @@ sub createHash {
|
|||
# @param fragment Set to true to return fragment component
|
||||
# @return void
|
||||
sub returnRedirectError {
|
||||
my ( $self, $req, $redirect_url, $error, $error_description, $error_uri,
|
||||
$state, $fragment )
|
||||
my ( $self, $req, $redirect_url, $error, $error_description,
|
||||
$error_uri, $state, $fragment )
|
||||
= @_;
|
||||
|
||||
my $urldc =
|
||||
|
@ -1401,7 +1481,10 @@ sub addRouteFromConf {
|
|||
$self->logger->error("$_ parameter not defined");
|
||||
next;
|
||||
}
|
||||
$self->$adder( $self->path => { $path => $sub }, [ 'GET', 'POST' ] );
|
||||
$self->$adder(
|
||||
$self->path => { $path => $sub },
|
||||
[ 'GET', 'POST' ]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1524,6 +1607,22 @@ Get UserInfo response
|
|||
|
||||
Convert JSON to HashRef
|
||||
|
||||
=head2 newAuthorizationCode
|
||||
|
||||
Generate new Authorization Code session
|
||||
|
||||
=head2 newAccessToken
|
||||
|
||||
Generate new Access Token session
|
||||
|
||||
=head2 getAuthorizationCode
|
||||
|
||||
Get existing Authorization Code session
|
||||
|
||||
=head2 getAccessToken
|
||||
|
||||
Get existing Access Token session
|
||||
|
||||
=head2 getOpenIDConnectSession
|
||||
|
||||
Try to recover the OpenID Connect session corresponding to id and return session
|
||||
|
|
|
@ -17,6 +17,13 @@ has ua => (
|
|||
|
||||
sub restCall {
|
||||
my ( $self, $url, $content ) = @_;
|
||||
$self->logger->debug("REST: trying to call $url with:");
|
||||
eval {
|
||||
foreach ( keys %$content ) {
|
||||
$self->logger->debug(
|
||||
" $_: " . ( /password/ ? '****' : $content->{$_} ) );
|
||||
}
|
||||
};
|
||||
my $hreq = HTTP::Request->new( POST => $url );
|
||||
$hreq->header( 'Content-Type' => 'application/json' );
|
||||
$hreq->content( to_json($content) );
|
||||
|
|
|
@ -259,6 +259,13 @@ sub display {
|
|||
or ( not $req->data->{noerror}
|
||||
and $req->userData
|
||||
and %{ $req->userData } )
|
||||
|
||||
# Avoid issue 1867
|
||||
or ( $self->conf->{authentication} eq 'Combination'
|
||||
and $req->{error} > PE_OK
|
||||
and $req->{error} != PE_FIRSTACCESS )
|
||||
|
||||
# and ( $req->{error} == PE_TOKENEXPIRED or $req->{error} == PE_NOTOKEN )
|
||||
)
|
||||
{
|
||||
$skinfile = 'error';
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
document.onreadystatechange = () ->
|
||||
if document.readyState == "complete"
|
||||
redirect = document.getElementById('redirect').textContent.replace /\s/g, ''
|
||||
try
|
||||
redirect = document.getElementById('redirect').textContent.replace /\s/g, ''
|
||||
catch
|
||||
redirect = document.getElementById('redirect').innerHTML.replace /\s/g, ''
|
||||
if redirect
|
||||
if redirect == 'form'
|
||||
document.getElementById('form').submit()
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
document.onreadystatechange = function() {
|
||||
var redirect;
|
||||
if (document.readyState === "complete") {
|
||||
redirect = document.getElementById('redirect').textContent.replace(/\s/g, '');
|
||||
try {
|
||||
redirect = document.getElementById('redirect').textContent.replace(/\s/g, '');
|
||||
} catch (error) {
|
||||
redirect = document.getElementById('redirect').innerHTML.replace(/\s/g, '');
|
||||
}
|
||||
if (redirect) {
|
||||
if (redirect === 'form') {
|
||||
return document.getElementById('form').submit();
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
(function(){document.onreadystatechange=function(){var e;if("complete"===document.readyState)return e=document.getElementById("redirect").textContent.replace(/\s/g,""),e?"form"===e?document.getElementById("form").submit():document.location.href=e:console.log("No redirection !")}}).call(this);
|
||||
//# sourceMappingURL=lemonldap-ng-portal/site/htdocs/static/common/js/redirect.min.js.map
|
||||
//# sourceMappingURL=lemonldap-ng-portal/site/htdocs/static/common/js/redirect.min.js.map
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"version":3,"sources":["lemonldap-ng-portal/site/htdocs/static/common/js/redirect.js"],"names":["document","onreadystatechange","redirect","readyState","getElementById","textContent","replace","submit","location","href","console","log","call","this"],"mappings":"CACA,WACEA,SAASC,mBAAqB,WAC5B,GAAIC,EACJ,IAA4B,aAAxBF,SAASG,WAEX,MADAD,GAAWF,SAASI,eAAe,YAAYC,YAAYC,QAAQ,MAAO,IACtEJ,EACe,SAAbA,EACKF,SAASI,eAAe,QAAQG,SAEhCP,SAASQ,SAASC,KAAOP,EAG3BQ,QAAQC,IAAI,uBAKxBC,KAAKC","file":"lemonldap-ng-portal/site/htdocs/static/common/js/redirect.min.js"}
|
||||
{"version":3,"sources":["lemonldap-ng-portal/site/htdocs/static/common/js/redirect.js"],"names":["document","onreadystatechange","redirect","readyState","getElementById","textContent","replace","submit","location","href","console","log","call","this"],"mappings":"CACA,WACEA,SAASC,mBAAqB,WAC5B,GAAIC,EACJ,IAA4B,aAAxBF,SAASG,WAEX,MADAD,GAAWF,SAASI,eAAe,YAAYC,YAAYC,QAAQ,MAAO,IACtEJ,EACe,SAAbA,EACKF,SAASI,eAAe,QAAQG,SAEhCP,SAASQ,SAASC,KAAOP,EAG3BQ,QAAQC,IAAI,uBAKxBC,KAAKC","file":"lemonldap-ng-portal/site/htdocs/static/common/js/redirect.min.js"}
|
||||
|
|
|
@ -8,11 +8,12 @@ my $res;
|
|||
|
||||
my $client = LLNG::Manager::Test->new( {
|
||||
ini => {
|
||||
logLevel => 'error',
|
||||
useSafeJail => 1,
|
||||
'corsAllow_Origin' => '',
|
||||
'corsAllow_Methods' => 'POST',
|
||||
'cspFormAction' => '*'
|
||||
logLevel => 'error',
|
||||
useSafeJail => 1,
|
||||
corsAllow_Origin => '',
|
||||
corsAllow_Methods => 'POST',
|
||||
cspFormAction => '*',
|
||||
customToTrace => 'mail'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -37,44 +38,33 @@ ok( $res->[2]->[0] =~ m%<span id="languages"></span>%, ' Language icons found' )
|
|||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
count(2);
|
||||
|
||||
my %policy = @{ $res->[1] };
|
||||
|
||||
# CORS
|
||||
ok( $res->[1]->[12] eq 'Access-Control-Allow-Origin', ' CORS origin found' )
|
||||
ok( $policy{'Access-Control-Allow-Origin'} eq '', "CORS origin '' found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[13] eq '', " CORS origin ''" )
|
||||
ok( $policy{'Access-Control-Allow-Credentials'} eq 'true',
|
||||
"CORS credentials 'true' found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[14] eq 'Access-Control-Allow-Credentials',
|
||||
' CORS credentials found' )
|
||||
ok( $policy{'Access-Control-Allow-Headers'} eq '*', "CORS headers '*' found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[15] eq 'true', " CORS credentials 'true'" )
|
||||
ok( $policy{'Access-Control-Allow-Methods'} eq 'POST',
|
||||
"CORS methods 'POST' found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[16] eq 'Access-Control-Allow-Headers', " CORS headers found" )
|
||||
ok( $policy{'Access-Control-Expose-Headers'} eq '*',
|
||||
"CORS expose-headers '*' found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[17] eq '*', " CORS headers '*'" )
|
||||
ok( $policy{'Access-Control-Max-Age'} eq '86400', "CORS max-age '86400' found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[18] eq 'Access-Control-Allow-Methods', " CORS methods found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[19] eq 'POST', " CORS methods 'POST'" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[20] eq 'Access-Control-Expose-Headers',
|
||||
" CORS expose-headers found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[21] eq '*', " CORS expose-headers '*'" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[22] eq 'Access-Control-Max-Age', ' CORS max-age found' )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[23] == 86400, ' CORS max-age 86400' )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
count(12);
|
||||
count(6);
|
||||
|
||||
#CSP
|
||||
ok( $res->[1]->[26] eq 'Content-Security-Policy', ' CSP found' )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok(
|
||||
$res->[1]->[27] =~
|
||||
$policy{'Content-Security-Policy'} =~
|
||||
/default-src 'self';img-src 'self' data:;style-src 'self';font-src 'self';connect-src 'self';script-src 'self';form-action \*;frame-ancestors 'none'/,
|
||||
' CSP headers found'
|
||||
'CSP header value found'
|
||||
) or print STDERR Dumper( $res->[1] );
|
||||
count(2);
|
||||
count(1);
|
||||
|
||||
# Try to authenticate with good password
|
||||
# --------------------------------------
|
||||
|
@ -115,39 +105,36 @@ ok(
|
|||
);
|
||||
count(1);
|
||||
|
||||
ok( $res->[1]->[14] eq 'Access-Control-Allow-Origin', ' CORS origin found' )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[15] eq '', " CORS origin ''" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[16] eq 'Access-Control-Allow-Credentials',
|
||||
' CORS credentials found' )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[17] eq 'true', " CORS credentials 'true'" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[18] eq 'Access-Control-Allow-Headers', " CORS headers found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[19] eq '*', " CORS headers '*'" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[20] eq 'Access-Control-Allow-Methods', " CORS methods found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[21] eq 'POST', " CORS methods 'POST'" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[22] eq 'Access-Control-Expose-Headers',
|
||||
" CORS expose-headers found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[23] eq '*', " CORS expose-headers '*'" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[24] eq 'Access-Control-Max-Age', ' CORS max-age found' )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $res->[1]->[25] == 86400, ' CORS max-age 86400' )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
count(12);
|
||||
%policy = @{ $res->[1] };
|
||||
|
||||
# Lm-Remote headers
|
||||
ok( $policy{'Lm-Remote-User'} eq 'dwho', "Lm-Remote-User found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $policy{'Lm-Remote-Custom'} eq 'dwho@badwolf.org',
|
||||
"Lm-Remote-Custom found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
count(2);
|
||||
|
||||
# CORS
|
||||
ok( $policy{'Access-Control-Allow-Origin'} eq '', "CORS origin '' found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $policy{'Access-Control-Allow-Credentials'} eq 'true',
|
||||
"CORS credentials 'true' found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $policy{'Access-Control-Allow-Headers'} eq '*', "CORS headers '*' found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $policy{'Access-Control-Allow-Methods'} eq 'POST',
|
||||
"CORS methods 'POST' found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $policy{'Access-Control-Expose-Headers'} eq '*',
|
||||
"CORS expose-headers '*' found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
ok( $policy{'Access-Control-Max-Age'} eq '86400', "CORS max-age '86400' found" )
|
||||
or print STDERR Dumper( $res->[1] );
|
||||
count(6);
|
||||
|
||||
# Test logout
|
||||
$client->logout($id);
|
||||
|
||||
#print STDERR Dumper($res);
|
||||
|
||||
clean_sessions();
|
||||
|
||||
done_testing( count() );
|
||||
|
|
|
@ -5,6 +5,7 @@ use IO::String;
|
|||
use LWP::UserAgent;
|
||||
use LWP::Protocol::PSGI;
|
||||
use MIME::Base64;
|
||||
use JSON;
|
||||
|
||||
BEGIN {
|
||||
require 't/test-lib.pm';
|
||||
|
@ -54,7 +55,7 @@ my $op = LLNG::Manager::Test->new( {
|
|||
oidcRPMetaDataOptionsIDTokenSignAlg => "HS512",
|
||||
oidcRPMetaDataOptionsClientSecret => "rpsecret",
|
||||
oidcRPMetaDataOptionsUserIDAttr => "",
|
||||
oidcRPMetaDataOptionsAccessTokenExpiration => 3600,
|
||||
oidcRPMetaDataOptionsAccessTokenExpiration => 1,
|
||||
oidcRPMetaDataOptionsBypassConsent => 1,
|
||||
},
|
||||
rp2 => {
|
||||
|
@ -64,7 +65,7 @@ my $op = LLNG::Manager::Test->new( {
|
|||
oidcRPMetaDataOptionsIDTokenSignAlg => "HS512",
|
||||
oidcRPMetaDataOptionsClientSecret => "rp2secret",
|
||||
oidcRPMetaDataOptionsUserIDAttr => "",
|
||||
oidcRPMetaDataOptionsAccessTokenExpiration => 3600,
|
||||
oidcRPMetaDataOptionsAccessTokenExpiration => 1,
|
||||
oidcRPMetaDataOptionsBypassConsent => 1,
|
||||
oidcRPMetaDataOptionsRule => '$uid eq "dwho"',
|
||||
}
|
||||
|
@ -173,6 +174,44 @@ count(1);
|
|||
ok ($res->[0] = 400);
|
||||
count(1);
|
||||
|
||||
# Play code on RP1
|
||||
$query="grant_type=authorization_code&code=$code&redirect_uri=http%3A%2F%2Frp2.com%2F";
|
||||
|
||||
ok(
|
||||
$res = $op->_post(
|
||||
"/oauth2/token",
|
||||
IO::String->new($query),
|
||||
accept => 'text/html',
|
||||
length => length($query),
|
||||
custom => {
|
||||
HTTP_AUTHORIZATION => "Basic ". encode_base64("rpid:rpsecret"),
|
||||
},
|
||||
),
|
||||
"Post token"
|
||||
);
|
||||
count(1);
|
||||
my $json = from_json($res->[2]->[0]);
|
||||
my $token = $json->{access_token};
|
||||
ok($token, 'Access token present');
|
||||
count(1);
|
||||
sleep(2);
|
||||
|
||||
ok(
|
||||
$res = $op->_post(
|
||||
"/oauth2/userinfo",
|
||||
IO::String->new(""),
|
||||
accept => 'text/html',
|
||||
length => 0,
|
||||
custom => {
|
||||
HTTP_AUTHORIZATION => "Bearer ". $token,
|
||||
},
|
||||
),
|
||||
"Post userinfo"
|
||||
);
|
||||
count(1);
|
||||
ok($res->[0] == 401, "Access denied with expired token");
|
||||
count(1);
|
||||
|
||||
clean_sessions();
|
||||
done_testing( count() );
|
||||
|
|
@ -3,7 +3,7 @@ use strict;
|
|||
use IO::String;
|
||||
|
||||
require 't/test-lib.pm';
|
||||
my $maintests = 19;
|
||||
my $maintests = 20;
|
||||
|
||||
SKIP: {
|
||||
eval { require Convert::Base32 };
|
||||
|
@ -24,7 +24,7 @@ SKIP: {
|
|||
loginHistoryEnabled => 0,
|
||||
authentication => 'Combination',
|
||||
userDB => 'Same',
|
||||
combination => '[Dm1] or [Dm2]',
|
||||
combination => '[ssl, Dm1] or [Dm2]',
|
||||
combModules => {
|
||||
Dm1 => {
|
||||
for => 0,
|
||||
|
@ -34,6 +34,10 @@ SKIP: {
|
|||
for => 0,
|
||||
type => 'Demo',
|
||||
},
|
||||
ssl => {
|
||||
for => 1,
|
||||
type => 'SSL',
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -161,10 +165,11 @@ SKIP: {
|
|||
),
|
||||
'Post code'
|
||||
);
|
||||
( $host, $url, $query ) =
|
||||
expectForm( $res, '#', undef, 'user', 'password', 'token' );
|
||||
ok( $res->[2]->[0] =~ /<span trmsg="82"><\/span>/, 'Token expired' )
|
||||
or print STDERR Dumper( $res->[2]->[0] );
|
||||
ok( $res = $client->_get( '/', accept => 'text/html' ), 'Get Menu', );
|
||||
my ( $host, $url, $query ) =
|
||||
expectForm( $res, '#', undef, 'user', 'password', 'token' );
|
||||
}
|
||||
count($maintests);
|
||||
|
||||
|
|
Loading…
Reference in New Issue