Issue Description
Upgrading only the Stalwart binary from 0.16.16 to 0.16.17 causes valid externally issued OIDC bearer tokens to be rejected by the JMAP session endpoint.
The deployment uses Authentik 2026.5.6 as an external OIDC directory, Bulwark as the JMAP webmail client, and Caddy as the reverse proxy. The Stalwart configuration, database, OIDC provider, reverse-proxy configuration, and Bulwark configuration remained unchanged during testing.
This was reproduced as a controlled version comparison:
- Stalwart 0.16.13: SSO works
- Stalwart 0.16.16: SSO works
- Stalwart 0.16.17: SSO fails
- Rolling back from 0.16.17 to 0.16.16 immediately restores SSO
The failure occurred with both Bulwark 1.7.8 and 1.8.1. It was also reproduced from multiple independent clients, including a phone and a work laptop that had never previously accessed this webmail deployment. This rules out stale browser cookies or cached application state as the likely cause.
Expected Behavior
After Authentik successfully completes the authorization-code and token exchange, Stalwart should validate the resulting bearer token through the configured external OIDC directory and return an authenticated JMAP session.
This behavior should remain unchanged when upgrading from Stalwart 0.16.16 to 0.16.17 with the same configuration and externally issued token.
Actual Behavior
With Stalwart 0.16.17, Authentik authentication and token issuance complete successfully, but Stalwart returns HTTP 401 when Bulwark requests /jmap/session using the issued bearer token.
Caddy confirms that the request reaches the Stalwart upstream. An unauthenticated request to /jmap/session returns the expected anonymous JMAP session with HTTP 200, confirming that the endpoint and reverse-proxy route are operational.
Stalwart emits no warning-level journal entry explaining the rejected token.
Replacing only the 0.16.17 binary with 0.16.16 and restarting the service immediately restores authentication. Installing 0.16.17 again reproduces the failure.
Reproduction Steps
- Configure Stalwart to use an Authentik external OIDC directory for authentication.
- Run Stalwart 0.16.16 with Bulwark 1.8.1.
- Authenticate to Bulwark through Authentik.
- Confirm that Stalwart accepts the bearer token and returns an authenticated JMAP session.
- Replace only the Stalwart binary with version 0.16.17.
- Restart the Stalwart systemd service.
- Repeat authentication from a private browser window or a previously unused client.
- Observe that Authentik completes authentication and token issuance successfully.
- Observe that the subsequent
/jmap/sessionrequest returns HTTP 401. - Restore the 0.16.16 binary and restart Stalwart.
- Repeat the same authentication flow and observe that it works immediately.
The same 0.16.17 failure was also reproduced with Bulwark 1.7.8.
Relevant Log Output
Caddy access-log results for /jmap/session during a failed Stalwart 0.16.17 authentication attempt:
{"timestamp":1786477446.9052193,"status":204,"authorization":null}
{"timestamp":1786477447.420156,"status":401,"authorization":[]}
{"timestamp":1786477448.154787,"status":401,"authorization":[]}
The first entry is the unauthenticated preflight request. The following requests contain a redacted Authorization header and are rejected with HTTP 401.
Authentik recorded successful token requests from the Bulwark Node client during the authentication flow:
POST /application/o/token/ -> 200
auth_via=oauth_client_secret
user_agent=node
Direct unauthenticated JMAP session test:
GET /jmap/session -> 200
username=""
accounts={}
Stalwart warning-level journal output immediately after a failed attempt:
-- No entries --
Stalwart Version
v0.16.x
Installation Method
Binary (Linux)
Database Backend
RocksDB
Blob Storage
RocksDB
Search Engine
Internal
Directory Backend
OIDC
Additional Context
Environment:
- Operating system: Ubuntu Linux x86_64
- Installation: Native Linux binary managed by systemd
- Affected Stalwart version: 0.16.17
- Last verified working version: 0.16.16
- Also verified working: 0.16.13
- OIDC provider: Authentik 2026.5.6
- JMAP client: Bulwark 1.7.8 and 1.8.1
- Reverse proxy: Caddy
OIDC discovery succeeds from inside the Bulwark container. The discovered issuer, authorization endpoint, and token endpoint are reachable, and the token endpoint returns HTTP 200 during the real login flow.
A source comparison suggests a possible regression boundary in the dependency update that changed jsonwebtoken from 10.x using rust_crypto to 11.0.0 using aws_lc_rs:
The relevant external OIDC validation source appears otherwise substantially unchanged between 0.16.16 and 0.16.17. This dependency change is only a suspected regression boundary, not a confirmed root cause.
I cannot leave 0.16.17 running on the production mail server because it disables SSO. I retained the affected binary and can temporarily reproduce the issue with specific trace settings if the maintainers identify the relevant logging targets.
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
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
on