OIDC is not used by Stalwart if there is a provider outage

Issue Description

If Stalwart starts up before OIDC was available or if there was ever an OIDC outage and the discovery failed, Stalwart falls back to using its internal username+password authentication. This is not a behavior I think anyone would want, especially that it never reattempts OIDC discovery until server reload or restart even after the OIDC server is online again.

Stalwart Version

v0.16.x

Installation Method

NixOS

Database Backend

RocksDB

Blob Storage

RocksDB

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

This matches what the code actually does. The OIDC directory is built once, at startup or on a config reload, by fetching the provider’s /.well-known/openid-configuration discovery document (see OpenIdDirectory::new/open in crates/directory/src/backend/oidc/config.rs). If that fetch fails, the directory object is never inserted into the running directory map, it’s only recorded as a build error.

Downstream, Server::route_auth_request (crates/common/src/auth/authentication.rs) looks up the directory for the domain via get_directory_for_cached_domain. If no directory is registered for that domain (because OIDC failed to initialize), it falls through to the branch that checks the account’s own stored password credential instead of returning an authentication error. There is no background retry of discovery; the only paths that re-attempt it are a server restart or a configuration reload, which is exactly what you’re observing.

The OIDC documentation currently only describes the intended discovery/validation flow and doesn’t document this failure mode, so this behavior isn’t something you’re missing in configuration, it’s how the directory initialization currently works. See OpenID Connect backend docs for the documented flow, which does not mention outage handling.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

Fixed in v0.16.22 (yet to be released).

Hi, my problem is, that my Raspberry Pi 5 (with NVMe SSD) needs about a minute to start the keycloak container so when I start the Pi or update my containers most of the time I run into an error because the 30 Seconds are to low to check the directory object.

Is it possible to add a value where I can extend this limit to 90 or 120 Seconds?

Best regards, Johann

You can configure Docker to start the Stalwart container after the Keycloak one is ready.

You can add an ExecStartPre health check to your Stalwart systemd unit (stalwart.service):

# Check every 5 seconds, 6 attempts total (30 seconds timeout)
ExecStartPre=/bin/sh -c 'URL="http://127.0.0.1:1411/.well-known/openid-configuration"; for i in $(seq 1 6); do if curl -sI "$URL" | grep -q "200 OK"; then echo "Pocket-ID is ready! Starting Stalwart..."; exit 0; fi; echo "Waiting for Pocket-ID at $URL (attempt $i/6)..."; sleep 5; done; echo "WARNING: Pocket-ID failed to start within 30s. Starting Stalwart anyway..."; exit 0'