SOGo with OpenID authentication
Notes on configuring the following setup:
- SOGo serving a webmail interface as well as CalDAV and CardDAV via Apache as a reverse proxy
- SOGo authentication against OpenID, provided by Keycloak
- SOGo authentication against Dovecot via xoauth2, and Postfix which uses Dovecot as an authentication backend
- All services using an LDAP server as a single source of truth, provided by FreeIPA / 389 Directory Server
Preconditions:
- Keycloak and FreeIPA are up and running, with Keycloak user federation configured to use FreeIPA via LDAP
- Apache is up and running
- SOGo 5.12+ is installed
SOGo configuration
Parameters relevant to OpenID authentication in /etc/sogo/sogo.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
| {
// Must match Apache configuration
WOPort = 127.0.0.1:10000;
// Set authentication to OpenID
SOGoAuthenticationType = openid;
// Disable to allow redirects to keycloak and back
SOGoXSRFValidationEnabled = NO;
// Set xoauth2 for SMTP, IMAP, and ManageSieve
SOGoSMTPAuthenticationType = xoauth2;
NGImap4AuthMechanism = xoauth2;
// Use Dovecot IMAP with explicit TLS
SOGoIMAPServer = "imaps://mail.example.net:993";
// Use Dovecot ManageSieve with StartTLS
SOGoSieveServer = "sieve://mail.example.net:4190/?tls=YES";
// Use Postfix submission with StartTLS
SOGoMailingMechanism = smtp;
SOGoSMTPServer = "smtp://mail.example.net:587/?tls=YES";
OCSOpenIdURL = "mysql://sogo:foobar@localhost:3306/sogo/sogo_openid";
// Create a new client in Keycloak with Client authentication and Standard flow enabled, then add credentials below
SOGoOpenIdConfigUrl = "https://auth.example.net/realms/example/.well-known/openid-configuration";
SOGoOpenIdClient = sogo;
SOGoOpenIdClientSecret = foobar;
SOGoOpenIdScope = "openid profile email";
// This is the key within the OpenID scope that will later be used to look up the user in the LDAP directory
SOGoOpenIdEmailParam = "preferred_username";
SOGoOpenIdEnableRefreshToken = YES;
SOGoOpenIdTokenCheckInterval = 30;
SOGoOpenIdLogoutEnabled = YES;
// This is a somewhat tricky part. SOGo seems unable to use OpenID alone; instead, an additional UserSource is used to look up the user and their metadata after successful authentication. In this case, the preferred_username value (which in our case is <firstname.lastname>) is used to find the respective user entry in the LDAP directory.
SOGoUserSources = (
{
type = ldap;
id = example;
CNFieldName = cn;
IDFieldName = uid;
UIDFieldName = uid;
IMAPLoginFieldName = uid; // username used for Dovecot/Postfix
MailFieldNames = (mail);
baseDN = "cn=users,cn=accounts,dc=ldap,dc=example,dc=net";
filter = "(objectClass='inetorgperson') AND (memberOf='cn=mailusers,cn=groups,cn=accounts,dc=ldap,dc=example,dc=net')";
bindDN = "uid=sogo,cn=sysaccounts,cn=etc,dc=ldap,dc=example,dc=net";
bindPassword = foobar;
bindFields = (uid);
bindAsCurrentUser = NO;
canAuthenticate = YES;
hostname = "ldap://127.0.0.1:389";
...
}
);
...
}
|
Apache configuration
Apache configurations found on the internet often seem outdated or inaccurate. Here is a working example for the above setup: /etc/apache2/sites-available/10-sogo.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
| <VirtualHost *:80>
ServerName mail.example.net
Redirect permanent / https://mail.example.net
</VirtualHost>
<VirtualHost *:443>
ServerName mail.example.net
DocumentRoot /usr/lib/GNUstep/SOGo/WebServerResources
Alias /SOGo.woa/WebServerResources/ /usr/lib/GNUstep/SOGo/WebServerResources/
<Directory "/usr/lib/GNUstep/SOGo/WebServerResources">
AllowOverride None
Options +FollowSymlinks
Require all granted
</Directory>
RequestHeader set "x-webobjects-server-port" "443"
RequestHeader set "x-webobjects-server-name" "mail.example.net"
RequestHeader set "x-webobjects-server-url" "https://mail.example.net"
RewriteEngine On
RewriteRule ^/?$ https://mail.example.net/SOGo/ [R=301,L]
RewriteRule ^/.well-known/caldav/?$ /SOGo/dav [R=301,L]
RewriteRule ^/.well-known/carddav/?$ /SOGo/dav [R=301,L]
ProxyPreserveHost On
SetEnv proxy-nokeepalive 1
ProxyPass /SOGo/ "http://127.0.0.1:29080/SOGo/" retry=0
ProxyPassReverse /SOGo/ "http://127.0.0.1:29080/SOGo/"
#ProxyPass /Microsoft-Server-ActiveSync http://127.0.0.1:29080/SOGo/Microsoft-Server-ActiveSync retry=0
#ProxyPassReverse /Microsoft-Server-ActiveSync http://127.0.0.1:29080/SOGo/Microsoft-Server-ActiveSync
Header always add Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
SSLEngine On
SSLCertificateFile /etc/letsencrypt/live/example.net/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.net/privkey.pem
</VirtualHost>
|
Dovecot/Postfix configuration
A well-tested configuration to enable xoauth2 authentication for Postfix and Dovecot (<= 2.3) can be found here.
There are a few optional modifications to the above example configuration:
oauthbearer is not needed as SOGo uses xoauth2- If
plain authentication with an LDAP backend is used for other email clients, the userdb configuration might need to be changed from static to ldap, including the LDAP-specific configuration
Instead of the introspection endpoint that requires another client to be created in Keycloak, you can also use the following in dovecot-oauth2.conf.ext
1
2
| tokeninfo_url = https://auth.example.net/realms/example/protocol/openid-connect/userinfo?ignore=
username_attribute = preferred_username
|