OIDC as a Directory; getting 'NetworkError when attempting to fetch resource.' / 'Failed to fetch'

Issue Description

When I input my username / email, I’m forwarded to my identity provider (Keycloak), I sign in (despite already being validated earlier which defeats the purpose of SSO, I think).

Expected Behavior

It would redirect me and log me in

Actual Behavior

It takes me back to my mail server and it says, ‘NetworkError when attempting to fetch resource.’ on Firefox, ‘Failed to fetch’ on Google Chrome.

Stalwart Version

v0.16.x

Installation Method

Binary (Linux)

Database Backend

RocksDB

Blob Storage

RocksDB

Search Engine

Internal

Directory Backend

OIDC

Additional Context

I thought it could be CORS related but I’m not sure.

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

That error is coming from the browser, not from Stalwart, which is why there is nothing in your server log. With an OIDC directory the discovery call hands the browser Keycloak’s own endpoints, so the code-for-token exchange is a direct cross-origin POST from the admin UI to Keycloak’s token endpoint. A “NetworkError” or “Failed to fetch” there means the browser blocked or could not make that request; an actual OAuth failure would come back as a token exchange error with a status code instead.

The usual cause is CORS on the Keycloak side, since a new client’s Web Origins is empty by default. Add your Stalwart origin there (or +). While you are in that client, it also needs to be public with client authentication off, PKCE set to S256, https://yourhost/oauth/callback as a valid redirect URI, and the client id stalwart-webui. The other cause with an identical message is the browser simply not being able to reach the issuer host, so split DNS or an untrusted certificate on Keycloak. The Network tab in devtools tells the two apart at a glance: a CORS block looks quite different from a failed connection.

Being prompted to sign in again despite an active session is expected today, the login flow always sends prompt=login. One thing to watch once the exchange succeeds: the audience requirement defaults to stalwart, so the Keycloak client needs an audience mapper emitting that value, or the field changed to match what your tokens carry.

First off, thank you for the information, I appreciate it a lot; I got it working after a little bit of tinkering. Some weird behavior on our Keycloak side (maybe not weird behavior but I at least don’t understand it).

Secondly, is it possible to configure Stalwart to not send prompt=login. I don’t wanna have users log in again if they’ve already logged in because at that point, it would just be better to configure LDAP instead. Feels redundant.

And I apologize for not responding sooner.

Glad it’s working. On the prompt: no, not today. The prompt=login is hardcoded into the authorization request the web UI builds, so it isn’t a server setting and there’s nothing you can change on the Stalwart side to suppress it; the request is assembled in the browser before it ever reaches us.

Okay thank you for letting me know. Appreciate the help!