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
- A mail client must have support to acquire an OAuth2 token from your IdP (however many clients lack generic OAuth2 / OIDC provider support).
- The mail client then provides that token as the user password via the login mechanism
XOAUTH2
orOAUTHBEARER
. - DMS (Dovecot) will then check the validity of that token against the Authentication Service it was configured with.
- 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 withgrep
on DMS logs (for Dovecot and Postfix services). When not runningcurl
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:
- A working DMS server
- An Authentik server (documentation)
- A Roundcube server (docker image or bare metal install)
Setup Instructions
Update your Docker Compose ENV config to include:
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/
- Create a new OAuth2 provider.
- Note the client id and client secret. Roundcube will need this.
- 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;