We now handle correctly the SOGo logout when using SAML (#2376 and #2379)

pull/67/head
Ludovic Marcotte 2014-11-27 11:37:08 -05:00
parent c3715c9485
commit 1b715e0812
11 changed files with 125 additions and 26 deletions

View File

@ -453,7 +453,9 @@ the setup of your identity provider. Make sure this file is readable by the SOGo
|S |SOGoSAML2LogoutEnabled
|Boolean value indicated whether the "Logout" link is enabled when using
SAML2 as authentication mechanism.
SAML2 as authentication mechanism. When using this feature, SOGo will invoke
the IdP to proceed with the logout procedure. When the user clicks on the logout
button, a redirection will be made to the IdP to trigger the logout.
|D |SOGoTimeZone
|Parameter used to set a default time zone for users. The default

1
NEWS
View File

@ -8,6 +8,7 @@ Bug fixes
- Now possible to specify the username attribute for SAML2 (SOGoSAML2LoginAttribute) (#2381)
- Added support for IdP-initiated SAML2 logout (#2377)
- We now generate SAML2 metadata on the fly (#2378)
- We now handle correctly the SOGo logout when using SAML (#2376 and #2379)
2.2.10 (2014-11-21)
-------------------

View File

@ -1,8 +1,6 @@
/* SOGoCASSession.h - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2010-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -1,8 +1,6 @@
/* SOGoCASSession.m - this file is part of SOGo
*
* Copyright (C) 2010 Inverse inc.
*
* Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
* Copyright (C) 2010-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -132,6 +132,7 @@
- (NSDictionary *) saml2LoginDumpsForIdentifier: (NSString *) identifier;
- (void) setSaml2LoginDumps: (NSDictionary *) dump
forIdentifier: (NSString *) identifier;
- (void) removeSAML2LoginDumpsForIdentifier: (NSString *) identifier;
//
// ACL caching support

View File

@ -673,11 +673,13 @@ static memcached_st *handle = NULL;
{
key = [NSString stringWithFormat: @"cas-ticket:%@", ticket];
[self removeValueForKey: key];
[self debugWithFormat: @"Removed session: %@", session];
[self debugWithFormat: @"Removed CAS session: %@", session];
}
}
//
// SAML2 support
//
- (NSDictionary *) saml2LoginDumpsForIdentifier: (NSString *) identifier
{
NSString *key, *jsonString;
@ -698,6 +700,16 @@ static memcached_st *handle = NULL;
[self setValue: [dump jsonRepresentation] forKey: key];
}
- (void) removeSAML2LoginDumpsForIdentifier: (NSString *) identifier
{
NSString *key;
key = [NSString stringWithFormat: @"saml2-login:%@", identifier];
[self removeValueForKey: key];
[self debugWithFormat: @"Removed SAML2 session for identifier: %@", identifier];
}
//
// ACL caching code
//

View File

@ -37,8 +37,12 @@
NSString *login;
NSString *identifier;
NSString *assertion;
NSString *identity;
NSString *session;
}
+ (LassoServer *) lassoServerInContext: (WOContext *) context;
+ (NSString *) metadataInContext: (WOContext *) context
certificate: (NSString *) certificate;
@ -54,6 +58,8 @@
- (NSString *) login;
- (NSString *) identifier;
- (NSString *) assertion;
- (NSString *) identity;
- (NSString *) session;
@end

View File

@ -105,8 +105,7 @@ static NSMapTable *serverTable = nil;
lasso_init ();
}
static LassoServer *
LassoServerInContext (WOContext *context)
+ (LassoServer *) lassoServerInContext: (WOContext *) context
{
NSString *urlString, *metadata, *filename, *keyContent, *certContent,
*idpKeyFilename, *idpCertFilename;
@ -170,7 +169,7 @@ LassoServerInContext (WOContext *context)
NSString *url;
GList *providers;
server = LassoServerInContext (context);
server = [SOGoSAML2Session lassoServerInContext: context];
tempLogin = lasso_login_new (server);
providers = g_hash_table_get_keys (server->providers);
@ -239,6 +238,8 @@ LassoServerInContext (WOContext *context)
login = nil;
identifier = nil;
assertion = nil;
identity = nil;
session = nil;
}
return self;
@ -350,7 +351,7 @@ LassoServerInContext (WOContext *context)
if ((self = [self init]))
{
server = LassoServerInContext (context);
server = [SOGoSAML2Session lassoServerInContext: context];
lassoLogin = lasso_login_new (server);
if (saml2Dump)
{
@ -358,12 +359,17 @@ LassoServerInContext (WOContext *context)
ASSIGN (login, [saml2Dump objectForKey: @"login"]);
ASSIGN (identifier, [saml2Dump objectForKey: @"identifier"]);
ASSIGN (assertion, [saml2Dump objectForKey: @"assertion"]);
dump = [[saml2Dump objectForKey: @"identity"] UTF8String];
ASSIGN(identity, [saml2Dump objectForKey: @"identity"]);
dump = [identity UTF8String];
if (dump)
lasso_profile_set_identity_from_dump (profile, dump);
dump = [[saml2Dump objectForKey: @"session"] UTF8String];
ASSIGN (session, [saml2Dump objectForKey: @"session"]);
dump = [session UTF8String];
if (dump)
lasso_profile_set_session_from_dump (profile, dump);
lasso_login_accept_sso (lassoLogin);
// if (rc)
// [NSException raiseSAML2Exception: rc];
@ -381,6 +387,9 @@ LassoServerInContext (WOContext *context)
[login release];
[identifier release];
[assertion release];
[identity release];
[session release];
[super dealloc];
}
@ -433,13 +442,23 @@ LassoServerInContext (WOContext *context)
return assertion;
}
- (NSString *) identity
{
return identity;
}
- (NSString *) session
{
return session;
}
- (void) processAuthnResponse: (NSString *) authnResponse
{
lasso_error_t rc;
gchar *responseData, *dump;
LassoProfile *profile;
LassoIdentity *identity;
LassoSession *session;
LassoIdentity *lasso_identity;
LassoSession *lasso_session;
NSString *nsDump;
NSMutableDictionary *saml2Dump;
@ -463,22 +482,22 @@ LassoServerInContext (WOContext *context)
profile = LASSO_PROFILE (lassoLogin);
session = lasso_profile_get_session (profile);
if (session)
lasso_session = lasso_profile_get_session (profile);
if (lasso_session)
{
dump = lasso_session_dump (session);
dump = lasso_session_dump (lasso_session);
nsDump = [NSString stringWithUTF8String: dump];
[saml2Dump setObject: nsDump forKey: @"session"];
lasso_session_destroy (session);
lasso_session_destroy (lasso_session);
}
identity = lasso_profile_get_identity (profile);
if (identity)
lasso_identity = lasso_profile_get_identity (profile);
if (lasso_identity)
{
dump = lasso_identity_dump (identity);
dump = lasso_identity_dump (lasso_identity);
nsDump = [NSString stringWithUTF8String: dump];
[saml2Dump setObject: nsDump forKey: @"identity"];
lasso_identity_destroy (identity);
lasso_identity_destroy (lasso_identity);
}
[[SOGoCache sharedCache] setSaml2LoginDumps: saml2Dump

View File

@ -1,6 +1,6 @@
/* SOGoWebAuthenticator.m - this file is part of SOGo
*
* Copyright (C) 2007-2013 Inverse inc.
* Copyright (C) 2007-2014 Inverse inc.
*
* This file is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

View File

@ -32,6 +32,7 @@
#import <NGExtensions/NSCalendarDate+misc.h>
#import <NGExtensions/NSString+misc.h>
#import <SOGo/SOGoCache.h>
#import <SOGo/SOGoSAML2Session.h>
#import <SOGo/SOGoSession.h>
#import <SOGo/SOGoSystemDefaults.h>
@ -65,9 +66,12 @@
return response;
}
//
//
//
- (WOResponse *) saml2SingleLogoutServiceAction
{
NSString *userName, *value, *cookieName;
NSString *userName, *value, *cookieName, *domain, *username, *password;
SOGoWebAuthenticator *auth;
WOResponse *response;
NSCalendarDate *date;
@ -96,6 +100,18 @@
cookieName = [auth cookieNameInContext: context];
value = [[context request] cookieValueForKey: cookieName];
creds = [auth parseCredentials: value];
// We first delete our memcached entry
value = [SOGoSession valueForSessionKey: [creds lastObject]];
domain = nil;
[SOGoSession decodeValue: value
usingKey: [creds objectAtIndex: 0]
login: &username
domain: &domain
password: &password];
[[SOGoCache sharedCache] removeSAML2LoginDumpsForIdentifier: password];
if ([creds count] > 1)
[SOGoSession deleteValueForSessionKey: [creds objectAtIndex: 1]];

View File

@ -33,7 +33,12 @@
#import <NGExtensions/NSObject+Logs.h>
#import <Appointments/SOGoFreeBusyObject.h>
#import <SOGo/SOGoCache.h>
#import <SOGo/SOGoCASSession.h>
#if defined(SAML2_CONFIG)
#import <SOGo/SOGoSAML2Session.h>
#endif
#import <SOGo/SOGoUserManager.h>
#import <SOGo/SOGoWebAuthenticator.h>
#import <SOGo/SOGoUser.h>
@ -304,6 +309,47 @@
redirectURL = [SOGoCASSession CASURLWithAction: @"logout"
andParameters: nil];
}
#if defined(SAML2_CONFIG)
else if ([[sd authenticationType] isEqualToString: @"saml2"])
{
NSString *username, *password, *domain, *value;
SOGoSAML2Session *saml2Session;
SOGoWebAuthenticator *auth;
LassoServer *server;
LassoLogout *logout;
NSArray *creds;
auth = [[self clientObject] authenticatorInContext: context];
value = [[context request] cookieValueForKey: [auth cookieNameInContext: context]];
creds = [auth parseCredentials: value];
value = [SOGoSession valueForSessionKey: [creds lastObject]];
domain = nil;
[SOGoSession decodeValue: value
usingKey: [creds objectAtIndex: 0]
login: &username
domain: &domain
password: &password];
saml2Session = [SOGoSAML2Session SAML2SessionWithIdentifier: password
inContext: context];
server = [SOGoSAML2Session lassoServerInContext: context];
logout = lasso_logout_new(server);
lasso_profile_set_session_from_dump(LASSO_PROFILE(logout), [[saml2Session session] UTF8String]);
lasso_profile_set_identity_from_dump(LASSO_PROFILE(logout), [[saml2Session session] UTF8String]);
lasso_logout_init_request(logout, NULL, LASSO_HTTP_METHOD_REDIRECT);
lasso_logout_build_request_msg(logout);
redirectURL = [NSString stringWithFormat: @"%s", LASSO_PROFILE(logout)->msg_url];
// We destroy our cache entry, the session will be taken care by the caller
[[SOGoCache sharedCache] removeSAML2LoginDumpsForIdentifier: password];
}
#endif
else
{
container = [[self clientObject] container];