16.11.2025 – Linux/SOGo_with_OpenID_authentication.md

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