Skip to content

(feat) Add bearer-token auth mode and optional session URL rewriting (for use with other JMAP providers like Fastmail) - #750

Open
mdbraber wants to merge 1 commit into
bulwarkmail:mainfrom
mdbraber:fastmail-token-auth
Open

(feat) Add bearer-token auth mode and optional session URL rewriting (for use with other JMAP providers like Fastmail)#750
mdbraber wants to merge 1 commit into
bulwarkmail:mainfrom
mdbraber:fastmail-token-auth

Conversation

@mdbraber

@mdbraber mdbraber commented Aug 6, 2026

Copy link
Copy Markdown

Summary

My goals was to be able to connect to Fastmail as the JMAP backend. Unfortunately Fastmail does not (yet) support OAuth applications for individual users. But it does support long-lived API access tokens in the Bearer. As that infrastructure already exists in Bulwark the idea is to use the API token as password to login.

Changes

Two build-time flags, both inert unless set, so upstream behaviour is unchanged by default.

  • NEXT_PUBLIC_JMAP_AUTH_MODE=bearer sends the login form's password field as Authorization: Bearer <token> instead of Basic. Needed for hosted JMAP providers that only accept bearer tokens — Fastmail answers Basic with 401 and WWW-Authenticate: Bearer regardless of credentials, so its API tokens cannot be used at all otherwise. JMAPClient.withBearer already existed; it was just unreachable without an OAuth or TOTP exchange. No onTokenRefresh is passed, which is correct for a static token: a 401 surfaces as an auth error rather than a refresh attempt.

  • NEXT_PUBLIC_JMAP_REWRITE_SESSION_URLS=false disables rewriteSessionUrl. That rewrite forces every URL in the JMAP session resource onto JMAP_SERVER_URL's origin, which is right for Stalwart behind a reverse proxy advertising an internal hostname, but wrong for providers that serve blobs from a separate origin by design — Fastmail returns downloadUrl on www.fastmailusercontent.com, and rewriting it to api.fastmail.com breaks every attachment.

Related issues

See this discussion: https://github.com/orgs/bulwarkmail/discussions/596

Type of change

  • New feature (non-breaking change that adds functionality)

Checklist

  • I have read the Contributing Guide
  • My code follows the project's code style and conventions
  • I have run npm run typecheck && npm run lint and there are no errors
  • The build passes (npm run build)
  • I have tested my changes locally
  • I have added or updated documentation if needed
  • I have updated translations (locales/) if my changes affect user-facing text
  • I have included screenshots or a screen recording for UI changes

Notes for reviewers

This is mostly meant as a POC right now because using API keys as Bearer tokens would not be a preferred long-term solution. What it does allow is for (advanced) users to participate in using / developing Bulwark while (re)using the Fastmail infrastructure. As this is config only it could be considered a safe-enough option for users who understand what they're doing.

Two build-time flags, both inert unless set, so upstream behaviour is
unchanged by default.

NEXT_PUBLIC_JMAP_AUTH_MODE=bearer sends the login form's password field
as `Authorization: Bearer <token>` instead of Basic. Needed for hosted
JMAP providers that only accept bearer tokens — Fastmail answers Basic
with 401 and `WWW-Authenticate: Bearer` regardless of credentials, so
its API tokens cannot be used at all otherwise. JMAPClient.withBearer
already existed; it was just unreachable without an OAuth or TOTP
exchange. No onTokenRefresh is passed, which is correct for a static
token: a 401 surfaces as an auth error rather than a refresh attempt.

NEXT_PUBLIC_JMAP_REWRITE_SESSION_URLS=false disables rewriteSessionUrl.
That rewrite forces every URL in the JMAP session resource onto
JMAP_SERVER_URL's origin, which is right for Stalwart behind a reverse
proxy advertising an internal hostname, but wrong for providers that
serve blobs from a separate origin by design — Fastmail returns
downloadUrl on www.fastmailusercontent.com, and rewriting it to
api.fastmail.com breaks every attachment.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant