CHeck session iframe with CORS for session management (#184)

environments/ppa-mbqj77/deployments/1
Clément Oudot 11 years ago
parent dc63f83128
commit fe77ab4dbb
  1. 5
      lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Attributes.pm
  2. 1
      lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Tree.pm
  3. 3
      lemonldap-ng-portal/example/openid-configuration.pl
  4. 64
      lemonldap-ng-portal/lib/Lemonldap/NG/Portal/IssuerDBOpenIDConnect.pm
  5. 38
      lemonldap-ng-portal/lib/Lemonldap/NG/Portal/_OpenIDConnect.pm

@ -1956,6 +1956,11 @@ m{^(?:ldapi://[^/]*/?|\w[\w\-\.]*(?::\d{1,5})?|ldap(?:s|\+tls)?://\w[\w\-\.]*(?:
default => 'logout',
documentation => 'OpenID Connect end session endpoint',
},
oidcServiceMetaDataCheckSessionURI => {
type => 'text',
default => 'checksession',
documentation => 'OpenID Connect check session iframe',
},
oidcServiceMetaDataAuthnContext => {
type => 'keyTextContainer',
default => {

@ -817,6 +817,7 @@ sub tree {
'oidcServiceMetaDataJWKSURI',
'oidcServiceMetaDataRegistrationURI',
'oidcServiceMetaDataEndSessionURI',
'oidcServiceMetaDataCheckSessionURI',
]
},
'oidcServiceMetaDataAuthnContext',

@ -13,6 +13,7 @@ my $userinfo_uri = $portal->{oidcServiceMetaDataUserInfoURI};
my $jwks_uri = $portal->{oidcServiceMetaDataJWKSURI};
my $registration_uri = $portal->{oidcServiceMetaDataRegistrationURI};
my $endsession_uri = $portal->{oidcServiceMetaDataEndSessionURI};
my $checksession_uri = $portal->{oidcServiceMetaDataCheckSessionURI};
my ($path) = ( $issuerDBOpenIDConnectPath =~ /(\w+)/ );
my $issuer = $portal->{oidcServiceMetaDataIssuer};
@ -31,6 +32,8 @@ $configuration->{registration_endpoint} =
if ( $portal->{oidcServiceAllowDynamicRegistration} );
$configuration->{end_session_endpoint} =
$issuer . $path . "/" . $endsession_uri;
$configuration->{check_session_iframe} =
$issuer . $path . "/" . $checksession_uri;
$configuration->{scopes_supported} = [qw/openid profile email address phone/];
$configuration->{response_types_supported} = [
"code",

@ -37,6 +37,7 @@ sub issuerForUnAuthUser {
my $jwks_uri = $self->{oidcServiceMetaDataJWKSURI};
my $registration_uri = $self->{oidcServiceMetaDataRegistrationURI};
my $endsession_uri = $self->{oidcServiceMetaDataEndSessionURI};
my $checksession_uri = $self->{oidcServiceMetaDataCheckSessionURI};
my $issuer = $self->{oidcServiceMetaDataIssuer};
# Called URL
@ -543,6 +544,37 @@ sub issuerForUnAuthUser {
return PE_LOGOUT_OK;
}
# CHECK SESSION
if ( $url_path =~ m#${issuerDBOpenIDConnectPath}${checksession_uri}# ) {
$self->lmLog(
"URL $url detected as an OpenID Connect CHECK SESSION URL",
'debug' );
print $self->header(
-type => 'text/html',
-access_control_allow_origin => '*'
);
print $self->start_html(
-title => 'Check Session',
-script => [
{
-type => 'text/javascript',
-src =>
'http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha256.js'
},
{
-type => 'text/javascript',
-src =>
'http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/enc-base64-min.js'
},
{ -code => $self->getSessionManagementOPIFrameJS }
]
);
print $self->end_html();
$self->quit();
}
PE_OK;
}
@ -560,6 +592,7 @@ sub issuerForAuthUser {
my $jwks_uri = $self->{oidcServiceMetaDataJWKSURI};
my $registration_uri = $self->{oidcServiceMetaDataRegistrationURI};
my $endsession_uri = $self->{oidcServiceMetaDataEndSessionURI};
my $checksession_uri = $self->{oidcServiceMetaDataCheckSessionURI};
my $issuer = $self->{oidcServiceMetaDataIssuer};
# Session ID
@ -1343,6 +1376,37 @@ sub issuerForAuthUser {
return PE_CONFIRM;
}
# CHECK SESSION
if ( $url_path =~ m#${issuerDBOpenIDConnectPath}${checksession_uri}# ) {
$self->lmLog(
"URL $url detected as an OpenID Connect CHECK SESSION URL",
'debug' );
print $self->header(
-type => 'text/html',
-access_control_allow_origin => '*'
);
print $self->start_html(
-title => 'Check Session',
-script => [
{
-type => 'text/javascript',
-src =>
'http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/sha256.js'
},
{
-type => 'text/javascript',
-src =>
'http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/enc-base64-min.js'
},
{ -code => $self->getSessionManagementOPIFrameJS }
]
);
print $self->end_html();
$self->quit();
}
PE_OK;
}

@ -1423,7 +1423,12 @@ sub createSessionState {
my $salt = encode_base64url( $self->{cipher}->encrypt($client_id) );
my $data = $client_id . " " . $session_id . " " . $salt;
my $session_state = sha256_base64($data) . "." . $salt;
my $hash = sha256_base64($data);
while ( length($hash) % 4 ) {
$hash .= '=';
}
my $session_state = $hash . "." . $salt;
return $session_state;
}
@ -1445,6 +1450,37 @@ sub getRequestJWT {
return $response->decoded_content;
}
## @method String getSessionManagementOPIFrameJS
# Create JS code needed on OP side to manage session
# return String JS code
sub getSessionManagementOPIFrameJS {
my ($self) = splice @_;
my $js;
$js .= "window.addEventListener(\"message\", receiveMessage, false);\n";
$js .= "function receiveMessage(e){ \n";
$js .= "var message = e.data; \n";
$js .= "client_id = decodeURIComponent(message.split(' ')[0]);\n";
$js .= "session_state = decodeURIComponent(message.split(' ')[1]);\n";
$js .= "var salt = decodeURIComponent(session_state.split('.')[1]);\n";
$js .=
'var opbs = document.cookie.replace(/(?:(?:^|.*;\s*)'
. $self->{cookieName}
. '\s*\=\s*([^;]*).*$)|^.*$/, "$1");' . "\n";
$js .= "var hash = CryptoJS.SHA256(client_id + ' ' + opbs + ' ' + salt);\n";
$js .= "var ss = hash.toString(CryptoJS.enc.Base64) + '.' + salt;\n";
$js .= "if (session_state == ss) {\n";
$js .= "stat = 'unchanged';\n";
$js .= "} else {\n";
$js .= "stat = 'changed';\n";
$js .= "}\n";
$js .= "e.source.postMessage(stat,e.origin);\n";
$js .= "};\n";
return $js;
}
1;
__END__

Loading…
Cancel
Save