Finalized support for SAML2 logon

pull/7/head
Wolfgang Sourdeau 2012-11-02 15:31:49 -04:00
parent 695fc5fff9
commit aeabd85c90
11 changed files with 616 additions and 83 deletions

View File

@ -28,13 +28,30 @@
#import <Foundation/NSObject.h>
#include <lasso/lasso.h>
@class NSString;
@interface SOGoSAML2Session : NSObject
{
LassoLogin *lassoLogin;
NSString *login;
NSString *identifier;
}
+ (NSString *) metadataInContext: (WOContext *) context;
+ (NSString *) authenticationURLInContext: (WOContext *) context;
+ (SOGoSAML2Session *) SAML2SessionInContext: (WOContext *) context;
+ (SOGoSAML2Session *) SAML2SessionWithIdentifier: (NSString *) newIdentifier
inContext: (WOContext *) context;
- (void) processAuthnResponse: (NSString *) authnResponse;
- (NSString *) login;
- (NSString *) identifier;
@end

View File

@ -20,7 +20,18 @@
* Boston, MA 02111-1307, USA.
*/
#include <lasso/lasso.h>
#include <lasso/xml/misc_text_node.h>
#include <lasso/xml/saml-2.0/saml2_attribute.h>
#include <lasso/xml/saml-2.0/saml2_attribute_statement.h>
#include <lasso/xml/saml-2.0/saml2_attribute_value.h>
#include <lasso/xml/saml-2.0/samlp2_authn_request.h>
#include <lasso/xml/saml-2.0/samlp2_response.h>
#import <Foundation/NSBundle.h>
#import <Foundation/NSDictionary.h>
#import <Foundation/NSException.h>
#import <Foundation/NSMapTable.h>
#import <Foundation/NSString.h>
#import <Foundation/NSURL.h>
@ -29,25 +40,154 @@
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOResponse.h>
#import "SOGoCache.h"
#import "SOGoSAML2Exceptions.h"
#import "SOGoSystemDefaults.h"
#import "SOGoSAML2Session.h"
@interface WOContext (SOGoSAML2Extension)
- (NSString *) SAML2ServerURLString;
@end
@implementation WOContext (SOGoSAML2Extension)
- (NSString *) SAML2ServerURLString
{
NSString *appName;
NSURL *serverURL;
appName = [[WOApplication application] name];
serverURL = [NSURL URLWithString: [NSString stringWithFormat: @"/%@",
appName]
relativeToURL: [self serverURL]];
return [serverURL absoluteString];
}
@end
@implementation SOGoSAML2Session
static NSMapTable *serverTable = nil;
+ (void) initialize
{
if (!serverTable)
{
serverTable = [NSMapTable mapTableWithStrongToWeakObjects];
[serverTable retain];
}
lasso_init ();
}
static LassoServer *
LassoServerInContext (WOContext *context)
{
NSString *urlString, *metadata, *filename, *keyContent, *certContent,
*idpKeyFilename, *idpCertFilename;
LassoServer *server;
SOGoSystemDefaults *sd;
urlString = [context SAML2ServerURLString];
server = NSMapGet (serverTable, urlString);
if (!server)
{
sd = [SOGoSystemDefaults sharedSystemDefaults];
filename = [sd SAML2PrivateKeyLocation];
if (!filename)
[NSException raise: NSInvalidArgumentException
format: @"'SAML2PrivateKeyLocation' not set"];
keyContent = [NSString stringWithContentsOfFile: filename];
if (!keyContent)
[NSException raise: NSGenericException
format: @"private key file '%@' could not be read",
filename];
filename = [sd SAML2CertificateLocation];
if (!filename)
[NSException raise: NSInvalidArgumentException
format: @"'SAML2CertificateLocation' not set"];
certContent = [NSString stringWithContentsOfFile: filename];
if (!certContent)
[NSException raise: NSGenericException
format: @"certificate file '%@' could not be read",
filename];
metadata = [SOGoSAML2Session metadataInContext: context];
/* FIXME: enable key password in config ? */
server = lasso_server_new_from_buffers ([metadata UTF8String],
[keyContent UTF8String],
NULL,
[certContent UTF8String]);
filename = [sd SAML2IdpMetadataLocation];
idpKeyFilename = [sd SAML2IdpPublicKeyLocation];
idpCertFilename = [sd SAML2IdpCertificateLocation];
lasso_server_add_provider (server, LASSO_PROVIDER_ROLE_IDP,
[filename UTF8String],
[idpKeyFilename UTF8String],
[idpCertFilename UTF8String]);
NSMapInsert (serverTable, urlString, server);
}
return server;
}
+ (NSString *) authenticationURLInContext: (WOContext *) context
{
lasso_error_t rc;
LassoServer *server;
LassoLogin *tempLogin;
LassoSamlp2AuthnRequest *request;
NSString *url;
GList *providers;
server = LassoServerInContext (context);
tempLogin = lasso_login_new (server);
providers = g_hash_table_get_keys (server->providers);
rc = lasso_login_init_authn_request (tempLogin, providers->data, LASSO_HTTP_METHOD_REDIRECT);
if (rc)
[NSException raiseSAML2Exception: rc];
request = LASSO_SAMLP2_AUTHN_REQUEST (LASSO_PROFILE (tempLogin)->request);
if (request->NameIDPolicy->Format) {
g_free (request->NameIDPolicy->Format);
}
request->NameIDPolicy->Format = g_strdup(LASSO_SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT);
request->NameIDPolicy->AllowCreate = 1;
request->ForceAuthn = TRUE;
request->IsPassive = FALSE;
if (request->ProtocolBinding) {
g_free (request->ProtocolBinding);
}
// request->NameIDPolicy = strdup (LASSO_LIB_NAMEID_POLICY_TYPE_FEDERATED);
// request->consent = strdup (LASSO_LIB_CONSENT_OBTAINED);
rc = lasso_login_build_authn_request_msg (tempLogin);
if (rc)
[NSException raiseSAML2Exception: rc];
url = [NSString stringWithUTF8String: LASSO_PROFILE (tempLogin)->msg_url];
g_object_unref (tempLogin);
return url;
}
+ (NSString *) metadataInContext: (WOContext *) context
{
NSString *metadata, *serverURLString, *filename, *appName;
NSString *metadata, *serverURLString, *filename;
NSBundle *bundle;
NSURL *serverURL;
bundle = [NSBundle bundleForClass: self];
filename = [bundle pathForResource: @"SOGoSAML2Metadata" ofType: @"xml"];
if (filename)
{
appName = [[WOApplication application] name];
serverURL = [NSURL URLWithString: [NSString stringWithFormat: @"/%@/so",
appName]
relativeToURL: [context serverURL]];
serverURLString = [serverURL absoluteString];
serverURLString = [context SAML2ServerURLString];
metadata = [[NSString stringWithContentsOfFile: filename]
stringByReplacingString: @"%{base_url}"
withString: serverURLString];
@ -58,4 +198,204 @@
return metadata;
}
- (id) init
{
if ((self = [super init]))
{
lassoLogin = NULL;
}
return self;
}
- (void) _updateDataFromLogin
{
// LassoSamlp2Response *response;
LassoSaml2Assertion *assertion;
GList *statementList, *attributeList;
LassoSaml2AttributeStatement *statement;
LassoSaml2Attribute *attribute;
LassoSaml2AttributeValue *value;
LassoMiscTextNode *textNode;
LassoSaml2NameID *nameIdentifier;
NSLog (@"lassoLogin: class = %s", g_type_name_from_instance (lassoLogin));
assertion = LASSO_SAML2_ASSERTION (lasso_login_get_assertion (lassoLogin));
if (assertion)
{
/* deduce user login */
[login release];
login = nil;
statementList = assertion->AttributeStatement;
while (!login && statementList)
{
statement = LASSO_SAML2_ATTRIBUTE_STATEMENT (statementList->data);
attributeList = statement->Attribute;
while (!login && attributeList)
{
attribute = LASSO_SAML2_ATTRIBUTE (attributeList->data);
if (strcmp (attribute->Name, "uid") == 0)
{
value = LASSO_SAML2_ATTRIBUTE_VALUE (attribute->AttributeValue->data);
textNode = value->any->data;
login = [NSString stringWithUTF8String: textNode->content];
[login retain];
}
else
attributeList = attributeList->next;
}
statementList = statementList->next;
}
}
nameIdentifier
= LASSO_SAML2_NAME_ID (LASSO_PROFILE (lassoLogin)->nameIdentifier);
if (nameIdentifier)
{
/* deduce session id */
[identifier release];
identifier = [NSString stringWithUTF8String: nameIdentifier->content];
[identifier retain];
}
}
- (id) _initWithDump: (NSDictionary *) saml2Dump
inContext: (WOContext *) context
{
// lasso_error_t rc;
LassoServer *server;
LassoProfile *profile;
const gchar *dump;
if ((self = [self init]))
{
server = LassoServerInContext (context);
lassoLogin = lasso_login_new (server);
if (saml2Dump)
{
profile = LASSO_PROFILE (lassoLogin);
ASSIGN (login, [saml2Dump objectForKey: @"login"]);
ASSIGN (identifier, [saml2Dump objectForKey: @"identifier"]);
dump = [[saml2Dump objectForKey: @"identity"] UTF8String];
if (dump)
lasso_profile_set_identity_from_dump (profile, dump);
dump = [[saml2Dump objectForKey: @"session"] UTF8String];
if (dump)
lasso_profile_set_session_from_dump (profile, dump);
lasso_login_accept_sso (lassoLogin);
// if (rc)
// [NSException raiseSAML2Exception: rc];
[self _updateDataFromLogin];
}
}
return self;
}
- (void) dealloc
{
if (lassoLogin)
g_object_unref (lassoLogin);
[login release];
[identifier release];
[super dealloc];
}
+ (SOGoSAML2Session *) _SAML2SessionWithDump: (NSDictionary *) saml2Dump
inContext: (WOContext *) context
{
SOGoSAML2Session *newSession;
newSession = [[self alloc] _initWithDump: saml2Dump inContext: context];
[newSession autorelease];
return newSession;
}
+ (SOGoSAML2Session *) SAML2SessionInContext: (WOContext *) context
{
return [self _SAML2SessionWithDump: nil inContext: context];
}
+ (SOGoSAML2Session *) SAML2SessionWithIdentifier: (NSString *) identifier
inContext: (WOContext *) context
{
SOGoSAML2Session *session = nil;
NSDictionary *saml2Dump;
if (identifier)
{
saml2Dump = [[SOGoCache sharedCache]
saml2LoginDumpsForIdentifier: identifier];
if (saml2Dump)
session = [self _SAML2SessionWithDump: saml2Dump
inContext: context];
}
return session;
}
- (NSString *) login
{
return login;
}
- (NSString *) identifier
{
return identifier;
}
- (void) processAuthnResponse: (NSString *) authnResponse
{
lasso_error_t rc;
gchar *responseData, *dump;
LassoProfile *profile;
LassoIdentity *identity;
LassoSession *session;
NSString *nsDump;
NSMutableDictionary *saml2Dump;
responseData = strdup ([authnResponse UTF8String]);
rc = lasso_login_process_authn_response_msg (lassoLogin, responseData);
if (rc)
[NSException raiseSAML2Exception: rc];
rc = lasso_login_accept_sso (lassoLogin);
if (rc)
[NSException raiseSAML2Exception: rc];
[self _updateDataFromLogin];
saml2Dump = [NSMutableDictionary dictionary];
[saml2Dump setObject: login forKey: @"login"];
[saml2Dump setObject: identifier forKey: @"identifier"];
profile = LASSO_PROFILE (lassoLogin);
session = lasso_profile_get_session (profile);
if (session)
{
dump = lasso_session_dump (session);
nsDump = [NSString stringWithUTF8String: dump];
[saml2Dump setObject: nsDump forKey: @"session"];
lasso_session_destroy (session);
}
identity = lasso_profile_get_identity (profile);
if (identity)
{
dump = lasso_identity_dump (identity);
nsDump = [NSString stringWithUTF8String: dump];
[saml2Dump setObject: nsDump forKey: @"identity"];
lasso_identity_destroy (identity);
}
[[SOGoCache sharedCache] setSaml2LoginDumps: saml2Dump
forIdentifier: identifier];
free (responseData);
}
@end

View File

@ -43,6 +43,7 @@
login: (NSString **) theLogin
domain: (NSString **) theDomain
password: (NSString **) thePassword;
@end
#endif

View File

@ -26,6 +26,8 @@
#include "SOGoCache.h"
#import <NGObjWeb/WOCookie.h>
#import <Foundation/NSArray.h>
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSData.h>

View File

@ -32,6 +32,9 @@
@class NSString;
@class WOContext;
@class WOCookie;
@class SOGoUser;
@interface SOGoWebAuthenticator : SoCookieAuthenticator <SOGoAuthenticator>
@ -45,6 +48,10 @@
expire: (int *) _expire
grace: (int *) _grace;
- (WOCookie *) cookieWithUsername: (NSString *) username
andPassword: (NSString *) password
inContext: (WOContext *) context;
@end
#endif /* _SOGOWEBAUTHENTICATOR_H_ */

View File

@ -32,6 +32,7 @@
#import <NGObjWeb/WOCookie.h>
#import <NGObjWeb/WORequest.h>
#import <NGObjWeb/WOResponse.h>
#import <NGExtensions/NGBase64Coding.h>
#import <NGExtensions/NSCalendarDate+misc.h>
#import <NGExtensions/NSObject+Logs.h>
#import <NGExtensions/NSNull+misc.h>
@ -47,7 +48,9 @@
#import "SOGoSystemDefaults.h"
#import "SOGoUser.h"
#import "SOGoUserManager.h"
#if defined(SAML2_CONFIG)
#import "SOGoSAML2Session.h"
#endif
#import "SOGoWebAuthenticator.h"
@implementation SOGoWebAuthenticator
@ -107,11 +110,13 @@
{
SOGoCASSession *session;
SOGoSystemDefaults *sd;
NSString *authenticationType;
BOOL rc;
sd = [SOGoSystemDefaults sharedSystemDefaults];
if ([[sd authenticationType] isEqualToString: @"cas"])
authenticationType = [sd authenticationType];
if ([authenticationType isEqualToString: @"cas"])
{
session = [SOGoCASSession CASSessionWithIdentifier: _pwd fromProxy: NO];
if (session)
@ -119,6 +124,18 @@
else
rc = NO;
}
#if defined(SAML2_CONFIG)
else if ([authenticationType isEqualToString: @"saml2"])
{
SOGoSAML2Session *saml2Session;
WOContext *context;
context = [[WOApplication application] context];
saml2Session = [SOGoSAML2Session SAML2SessionWithIdentifier: _pwd
inContext: context];
rc = [[saml2Session login] isEqualToString: _login];
}
#endif /* SAML2_CONFIG */
else
rc = [[SOGoUserManager sharedUserManager] checkLogin: _login
password: _pwd
@ -314,4 +331,44 @@
[response addCookie: authCookie];
}
- (WOCookie *) cookieWithUsername: (NSString *) username
andPassword: (NSString *) password
inContext: (WOContext *) context
{
WOCookie *authCookie;
NSString *cookieValue, *cookieString, *appName, *sessionKey, *userKey, *securedPassword;
//
// We create a new cookie - thus we create a new session
// associated to the user. For security, we generate:
//
// A- a session key
// B- a user key
//
// In memcached, the session key will be associated to the user's password
// which will be XOR'ed with the user key.
//
sessionKey = [SOGoSession generateKeyForLength: 16];
userKey = [SOGoSession generateKeyForLength: 64];
NSString *value = [NSString stringWithFormat: @"%@:%@", username, password];
securedPassword = [SOGoSession securedValue: value usingKey: userKey];
[SOGoSession setValue: securedPassword forSessionKey: sessionKey];
//cookieString = [NSString stringWithFormat: @"%@:%@",
// username, password];
cookieString = [NSString stringWithFormat: @"%@:%@",
userKey, sessionKey];
cookieValue = [NSString stringWithFormat: @"basic %@",
[cookieString stringByEncodingBase64]];
authCookie = [WOCookie cookieWithName: [self cookieNameInContext: context]
value: cookieValue];
appName = [[context request] applicationName];
[authCookie setPath: [NSString stringWithFormat: @"/%@/", appName]];
return authCookie;
}
@end /* SOGoWebAuthenticator */

View File

@ -485,13 +485,17 @@
BOOL canLogoff;
id auth;
SOGoSystemDefaults *sd;
NSString *authType;
auth = [[self clientObject] authenticatorInContext: context];
if ([auth respondsToSelector: @selector (cookieNameInContext:)])
{
sd = [SOGoSystemDefaults sharedSystemDefaults];
if ([[sd authenticationType] isEqualToString: @"cas"])
authType = [sd authenticationType];
if ([authType isEqualToString: @"cas"])
canLogoff = [sd CASLogoutEnabled];
else if ([authType isEqualToString: @"saml2"])
canLogoff = [sd SAML2LogoutEnabled];
else
canLogoff = [[auth cookieNameInContext: context] length] > 0;
}

View File

@ -4,3 +4,7 @@ ADDITIONAL_CPPFLAGS += \
-DSOGO_MAJOR_VERSION=$(MAJOR_VERSION) \
-DSOGO_MINOR_VERSION=$(MINOR_VERSION) \
-DSOGO_SUBMINOR_VERSION=$(SUBMINOR_VERSION)
ifeq ($(HAS_LIBRARY_lasso), yes)
ADDITIONAL_CPPFLAGS += $(LASSO_CFLAGS)
endif

View File

@ -47,6 +47,9 @@
#import <SOGo/SOGoCache.h>
#import <SOGo/SOGoCASSession.h>
#import <SOGo/SOGoDomainDefaults.h>
#if defined(SAML2_CONFIG)
#import <SOGo/SOGoSAML2Session.h>
#endif /* SAML2_ENABLE */
#import <SOGo/SOGoSystemDefaults.h>
#import <SOGo/SOGoUser.h>
#import <SOGo/SOGoUserManager.h>
@ -100,46 +103,6 @@
return ([[self cookieUsername] length]);
}
- (WOCookie *) _cookieWithUsername: (NSString *) username
andPassword: (NSString *) password
forAuthenticator: (SOGoWebAuthenticator *) auth
{
WOCookie *authCookie;
NSString *cookieValue, *cookieString, *appName, *sessionKey, *userKey, *securedPassword;
//
// We create a new cookie - thus we create a new session
// associated to the user. For security, we generate:
//
// A- a session key
// B- a user key
//
// In memcached, the session key will be associated to the user's password
// which will be XOR'ed with the user key.
//
sessionKey = [SOGoSession generateKeyForLength: 16];
userKey = [SOGoSession generateKeyForLength: 64];
NSString *value = [NSString stringWithFormat: @"%@:%@", username, password];
securedPassword = [SOGoSession securedValue: value usingKey: userKey];
[SOGoSession setValue: securedPassword forSessionKey: sessionKey];
//cookieString = [NSString stringWithFormat: @"%@:%@",
// username, password];
cookieString = [NSString stringWithFormat: @"%@:%@",
userKey, sessionKey];
cookieValue = [NSString stringWithFormat: @"basic %@",
[cookieString stringByEncodingBase64]];
authCookie = [WOCookie cookieWithName: [auth cookieNameInContext: context]
value: cookieValue];
appName = [[context request] applicationName];
[authCookie setPath: [NSString stringWithFormat: @"/%@/", appName]];
return authCookie;
}
- (WOCookie *) _cookieWithUsername: (NSString *) username
{
WOCookie *loginCookie;
@ -172,7 +135,8 @@
return loginCookie;
}
- (WOCookie *) _casLocationCookie: (BOOL) cookieReset
- (WOCookie *) _authLocationCookie: (BOOL) cookieReset
withName: (NSString *) cookieName
{
WOCookie *locationCookie;
NSString *appName;
@ -180,7 +144,7 @@
NSCalendarDate *date;
rq = [context request];
locationCookie = [WOCookie cookieWithName: @"cas-location" value: [rq uri]];
locationCookie = [WOCookie cookieWithName: cookieName value: [rq uri]];
appName = [rq applicationName];
[locationCookie setPath: [NSString stringWithFormat: @"/%@/", appName]];
if (cookieReset)
@ -261,9 +225,9 @@
username = [NSString stringWithFormat: @"%@@%@", username, domain];
}
authCookie = [self _cookieWithUsername: username
andPassword: password
forAuthenticator: auth];
authCookie = [auth cookieWithUsername: username
andPassword: password
inContext: context];
[response addCookie: authCookie];
supportedLanguages = [[SOGoSystemDefaults sharedSystemDefaults]
@ -357,14 +321,15 @@
{
auth = [[WOApplication application]
authenticatorInContext: context];
casCookie = [self _cookieWithUsername: login
andPassword: [casSession identifier]
forAuthenticator: auth];
casCookie = [auth cookieWithUsername: login
andPassword: [casSession identifier]
inContext: context];
[casSession updateCache];
newLocation = [rq cookieValueForKey: @"cas-location"];
/* login callback, we expire the "cas-location" cookie, created
below */
casLocationCookie = [self _casLocationCookie: YES];
casLocationCookie = [self _authLocationCookie: YES
withName: @"cas-location"];
}
}
}
@ -388,7 +353,8 @@
newLocation
= [SOGoCASSession CASURLWithAction: @"login"
andParameters: [self _casRedirectKeys]];
casLocationCookie = [self _casLocationCookie: NO];
casLocationCookie = [self _authLocationCookie: NO
withName: @"cas-location"];
}
response = [self redirectToLocation: newLocation];
if (casCookie)
@ -399,6 +365,51 @@
return response;
}
#if defined(SAML2_CONFIG)
- (id <WOActionResults>) _saml2DefaultAction
{
WOResponse *response;
NSString *login, *newLocation, *oldLocation;
WOCookie *saml2LocationCookie;
WORequest *rq;
saml2LocationCookie = nil;
newLocation = nil;
login = [[context activeUser] login];
if ([login isEqualToString: @"anonymous"])
login = nil;
if (login)
{
rq = [context request];
newLocation = [rq cookieValueForKey: @"saml2-location"];
if (newLocation)
saml2LocationCookie = [self _authLocationCookie: YES
withName: @"saml2-location"];
else
{
oldLocation = [[self clientObject] baseURLInContext: context];
newLocation = [NSString stringWithFormat: @"%@%@",
oldLocation, [login stringByEscapingURL]];
}
}
else
{
newLocation = [SOGoSAML2Session authenticationURLInContext: context];
saml2LocationCookie = [self _authLocationCookie: NO
withName: @"saml2-location"];
}
response = [self redirectToLocation: newLocation];
if (saml2LocationCookie)
[response addCookie: saml2LocationCookie];
return response;
}
#endif /* SAML2_CONFIG */
- (id <WOActionResults>) _standardDefaultAction
{
NSObject <WOActionResults> *response;
@ -433,13 +444,21 @@
- (id <WOActionResults>) defaultAction
{
SOGoSystemDefaults *sd;
NSString *authenticationType;
id <WOActionResults> result;
sd = [SOGoSystemDefaults sharedSystemDefaults];
authenticationType = [[SOGoSystemDefaults sharedSystemDefaults]
authenticationType];
if ([authenticationType isEqualToString: @"cas"])
result = [self _casDefaultAction];
#if defined(SAML2_CONFIG)
else if ([authenticationType isEqualToString: @"saml2"])
result = [self _saml2DefaultAction];
#endif /* SAML2_CONFIG */
else
result = [self _standardDefaultAction];
return ([[sd authenticationType] isEqualToString: @"cas"]
? [self _casDefaultAction]
: [self _standardDefaultAction]);
return result;
}
- (BOOL) isPublicInContext: (WOContext *) localContext
@ -553,9 +572,9 @@
}
response = [self responseWith204];
authCookie = [self _cookieWithUsername: username
andPassword: newPassword
forAuthenticator: auth];
authCookie = [auth cookieWithUsername: username
andPassword: newPassword
inContext: context];
[response addCookie: authCookie];
}
else

View File

@ -20,11 +20,22 @@
* Boston, MA 02111-1307, USA.
*/
#import <Foundation/NSCalendarDate.h>
#import <Foundation/NSTimeZone.h>
#import <NGObjWeb/SoApplication.h>
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/SoObject.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WOCookie.h>
#import <NGObjWeb/WODirectAction.h>
#import <NGObjWeb/WORequest.h>
#import <NGObjWeb/WOResponse.h>
#import <NGExtensions/NSCalendarDate+misc.h>
#import <NGExtensions/NSString+misc.h>
#import <SOGo/SOGoSAML2Session.h>
#import <SOGo/SOGoWebAuthenticator.h>
@interface SOGoSAML2Actions : WODirectAction
@end
@ -47,4 +58,60 @@
return response;
}
- (WOCookie *) _authLocationResetCookieWithName: (NSString *) cookieName
{
WOCookie *locationCookie;
NSString *appName;
WORequest *rq;
NSCalendarDate *date;
rq = [context request];
locationCookie = [WOCookie cookieWithName: cookieName value: [rq uri]];
appName = [rq applicationName];
[locationCookie setPath: [NSString stringWithFormat: @"/%@/", appName]];
date = [NSCalendarDate calendarDate];
[date setTimeZone: [NSTimeZone timeZoneWithAbbreviation: @"GMT"]];
[locationCookie setExpires: [date yesterday]];
return locationCookie;
}
- (WOResponse *) saml2SignOnPOSTAction
{
WORequest *rq;
WOResponse *response;
SoApplication *application;
SOGoSAML2Session *newSession;
WOCookie *authCookie;
NSString *login, *oldLocation, *newLocation;
SOGoWebAuthenticator *auth;
rq = [context request];
if ([[rq method] isEqualToString: @"POST"])
{
newSession = [SOGoSAML2Session SAML2SessionInContext: context];
[newSession processAuthnResponse: [rq formValueForKey: @"SAMLResponse"]];
login = [newSession login];
application = [SoApplication application];
auth = [application authenticatorInContext: context];
authCookie = [auth cookieWithUsername: login
andPassword: [newSession identifier]
inContext: context];
oldLocation = [[context clientObject] baseURLInContext: context];
newLocation = [NSString stringWithFormat: @"%@/%@",
oldLocation, [login stringByEscapingURL]];
response = [context response];
[response setStatus: 302];
[response setHeader: @"text/plain; charset=utf-8"
forKey: @"content-type"];
[response setHeader: newLocation forKey: @"location"];
[response addCookie: authCookie];
}
return response;
}
@end

View File

@ -124,21 +124,36 @@
actionClass = "SOGoSAML2Actions";
actionName = "saml2Metadata";
};
/* crash = {
protectedBy = "<public>";
pageName = "SOGoRootPage";
actionName = "crash";
};
exception = {
protectedBy = "<public>";
pageName = "SOGoRootPage";
actionName = "exception";
};
raisedException = {
protectedBy = "<public>";
pageName = "SOGoRootPage";
actionName = "raisedException";
}; */
saml2-signon-post = {
protectedBy = "<public>";
actionClass = "SOGoSAML2Actions";
actionName = "saml2SignOnPOST";
};
/* saml2-signon-redirect = {
protectedBy = "<public>";
actionClass = "SOGoSAML2Actions";
actionName = "saml2SignOnRedirect";
};
saml2-signon-soap = {
protectedBy = "<public>";
actionClass = "SOGoSAML2Actions";
actionName = "saml2SignOnSOAP";
};
crash = {
protectedBy = "<public>";
pageName = "SOGoRootPage";
actionName = "crash";
};
exception = {
protectedBy = "<public>";
pageName = "SOGoRootPage";
actionName = "exception";
};
raisedException = {
protectedBy = "<public>";
pageName = "SOGoRootPage";
actionName = "raisedException";
}; */
connect = {
protectedBy = "<public>";
pageName = "SOGoRootPage";