Issue Description
When trying to use a JMAP client (Plume) to log into the server, the client correctly pulls <server.tld>/.well-known/openid-configuration and shows the authorization_endpoint website at <server.tld>/login which displays a username and password prompt, as if I was using the internal directory, instead of OIDC. I would expect to either get the same login prompt as <server.tld>/admin/login which prompts for the username and directs to the OIDC provider(Authentik in my case), or be redirected to the OIDC provider directly.
Expected Behavior
When logging in with a JMAP/OIDC compliant client, the user should be directed to the OIDC provider which is configured in Stalwart.
Actual Behavior
The user is directed to a regular login prompt used for the internal directory, making it impossible to login with OIDC without using an app password.
Reproduction Steps
- Configure Stalwart to use an external OIDC directory
- Use a JMAP compliant client that utilizes openid-configuration and attempt to configure the mailbox
Stalwart Version
v0.16.x
Installation Method
Docker
Database Backend
PostgreSQL
Blob Storage
Filesystem
Search Engine
Internal
Directory Backend
OIDC
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on
The behavior you’re seeing is by design, and it’s a fundamental distinction in how Stalwart handles the two OIDC-related roles it can play.
Stalwart’s /.well-known/openid-configuration and /login page belong to Stalwart’s built-in OIDC Provider, not to your external Authentik directory. These two things are independent:
-
Stalwart as an OIDC Provider (always active): Stalwart exposes its own OAuth/OIDC endpoints (/.well-known/openid-configuration, /login, /auth/token, etc.) so that clients can authenticate against Stalwart itself. The /login page will always show Stalwart’s own username/password prompt, because Stalwart is acting as the authorization server in this flow. This is what Plume sees when it discovers the OIDC configuration.
-
External OIDC as a backend directory (your Authentik setup): When you configure Authentik as an OIDC directory, Stalwart uses it only to validate access tokens that are presented to it via the OAUTHBEARER SASL mechanism. Stalwart does not redirect users to Authentik during this flow - it does not initiate the OIDC flow itself.
The correct flow with an external OIDC provider like Authentik is:
- Your mail client must obtain an access token directly from Authentik (outside of Stalwart).
- The client then presents that token to Stalwart using the
OAUTHBEARER SASL mechanism.
- Stalwart validates the token against Authentik’s userinfo endpoint.
The docs explicitly state:
“Clients authenticate over IMAP, POP3, SMTP, or JMAP using the OAUTHBEARER SASL mechanism, which carries an access token already obtained from the identity provider. Stalwart does not initiate the OIDC flow itself.”
For Plume specifically: If Plume is using Stalwart’s own /.well-known/openid-configuration to kick off an authorization flow, it will always land on Stalwart’s login page (which accepts the credentials valid for the configured directory, including OIDC-backed accounts). Whether Plume can then use OAUTHBEARER with a token obtained from Authentik depends on whether Plume supports that mechanism with a third-party token.
Practical workaround: If Plume (or any client) does not support OAUTHBEARER with third-party tokens, the standard workaround is to use App Passwords, as described in the OAuth Interoperability docs.
Relevant documentation:
This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.
I believe this might be the correct answer, but the question remains - how is the client supposed to be aware of the OIDC setup? A client does discovery via /.well-known/openid-configuration and is directed to Stalwart’s own OAuth. Shouldn’t it be directed to the configured external directory instead?
I will still leave this up for someone to check out.