parent
5a5464dc61
commit
be608dc76c
|
@ -425,25 +425,31 @@ Defaults to `YES` when unset.
|
||||||
|The location of the SSL private key file on the filesystem that is used
|
|The location of the SSL private key file on the filesystem that is used
|
||||||
by SOGo to sign and encrypt communications with the SAML2 identity
|
by SOGo to sign and encrypt communications with the SAML2 identity
|
||||||
provider. This file must be generated for each running SOGo service
|
provider. This file must be generated for each running SOGo service
|
||||||
(rather than host).
|
(rather than host). Make sure this file is readable by the SOGo user.
|
||||||
|
|
||||||
|S |SOGoSAML2CertiticateLocation
|
|S |SOGoSAML2CertiticateLocation
|
||||||
|The location of the SSL certificate file. This file must be generated
|
|The location of the SSL certificate file. This file must be generated
|
||||||
for each running SOGo service.
|
for each running SOGo service. Make sure this file is readable by the SOGo user.
|
||||||
|
|
||||||
|S |SOGoSAML2IdpMetadataLocation
|
|S |SOGoSAML2IdpMetadataLocation
|
||||||
|The location of the metadata file that describes the services available
|
|The location of the metadata file that describes the services available
|
||||||
on the SAML2 identify provider.
|
on the SAML2 identify provider. The content of this file is usually generated
|
||||||
|
directly by your SAML 2.0 IdP solution. For example, using SimpleSAMLphp, you
|
||||||
|
can get the metadata directly from https://MYSERVER/simplesaml/saml2/idp/metadata.php
|
||||||
|
Make sure this file is readable by the SOGo user.
|
||||||
|
|
||||||
|S |SOGoSAML2IdpPublicKeyLocation
|
|S |SOGoSAML2IdpPublicKeyLocation
|
||||||
|The location of the SSL public key file on the filesystem that is used
|
|The location of the SSL public key file on the filesystem that is used
|
||||||
by SOGo to sign and encrypt communications with the SAML2 identity
|
by SOGo to sign and encrypt communications with the SAML2 identity
|
||||||
provider. This file should be part of the setup of your identity
|
provider. This file should be part of the setup of your identity
|
||||||
provider.
|
provider. Make sure this file is readable by the SOGo user.
|
||||||
|
|
||||||
|S |SOGoSAML2IdpCertificateLocation
|
|S |SOGoSAML2IdpCertificateLocation
|
||||||
|The location of the SSL certificate file. This file should be part of
|
|The location of the SSL certificate file. This file should be part of
|
||||||
the setup of your identity provider.
|
the setup of your identity provider. Make sure this file is readable by the SOGo user.
|
||||||
|
|
||||||
|
|S |SOGoSAML2LoginAttribute
|
||||||
|
|The attribute provided by the IdP to identify the user in SOGo.
|
||||||
|
|
||||||
|S |SOGoSAML2LogoutEnabled
|
|S |SOGoSAML2LogoutEnabled
|
||||||
|Boolean value indicated whether the "Logout" link is enabled when using
|
|Boolean value indicated whether the "Logout" link is enabled when using
|
||||||
|
@ -1230,13 +1236,32 @@ documentation of your identity provider and the SAML2 configuration keys
|
||||||
that are listed above for proper setup. Once a SOGo instance is
|
that are listed above for proper setup. Once a SOGo instance is
|
||||||
configured properly, the metadata for that instance can be retrieved
|
configured properly, the metadata for that instance can be retrieved
|
||||||
from `http://<hostname>/SOGo/saml2-metadata` for registration with the
|
from `http://<hostname>/SOGo/saml2-metadata` for registration with the
|
||||||
identity provider.
|
identity provider. SOGo will dynamically generate the metadata based on
|
||||||
|
the SOGoSAML2CertificateLocation's content and the SOGo server name.
|
||||||
|
|
||||||
|
When using SimpleSAMLphp, make sure the convert OID to names by modifying your
|
||||||
|
`metadata/saml20-idp-hosted.php` to contain something like this:
|
||||||
|
|
||||||
|
----
|
||||||
|
'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
|
||||||
|
'authproc' => array(
|
||||||
|
100 => array('class' => 'core:AttributeMap', 'oid2name'),
|
||||||
|
),
|
||||||
|
----
|
||||||
|
|
||||||
|
If you want to test the IdP-initiated logout using SimpleSAMLphp, you can do so by opening
|
||||||
|
the following URL:
|
||||||
|
|
||||||
|
----
|
||||||
|
https://idp.example.org/simplesaml/saml2/idp/SingleLogoutService.php?ReturnTo=www.sogo.nu
|
||||||
|
----
|
||||||
|
|
||||||
In order to relay authentication information to your IMAP server and if
|
In order to relay authentication information to your IMAP server and if
|
||||||
you make use of the CrudeSAML SASL plugin, you need to make sure that
|
you make use of the CrudeSAML SASL plugin, you need to make sure that
|
||||||
_NGImap4AuthMechanism_ is configured to use the `SAML` mechanism. If you
|
_NGImap4AuthMechanism_ is configured to use the `SAML` mechanism. If you
|
||||||
make use of the CrudeSAML PAM plugin, this value may be left empty.
|
make use of the CrudeSAML PAM plugin, this value may be left empty.
|
||||||
|
|
||||||
|
|
||||||
Database Configuration
|
Database Configuration
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
7
NEWS
7
NEWS
|
@ -1,8 +1,13 @@
|
||||||
2.2.11 (2014-xx-xx)
|
2.2.11 (2014-xx-xx)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
- Improved the SAML2 documentation
|
||||||
|
|
||||||
Bug fixes
|
Bug fixes
|
||||||
- Now possible to specify the username attribute for SAML2 (SOGoSAML2LoginAttribute)
|
- 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)
|
||||||
|
|
||||||
2.2.10 (2014-11-21)
|
2.2.10 (2014-11-21)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<EntityDescriptor
|
||||||
|
entityID="%{base_url}/saml2-metadata"
|
||||||
|
xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
|
||||||
|
<SPSSODescriptor
|
||||||
|
AuthnRequestsSigned="true"
|
||||||
|
WantAssertionsSigned="true"
|
||||||
|
protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
|
||||||
|
<KeyDescriptor use="signing"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data><ds:X509Certificate>%{certificate}</ds:X509Certificate></ds:X509Data></ds:KeyInfo></KeyDescriptor><KeyDescriptor use="encryption"><ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:X509Data>%{certificate}<ds:X509Certificate></ds:X509Certificate></ds:X509Data></ds:KeyInfo></KeyDescriptor>
|
||||||
|
<SingleLogoutService
|
||||||
|
Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
|
||||||
|
Location="%{base_url}/saml2-sls" />
|
||||||
|
<SingleLogoutService
|
||||||
|
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
|
||||||
|
Location="%{base_url}/saml2-sls" />
|
||||||
|
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
|
||||||
|
<AssertionConsumerService
|
||||||
|
index="0"
|
||||||
|
isDefault="true"
|
||||||
|
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
||||||
|
Location="%{base_url}/saml2-signon-post" />
|
||||||
|
<AssertionConsumerService
|
||||||
|
index="1"
|
||||||
|
Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
|
||||||
|
Location="%{base_url}/saml2/artifactResponse" />
|
||||||
|
</SPSSODescriptor>
|
||||||
|
</EntityDescriptor>
|
|
@ -39,7 +39,9 @@
|
||||||
NSString *assertion;
|
NSString *assertion;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString *) metadataInContext: (WOContext *) context;
|
+ (NSString *) metadataInContext: (WOContext *) context
|
||||||
|
certificate: (NSString *) certificate;
|
||||||
|
|
||||||
+ (NSString *) authenticationURLInContext: (WOContext *) context;
|
+ (NSString *) authenticationURLInContext: (WOContext *) context;
|
||||||
|
|
||||||
+ (SOGoSAML2Session *) SAML2SessionInContext: (WOContext *) context;
|
+ (SOGoSAML2Session *) SAML2SessionInContext: (WOContext *) context;
|
||||||
|
|
|
@ -46,6 +46,28 @@
|
||||||
|
|
||||||
#import "SOGoSAML2Session.h"
|
#import "SOGoSAML2Session.h"
|
||||||
|
|
||||||
|
@interface NSString (SOGoCertificateExtension)
|
||||||
|
|
||||||
|
- (NSString *) cleanedUpCertificate;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation NSString (SOGoCertificateExtension)
|
||||||
|
|
||||||
|
- (NSString *) cleanedUpCertificate
|
||||||
|
{
|
||||||
|
NSMutableArray *a;
|
||||||
|
|
||||||
|
a = [NSMutableArray arrayWithArray: [self componentsSeparatedByString: @"\n"]];
|
||||||
|
[a removeObjectAtIndex: 0];
|
||||||
|
[a removeLastObject];
|
||||||
|
[a removeLastObject];
|
||||||
|
|
||||||
|
return [a componentsJoinedByString: @""];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@interface WOContext (SOGoSAML2Extension)
|
@interface WOContext (SOGoSAML2Extension)
|
||||||
|
|
||||||
- (NSString *) SAML2ServerURLString;
|
- (NSString *) SAML2ServerURLString;
|
||||||
|
@ -117,7 +139,9 @@ LassoServerInContext (WOContext *context)
|
||||||
format: @"certificate file '%@' could not be read",
|
format: @"certificate file '%@' could not be read",
|
||||||
filename];
|
filename];
|
||||||
|
|
||||||
metadata = [SOGoSAML2Session metadataInContext: context];
|
metadata = [SOGoSAML2Session metadataInContext: context
|
||||||
|
certificate: certContent];
|
||||||
|
|
||||||
/* FIXME: enable key password in config ? */
|
/* FIXME: enable key password in config ? */
|
||||||
server = lasso_server_new_from_buffers ([metadata UTF8String],
|
server = lasso_server_new_from_buffers ([metadata UTF8String],
|
||||||
[keyContent UTF8String],
|
[keyContent UTF8String],
|
||||||
|
@ -179,8 +203,10 @@ LassoServerInContext (WOContext *context)
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString *) metadataInContext: (WOContext *) context
|
+ (NSString *) metadataInContext: (WOContext *) context
|
||||||
|
certificate: (NSString *) certificate
|
||||||
{
|
{
|
||||||
NSString *metadata, *serverURLString, *filename;
|
NSString *serverURLString, *filename;
|
||||||
|
NSMutableString *metadata;
|
||||||
NSBundle *bundle;
|
NSBundle *bundle;
|
||||||
|
|
||||||
bundle = [NSBundle bundleForClass: self];
|
bundle = [NSBundle bundleForClass: self];
|
||||||
|
@ -188,9 +214,16 @@ LassoServerInContext (WOContext *context)
|
||||||
if (filename)
|
if (filename)
|
||||||
{
|
{
|
||||||
serverURLString = [context SAML2ServerURLString];
|
serverURLString = [context SAML2ServerURLString];
|
||||||
metadata = [[NSString stringWithContentsOfFile: filename]
|
|
||||||
stringByReplacingString: @"%{base_url}"
|
metadata = [NSMutableString stringWithContentsOfFile: filename];
|
||||||
withString: serverURLString];
|
[metadata replaceOccurrencesOfString: @"%{base_url}"
|
||||||
|
withString: serverURLString
|
||||||
|
options: 0
|
||||||
|
range: NSMakeRange(0, [metadata length])];
|
||||||
|
[metadata replaceOccurrencesOfString: @"%{certificate}"
|
||||||
|
withString: [certificate cleanedUpCertificate]
|
||||||
|
options: 0
|
||||||
|
range: NSMakeRange(0, [metadata length])];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
metadata = nil;
|
metadata = nil;
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
#import <NGExtensions/NSString+misc.h>
|
#import <NGExtensions/NSString+misc.h>
|
||||||
|
|
||||||
#import <SOGo/SOGoSAML2Session.h>
|
#import <SOGo/SOGoSAML2Session.h>
|
||||||
|
#import <SOGo/SOGoSession.h>
|
||||||
|
#import <SOGo/SOGoSystemDefaults.h>
|
||||||
#import <SOGo/SOGoWebAuthenticator.h>
|
#import <SOGo/SOGoWebAuthenticator.h>
|
||||||
|
|
||||||
@interface SOGoSAML2Actions : WODirectAction
|
@interface SOGoSAML2Actions : WODirectAction
|
||||||
|
@ -42,20 +44,76 @@
|
||||||
|
|
||||||
- (WOResponse *) saml2MetadataAction
|
- (WOResponse *) saml2MetadataAction
|
||||||
{
|
{
|
||||||
|
NSString *metadata, *certContent;
|
||||||
|
SOGoSystemDefaults *sd;
|
||||||
WOResponse *response;
|
WOResponse *response;
|
||||||
NSString *metadata;
|
|
||||||
|
|
||||||
response = [context response];
|
response = [context response];
|
||||||
[response setHeader: @"application/xml; charset=utf-8"
|
[response setHeader: @"application/xml; charset=utf-8"
|
||||||
forKey: @"content-type"];
|
forKey: @"content-type"];
|
||||||
|
|
||||||
metadata = [SOGoSAML2Session metadataInContext: context];
|
sd = [SOGoSystemDefaults sharedSystemDefaults];
|
||||||
|
|
||||||
|
certContent = [NSString stringWithContentsOfFile: [sd SAML2CertificateLocation]];
|
||||||
|
|
||||||
|
metadata = [SOGoSAML2Session metadataInContext: context
|
||||||
|
certificate: certContent];
|
||||||
|
|
||||||
[response setContentEncoding: NSUTF8StringEncoding];
|
[response setContentEncoding: NSUTF8StringEncoding];
|
||||||
[response appendContentString: metadata];
|
[response appendContentString: metadata];
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (WOResponse *) saml2SingleLogoutServiceAction
|
||||||
|
{
|
||||||
|
NSString *userName, *value, *cookieName;
|
||||||
|
SOGoWebAuthenticator *auth;
|
||||||
|
WOResponse *response;
|
||||||
|
NSCalendarDate *date;
|
||||||
|
WOCookie *cookie;
|
||||||
|
NSArray *creds;
|
||||||
|
|
||||||
|
userName = [[context activeUser] login];
|
||||||
|
[self logWithFormat: @"SAML2 IdP-initiated SLO for user '%@'", userName];
|
||||||
|
|
||||||
|
response = [context response];
|
||||||
|
|
||||||
|
if ([userName isEqualToString: @"anonymous"])
|
||||||
|
return response;
|
||||||
|
|
||||||
|
cookie = nil;
|
||||||
|
|
||||||
|
date = [NSCalendarDate calendarDate];
|
||||||
|
[date setTimeZone: [NSTimeZone timeZoneWithAbbreviation: @"GMT"]];
|
||||||
|
|
||||||
|
// We cleanup the memecached/database session cache. We do this before
|
||||||
|
// invoking _logoutCookieWithDate: in order to obtain its value.
|
||||||
|
auth = [[SoApplication application] authenticatorInContext: context];
|
||||||
|
|
||||||
|
if ([auth respondsToSelector: @selector (cookieNameInContext:)])
|
||||||
|
{
|
||||||
|
cookieName = [auth cookieNameInContext: context];
|
||||||
|
value = [[context request] cookieValueForKey: cookieName];
|
||||||
|
creds = [auth parseCredentials: value];
|
||||||
|
|
||||||
|
if ([creds count] > 1)
|
||||||
|
[SOGoSession deleteValueForSessionKey: [creds objectAtIndex: 1]];
|
||||||
|
|
||||||
|
if ([cookieName length])
|
||||||
|
{
|
||||||
|
cookie = [WOCookie cookieWithName: cookieName value: @"discard"];
|
||||||
|
[cookie setPath: [NSString stringWithFormat: @"/%@/", [[context request] applicationName]]];
|
||||||
|
[cookie setExpires: [date yesterday]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cookie)
|
||||||
|
[response addCookie: cookie];
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
- (WOCookie *) _authLocationResetCookieWithName: (NSString *) cookieName
|
- (WOCookie *) _authLocationResetCookieWithName: (NSString *) cookieName
|
||||||
{
|
{
|
||||||
WOCookie *locationCookie;
|
WOCookie *locationCookie;
|
||||||
|
|
|
@ -133,6 +133,11 @@
|
||||||
actionClass = "SOGoSAML2Actions";
|
actionClass = "SOGoSAML2Actions";
|
||||||
actionName = "saml2SignOnPOST";
|
actionName = "saml2SignOnPOST";
|
||||||
};
|
};
|
||||||
|
saml2-sls = {
|
||||||
|
protectedBy = "<public>";
|
||||||
|
actionClass = "SOGoSAML2Actions";
|
||||||
|
actionName = "saml2SingleLogoutService";
|
||||||
|
};
|
||||||
/* saml2-signon-redirect = {
|
/* saml2-signon-redirect = {
|
||||||
protectedBy = "<public>";
|
protectedBy = "<public>";
|
||||||
actionClass = "SOGoSAML2Actions";
|
actionClass = "SOGoSAML2Actions";
|
||||||
|
|
Loading…
Reference in New Issue