Commit b94a337a authored by Xavier Guimard's avatar Xavier Guimard

Optimize checksession endpoint (#595)

parent 83c3b503
#========================================================================
# Apache configuration for LemonLDAP::NG Handler
#========================================================================
# This file implements the reload virtualhost that permits to reload
# configuration without restarting server, and some common instructions.
# You need then to declare this vhost in reloadUrls (in the manager
# interface if this server doesn't host the manager itself):
#
# KEY : VALUE
# host-or-IP:port : http://reload.example.com/reload
#
# IMPORTANT:
# To protect applications, see test-apache.conf template in example files
# Uncomment this if no previous NameVirtualHost declaration
#NameVirtualHost __VHOSTLISTEN__
# Load LemonLDAP::NG Handler
PerlRequire Lemonldap/NG/Handler.pm
# Common error page and security parameters
ErrorDocument 403 http://auth.__DNSDOMAIN__/?lmError=403
ErrorDocument 500 http://auth.__DNSDOMAIN__/?lmError=500
ErrorDocument 503 http://auth.__DNSDOMAIN__/?lmError=503
<VirtualHost __VHOSTLISTEN__>
ServerName reload.__DNSDOMAIN__
# Configuration reload mechanism (only 1 per physical server is
# needed): choose your URL to avoid restarting Apache when
# configuration change
<Location /reload>
Order deny,allow
Deny from all
Allow from 127.0.0.0/8 ::1
PerlHeaderParserHandler Lemonldap::NG::Handler->reload
</Location>
# Uncomment this to activate status module
#<Location /status>
# Order deny,allow
# Deny from all
# Allow from 127.0.0.0/8 ::1
# SetHandler perl-script
# PerlHandler Lemonldap::NG::Handler->status
# # You may have to uncomment the next directive to skip
# # an upper PerlHeaderParserHandler directive
# #PerlHeaderParserHandler Apache::Constants::DECLINED
#</Location>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000
</VirtualHost>
#====================================================================
# Apache configuration for LemonLDAP::NG Portal
#====================================================================
# Uncomment this if no previous NameVirtualHost declaration
#NameVirtualHost __VHOSTLISTEN__
# Portal Virtual Host (auth.__DNSDOMAIN__)
<VirtualHost __VHOSTLISTEN__>
ServerName auth.__DNSDOMAIN__
# DocumentRoot (FCGI scripts)
DocumentRoot __PORTALDIR__
<Directory __PORTALDIR__>
Order allow,deny
Allow from all
Options +ExecCGI +FollowSymLinks
</Directory>
RewriteEngine On
RewriteCond "%{REQUEST_FILENAME}" "!^/(?:(?:static|javascript|favicon).*|.*\.fcgi)$"
RewriteRule "^/(.+)$" "/index.fcgi/$1" [PT]
<Files *.fcgi>
SetHandler fcgid-script
Options +ExecCGI
</Files>
# Static files
Alias /static/ __PORTALSTATICDIR__/
<Directory __PORTALSTATICDIR__>
Order allow,deny
Allow from all
Options +FollowSymLinks
</Directory>
<Location /static/>
<IfModule mod_expires.c>
ExpiresActive On
ExpiresDefault "access plus 1 month"
</IfModule>
</Location>
<IfModule mod_dir.c>
DirectoryIndex index.fcgi index.html
</IfModule>
# SOAP functions for sessions management (disabled by default)
<Location /index.fcgi/adminSessions>
Order deny,allow
Deny from all
</Location>
# SOAP functions for sessions access (disabled by default)
<Location /index.fcgi/sessions>
Order deny,allow
Deny from all
</Location>
# SOAP functions for configuration access (disabled by default)
<Location /index.fcgi/config>
Order deny,allow
Deny from all
</Location>
# SOAP functions for notification insertion (disabled by default)
<Location /index.fcgi/notification>
Order deny,allow
Deny from all
</Location>
# Enabe compression
<Location />
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/javascript text/css
SetOutputFilter DEFLATE
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary
</IfModule>
<IfModule mod_headers.c>
Header append Vary User-Agent env=!dont-vary
</IfModule>
</Location>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000
</VirtualHost>
......@@ -16,6 +16,10 @@
Options +ExecCGI +FollowSymLinks
</Directory>
RewriteEngine On
# For performances, you can put static html files: simply put the HTML
# result (example: /oauth2/checksession.html) as static file. Then
# uncomment the following line.
# RewriteCond "%{REQUEST_FILENAME}" "!\.html$"
RewriteCond "%{REQUEST_FILENAME}" "!^/(?:(?:static|javascript|favicon).*|.*\.fcgi)$"
RewriteRule "^/(.+)$" "/index.fcgi/$1" [PT]
......
......@@ -22,6 +22,10 @@
Options +ExecCGI +FollowSymLinks
</Directory>
RewriteEngine On
# For performances, you can put static html files: simply put the HTML
# result (example: /oauth2/checksession.html) as static file. Then
# uncomment the following line.
# RewriteCond "%{REQUEST_FILENAME}" "!\.html$"
RewriteCond "%{REQUEST_FILENAME}" "!^/(?:(?:static|javascript|favicon).*|.*\.fcgi)$"
RewriteRule "^/(.+)$" "/index.fcgi/$1" [PT]
......
......@@ -17,6 +17,10 @@
Options +ExecCGI +FollowSymLinks
</Directory>
RewriteEngine On
# For performances, you can put static html files: simply put the HTML
# result (example: /oauth2/checksession.html) as static file. Then
# uncomment the following line.
# RewriteCond "%{REQUEST_FILENAME}" "!\.html$"
RewriteCond "%{REQUEST_FILENAME}" "!^/(?:(?:static|javascript|favicon).*|.*\.fcgi)$"
RewriteRule "^/(.+)$" "/index.fcgi/$1" [PT]
......
#====================================================================
# Apache configuration for LemonLDAP::NG sample applications
#====================================================================
# Uncomment this if no previous NameVirtualHost declaration
#NameVirtualHost __VHOSTLISTEN__
# Sample application
<VirtualHost __VHOSTLISTEN__>
ServerName test1.__DNSDOMAIN__
ServerAlias test2.__DNSDOMAIN__
# SSO protection
PerlHeaderParserHandler Lemonldap::NG::Handler
# DocumentRoot
DocumentRoot __TESTDIR__
<Directory __TESTDIR__>
Order allow,deny
Allow from all
Options +ExecCGI
</Directory>
# Perl script (application test is written in Perl)
<Files *.pl>
SetHandler perl-script
PerlHandler Apache::Registry
</Files>
# Directory index
<IfModule mod_dir.c>
DirectoryIndex index.pl index.html
</IfModule>
# Uncomment this if site if you use SSL only
#Header set Strict-Transport-Security 15768000
</VirtualHost>
......@@ -154,7 +154,7 @@ sub defaultValues {
'loa-5' => 5
},
'oidcServiceMetaDataAuthorizeURI' => 'authorize',
'oidcServiceMetaDataCheckSessionURI' => 'checksession',
'oidcServiceMetaDataCheckSessionURI' => 'checksession.html',
'oidcServiceMetaDataEndSessionURI' => 'logout',
'oidcServiceMetaDataIssuer' => 'http://auth.example.com',
'oidcServiceMetaDataJWKSURI' => 'jwks',
......
......@@ -1633,7 +1633,7 @@ qr/^(?:(?:(?:(?:[a-zA-Z0-9][-a-zA-Z0-9]*)?[a-zA-Z0-9])[.])*(?:[a-zA-Z][-a-zA-Z0-
'type' => 'text'
},
'oidcServiceMetaDataCheckSessionURI' => {
'default' => 'checksession',
'default' => 'checksession.html',
'type' => 'text'
},
'oidcServiceMetaDataEndSessionURI' => {
......
......@@ -2273,7 +2273,7 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
},
oidcServiceMetaDataCheckSessionURI => {
type => 'text',
default => 'checksession',
default => 'checksession.html',
documentation => 'OpenID Connect check session iframe',
},
oidcServiceMetaDataAuthnContext => {
......
......@@ -1243,17 +1243,12 @@ sub checkSession {
$self->lmLog( "URL detected as an OpenID Connect CHECK SESSION URL",
'debug' );
my $portalPath = $self->conf->{portal};
$portalPath =~ s#^https?://[^/]+/?#/#;
$portalPath =~ s#[^/]+\.pl$##;
# TODO: access_control_allow_origin => '*'
return $self->p->sendHtml(
$req,
'../common/oidc_checksession',
params => {
JS_CODE => $self->getSessionManagementOPIFrameJS,
SKIN_PATH => $portalPath . 'skins',
COOKIENAME => $self->conf->{cookieName},
}
);
}
......
......@@ -1373,30 +1373,6 @@ sub getRequestJWT {
return $response->decoded_content;
}
# Create JS code needed on OP side to manage session
# return String JS code
sub getSessionManagementOPIFrameJS {
my ($self) = @_;
return q@window.addEventListener("message", receiveMessage, false);
function receiveMessage(e){
var message = e.data;
client_id = decodeURIComponent(message.split(' ')[0]);
session_state = decodeURIComponent(message.split(' ')[1]);
var salt = decodeURIComponent(session_state.split('.')[1]);
var opbs = document.cookie.replace(/(?:(?:^|.*;\s*)@
. $self->conf->{cookieName} . q@\s*\=\s*([^;]*).*$)|^.*$/, "$1");
var hash = CryptoJS.SHA256(client_id + ' ' + opbs + ' ' + salt);
var ss = hash.toString(CryptoJS.enc.Base64) + '.' + salt;
if (session_state == ss) {
stat = 'unchanged';
} else {
stat = 'changed';
}
e.source.postMessage(stat,e.origin);
}@;
}
### Import encode_base64url and decode_base64url from recent MIME::Base64 module:
sub encode_base64url {
my $e = encode_base64( shift, '' );
......
......@@ -41,7 +41,7 @@ sub handler {
# -----------------
#
# Entry points:
# - "/test": - authenticated() for already authenticated users
# - "/ping": - authenticated() for already authenticated users
# - pleaseAuth() for others
# - "/": - login() ~first access
# - postLogin(), same for POST requests
......
......@@ -12,7 +12,22 @@
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">bwr/crypto-js/enc-base64.js"></script>
<!-- //endif -->
<script type="text/javascript">//<![CDATA[
<TMPL_VAR NAME="JS_CODE">
function receiveMessage(e){
var message = e.data;
client_id = decodeURIComponent(message.split(' ')[0]);
session_state = decodeURIComponent(message.split(' ')[1]);
var salt = decodeURIComponent(session_state.split('.')[1]);
var opbs = document.cookie.replace(/(?:(?:^|.*;\s*)<TMPL_VAR NAME="COOKIENAME">\s*\=\s*([^;]*).*$)|^.*$/, "$1");
var hash = CryptoJS.SHA256(client_id + ' ' + opbs + ' ' + salt);
var ss = hash.toString(CryptoJS.enc.Base64) + '.' + salt;
if (session_state == ss) {
stat = 'unchanged';
} else {
stat = 'changed';
}
e.source.postMessage(stat,e.origin);
}@;
window.addEventListener("message", receiveMessage, false);
//]]></script>
</head>
<body>
......
......@@ -81,11 +81,13 @@ my $spId = expectCookie($res);
switch ('op');
ok(
$res = $op->_get( '/oauth2/checksession', accept => 'text.html' ),
'Check session, endpoint /oauth2/checksession'
$res = $op->_get( '/oauth2/checksession.html', accept => 'text.html' ),
'Check session, endpoint /oauth2/checksession.html'
);
count(1);
expectOK($res);
ok($res->[2]->[0]=~ /e\.source\.postMessage/, 'Found javascript');
count(1);
# Logout initiated by RP
switch ('rp');
......@@ -258,7 +260,7 @@ sub op {
},
oidcServiceMetaDataIssuer => "http://auth.op.com",
oidcServiceMetaDataAuthorizeURI => "authorize",
oidcServiceMetaDataCheckSessionURI => "checksession",
oidcServiceMetaDataCheckSessionURI => "checksession.html",
oidcServiceMetaDataJWKSURI => "jwks",
oidcServiceMetaDataEndSessionURI => "logout",
oidcServiceMetaDataRegistrationURI => "register",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment