Add support for CAS LogoutRequests
Fixes #2346 This changes the serviceURL sent by SOGo to the CAS server: /SOGo/so/ -> /SOGo/so/indexpull/12/head
parent
d28482557f
commit
41ed498d65
1
NEWS
1
NEWS
|
@ -20,6 +20,7 @@ Bug fixes
|
|||
- fixed public access when SOGoTrustProxyAuthentication is used (#2237)
|
||||
- fixed access right issues with import feature (#2294)
|
||||
- fixed IMAP ACL issue when SOGoForceExternalLoginWithEmail is used (#2313)
|
||||
- fixed handling of CAS logoutRequest (#2346)
|
||||
- OpenChange stability fixes
|
||||
|
||||
2.0.5a (2013-04-17)
|
||||
|
|
|
@ -140,7 +140,8 @@ SOGo_OBJC_FILES = \
|
|||
|
||||
SOGo_RESOURCE_FILES = \
|
||||
SOGoDefaults.plist \
|
||||
DAVReportMap.plist
|
||||
DAVReportMap.plist \
|
||||
CASLogoutRequestMap.plist
|
||||
|
||||
ifeq ($(saml2_config), yes)
|
||||
SOGo_HEADER_FILES += SOGoSAML2Session.h SOGoSAML2Exceptions.h
|
||||
|
|
|
@ -51,6 +51,8 @@
|
|||
+ (SOGoCASSession *) CASSessionWithIdentifier: (NSString *) newIdentifier
|
||||
fromProxy: (BOOL) fromProxy;
|
||||
|
||||
+ (void) handleLogoutRequest: (NSString *) logoutRequest;
|
||||
|
||||
- (NSString *) identifier;
|
||||
|
||||
- (NSString *) ticket;
|
||||
|
@ -65,4 +67,13 @@
|
|||
|
||||
@end
|
||||
|
||||
@interface CASLogoutRequest : NSObject
|
||||
{
|
||||
NSString *sessionIndex;
|
||||
}
|
||||
|
||||
- (NSString *) sessionIndex;
|
||||
|
||||
@end
|
||||
|
||||
#endif /* SOGOCASSESSION_H */
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#import <Foundation/NSBundle.h>
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSURL.h>
|
||||
|
||||
|
@ -35,6 +36,11 @@
|
|||
#import <NGObjWeb/WOResponse.h>
|
||||
#import <NGExtensions/NSObject+Logs.h>
|
||||
|
||||
#import <SaxObjC/SaxObjC.h>
|
||||
#import <SaxObjC/SaxMethodCallHandler.h>
|
||||
#import <SaxObjC/SaxObjectDecoder.h>
|
||||
#import <SaxObjC/SaxXMLReaderFactory.h>
|
||||
|
||||
#import "NSDictionary+Utilities.h"
|
||||
#import "NSString+Utilities.h"
|
||||
#import "SOGoCache.h"
|
||||
|
@ -106,6 +112,43 @@
|
|||
return session;
|
||||
}
|
||||
|
||||
+ (void) handleLogoutRequest: (NSString *) logoutRequest
|
||||
{
|
||||
CASLogoutRequest *rq;
|
||||
SOGoCache *cache;
|
||||
NSBundle *bundle;
|
||||
NSDictionary *root;
|
||||
NSString *mapFile, *sessionIndex;
|
||||
|
||||
bundle = [NSBundle bundleForClass: [self class]];
|
||||
mapFile = [bundle pathForResource: @"CASLogoutRequestMap" ofType: @"plist"];
|
||||
if (![mapFile length])
|
||||
{
|
||||
[self errorWithFormat: @"mapFile not found (CASLogoutRequest.plist)"];
|
||||
return;
|
||||
}
|
||||
|
||||
id<NSObject,SaxXMLReader> parser = nil;
|
||||
SaxObjectDecoder *sax = nil;
|
||||
parser = [[SaxXMLReaderFactory standardXMLReaderFactory]
|
||||
createXMLReaderForMimeType:@"text/xml"];
|
||||
|
||||
sax = [[SaxObjectDecoder alloc] initWithMappingAtPath: mapFile];
|
||||
[sax autorelease];
|
||||
[parser setContentHandler:sax];
|
||||
[parser setErrorHandler:sax];
|
||||
[parser parseFromSource: logoutRequest];
|
||||
|
||||
rq = [sax rootObject];
|
||||
sessionIndex = [rq sessionIndex];
|
||||
|
||||
if ([sessionIndex length])
|
||||
{
|
||||
cache = [SOGoCache sharedCache];
|
||||
[cache removeCASSessionWithTicket: sessionIndex];
|
||||
}
|
||||
}
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
|
@ -381,7 +424,12 @@
|
|||
NSString *serviceURL;
|
||||
|
||||
soURL = [[WOApplication application] soURL];
|
||||
serviceURL = [soURL absoluteString];
|
||||
|
||||
/* appending 'index' to /SOGo/so/ so that callbacks made by the CAS server
|
||||
* are not greeted with a 302 generated by sope. The CAS server doesn't
|
||||
* follow redirects, and we'd end up losing the LogoutRequests
|
||||
*/
|
||||
serviceURL = [NSString stringWithFormat: @"%@index", [soURL absoluteString]];
|
||||
|
||||
params = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||
ticket, @"ticket", serviceURL, @"service",
|
||||
|
@ -466,3 +514,28 @@
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation CASLogoutRequest
|
||||
|
||||
- (id) init
|
||||
{
|
||||
if ((self = [super init]))
|
||||
{
|
||||
sessionIndex = nil;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) dealloc
|
||||
{
|
||||
[sessionIndex release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (NSString *) sessionIndex
|
||||
{
|
||||
return sessionIndex;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -122,6 +122,8 @@
|
|||
- (void) setCASPGTId: (NSString *) pgtId
|
||||
forPGTIOU: (NSString *) pgtIou;
|
||||
|
||||
- (void) removeCASSessionWithTicket: (NSString *) ticket;
|
||||
|
||||
// SAML2 support
|
||||
- (NSDictionary *) saml2LoginDumpsForIdentifier: (NSString *) identifier;
|
||||
- (void) setSaml2LoginDumps: (NSDictionary *) dump
|
||||
|
|
|
@ -648,6 +648,17 @@ static memcached_st *handle = NULL;
|
|||
forKey: [NSString stringWithFormat: @"cas-pgtiou:%@", pgtIou]];
|
||||
}
|
||||
|
||||
- (void) removeCASSessionWithTicket: (NSString *) ticket
|
||||
{
|
||||
NSString *key, *session;
|
||||
if ((session = [self CASSessionWithTicket: ticket]))
|
||||
{
|
||||
key = [NSString stringWithFormat: @"cas-ticket:%@", ticket];
|
||||
[self removeValueForKey: key];
|
||||
[self debugWithFormat: @"Removed session: %@", session];
|
||||
}
|
||||
}
|
||||
|
||||
// SAML2 support
|
||||
- (NSDictionary *) saml2LoginDumpsForIdentifier: (NSString *) identifier
|
||||
{
|
||||
|
|
|
@ -272,10 +272,13 @@
|
|||
{
|
||||
NSDictionary *redirectKeys;
|
||||
NSURL *soURL;
|
||||
NSString *serviceURL;
|
||||
|
||||
soURL = [[WOApplication application] soURL];
|
||||
// appending 'index' to /SOGo/so/. Matches serviceURL sent by _pgtUrlFromURL
|
||||
serviceURL = [NSString stringWithFormat: @"%@index", [soURL absoluteString]];
|
||||
|
||||
redirectKeys = [NSDictionary dictionaryWithObject: [soURL absoluteString]
|
||||
redirectKeys = [NSDictionary dictionaryWithObject: serviceURL
|
||||
forKey: @"service"];
|
||||
|
||||
return redirectKeys;
|
||||
|
@ -302,7 +305,7 @@
|
|||
- (id <WOActionResults>) _casDefaultAction
|
||||
{
|
||||
WOResponse *response;
|
||||
NSString *login, *newLocation, *oldLocation, *ticket;
|
||||
NSString *login, *logoutRequest, *newLocation, *oldLocation, *ticket;
|
||||
SOGoCASSession *casSession;
|
||||
SOGoWebAuthenticator *auth;
|
||||
WOCookie *casCookie, *casLocationCookie;
|
||||
|
@ -340,6 +343,18 @@
|
|||
withName: @"cas-location"];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* anonymous and no ticket, possibly a logout request from CAS
|
||||
* See: https://wiki.jasig.org/display/CASUM/Single+Sign+Out
|
||||
*/
|
||||
logoutRequest = [rq formValueForKey: @"logoutRequest"];
|
||||
if ([logoutRequest length])
|
||||
{
|
||||
[SOGoCASSession handleLogoutRequest: logoutRequest];
|
||||
return [self responseWithStatus: 200];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
ticket = nil;
|
||||
|
|
Loading…
Reference in New Issue