Skip to content

Authentication - OAuth2 / OIDC

This feature enables support for delegating DMS account authentication through to an external Identity Provider (IdP).

Receiving mail requires a DMS account to exist

If you expect DMS to receive mail, you must provision an account into DMS in advance. Otherwise DMS has no awareness of your externally manmaged users and will reject delivery.

There are plans to implement support to provision users through a SCIM 2.0 API. An IdP that can operate as a SCIM Client (eg: Authentik) would then integrate with DMS for user provisioning. Until then you must keep your user accounts in sync manually via your configured ACCOUNT_PROVISIONER.

How the feature works
  1. A mail client must have support to acquire an OAuth2 token from your IdP (however many clients lack generic OAuth2 / OIDC provider support).
  2. The mail client then provides that token as the user password via the login mechanism XOAUTH2 or OAUTHBEARER.
  3. DMS (Dovecot) will then check the validity of that token against the Authentication Service it was configured with.
  4. If the response returned is valid for the user account, authentication is successful.

XOAUTH2 (Googles widely adopted implementation) and OAUTHBEARER (the newer variant standardized by RFC 7628 in 2015) are supported as standards for verifying that a OAuth Bearer Token (RFC 6750 from 2012) is valid at the identity provider that created the token. The token itself in both cases is expected to be can an opaque Access Token, but it is possible to use a JWT ID Token (which encodes additional information into the token itself).

A mail client like Thunderbird has limited OAuth2 / OIDC support. The software maintains a hard-coded list of providers supported. Roundcube is a webmail client that does have support for generic providers, allowing you to integrate with a broader range of IdP services.


Documentation for this feature is WIP

See the initial feature support and existing issues for guidance that has not yet been documented officially.

Verify authentication works

If you have a compatible mail client you can verify login through that.


CLI - Verify with curl
# Shell into your DMS container:
docker exec -it dms bash

# Adjust these variables for the methods below to use:
export AUTH_METHOD='OAUTHBEARER' USER_ACCOUNT='hello@example.com' ACCESS_TOKEN='DMS_YWNjZXNzX3Rva2Vu'

# Authenticate via IMAP (Dovecot):
curl --silent --url 'imap://localhost:143' \
    --login-options "AUTH=${AUTH_METHOD}" --user "${USER_ACCOUNT}" --oauth2-bearer "${ACCESS_TOKEN}" \
    --request 'LOGOUT' \
    && grep "dovecot: imap-login: Login: user=<${USER_ACCOUNT}>, method=${AUTH_METHOD}" /var/log/mail/mail.log

# Authenticate via SMTP (Postfix), sending a mail with the same sender(from) and recipient(to) address:
# NOTE: `curl` seems to require `--upload-file` with some mail content provided to test SMTP auth.
curl --silent --url 'smtp://localhost:587' \
    --login-options "AUTH=${AUTH_METHOD}" --user "${USER_ACCOUNT}" --oauth2-bearer "${ACCESS_TOKEN}" \
    --mail-from "${USER_ACCOUNT}" --mail-rcpt "${USER_ACCOUNT}" --upload-file - <<< 'RFC 5322 content - not important' \
    && grep "postfix/submission/smtpd.*, sasl_method=${AUTH_METHOD}, sasl_username=${USER_ACCOUNT}" /var/log/mail/mail.log

Troubleshooting:

  • Add --verbose to the curl options. This will output the protocol exchange which includes if authentication was successful or failed.
  • The above example chains the curl commands with grep on DMS logs (for Dovecot and Postfix services). When not running curl from the DMS container, ensure you check the logs correctly, or inspect the --verbose output instead.

curl bug with XOAUTH2

Older releases of curl have a bug with XOAUTH2 support since 7.80.0 (Nov 2021) but fixed from 8.6.0 (Jan 2024). It treats XOAUTH2 as OAUTHBEARER.

If you use docker exec to run curl from within DMS, the current DMS v14 release (Debian 12 with curl 7.88.1) is affected by this bug.

Config Examples

Authentik with Roundcube

This example assumes you have already set up:

Setup Instructions

Update your Docker Compose ENV config to include:

compose.yaml
services:
  mailserver:
    env:
      # Enable the feature:
      - ENABLE_OAUTH2=1
      # Specify the user info endpoint URL of the oauth2 server for token inspection:
      - OAUTH2_INTROSPECTION_URL=https://authentik.example.com/application/o/userinfo/
  1. Create a new OAuth2 provider.
  2. Note the client id and client secret. Roundcube will need this.
  3. Set the allowed redirect url to the equivalent of https://roundcube.example.com/index.php/login/oauth for your RoundCube instance.

Add the following to oauth2.inc.php (documentation):

$config['oauth_provider'] = 'generic';
$config['oauth_provider_name'] = 'Authentik';
$config['oauth_client_id'] = '<insert client id here>';
$config['oauth_client_secret'] = '<insert client secret here>';
$config['oauth_auth_uri'] = 'https://authentik.example.com/application/o/authorize/';
$config['oauth_token_uri'] = 'https://authentik.example.com/application/o/token/';
$config['oauth_identity_uri'] = 'https://authentik.example.com/application/o/userinfo/';

// Optional: disable SSL certificate check on HTTP requests to OAuth server. For possible values, see:
// http://docs.guzzlephp.org/en/stable/request-options.html#verify
$config['oauth_verify_peer'] = false;

$config['oauth_scope'] = 'email openid profile';
$config['oauth_identity_fields'] = ['email'];

// Boolean: automatically redirect to OAuth login when opening Roundcube without a valid session
$config['oauth_login_redirect'] = false;