Skip to content

feat(mail): document generic OIDC/XOAUTH2 integration - #16017

Open
ChristophWurst wants to merge 1 commit into
masterfrom
docs/oidc-xoauth2-admin-user-manual
Open

ChristophWurst wants to merge 1 commit into
masterfrom
docs/oidc-xoauth2-admin-user-manual

Conversation

@ChristophWurst

Copy link
Copy Markdown
Member

Summary

  • Mail 6.0 generalises the existing Google and Microsoft XOAUTH2 integrations to any OpenID Connect provider (feat: generic OIDC/XOAUTH2 support for individual mail accounts mail#13317, merged).
  • Adds an admin-manual section ("Generic OpenID Connect (XOAUTH2) integration") mirroring the existing Google/Microsoft OAuth entries: registering an OAuth client, configuring a provider in the groupware admin settings, and how accounts connect.
  • Adds a short user-manual note on the single-sign-on add-account flow, under the existing "Add a new mail account" section (this flow was previously undocumented for Google/Microsoft too).

Not in draft since the feature has already merged to main in nextcloud/mail.

🤖 AI (if applicable)

  • The content of this PR was partly or fully generated using AI

Mail 6.0 (nextcloud/mail#13317) generalises the existing Google and
Microsoft XOAUTH2 integrations to any OpenID Connect provider. Add an
admin-manual section mirroring the existing Google/Microsoft OAuth
entries, and a short user-manual note on the single-sign-on add
account flow.

Assisted-by: ClaudeCode:claude-sonnet-5
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>
@ChristophWurst

Copy link
Copy Markdown
Member Author

cc @LeahAuroraV for review

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

📖 Documentation Preview

🔍 Open preview →

📄 2 changed documentation pages

Last updated: Thu, 05 Nov 2026 15:21:29 GMT

madbob pushed a commit to madbob/nextcloud-mail that referenced this pull request Nov 5, 2026
Admin- and user-facing docs belong in nextcloud/documentation
(nextcloud/documentation#16017), not in this repo's doc/, the same
reason doc/admin.md and doc/user.md were removed in 491f488.
doc/oidc-xoauth2.md now covers only the local test environment, same
scope as doc/developer.md.

Assisted-by: ClaudeCode:claude-sonnet-5
Signed-off-by: Christoph Wurst <1374172+ChristophWurst@users.noreply.github.com>

@Leah-BW Leah-BW left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked this against the merged code in nextcloud/mail#13317. It's accurate overall; below are one correction and a few things admins need to know, as suggestions so they can be applied directly.

Comment on lines +206 to +207
by default), and make sure the access tokens it issues are accepted by your IMAP/SMTP server
for XOAUTH2.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mail logs in with the full email address as the IMAP and SMTP username (AccountForm::applyOidcProvider() sets imapUser/smtpUser to it), so the mail server has to map the token to that login. Otherwise XOAUTH2 fails even with a valid token.

Suggested change
by default), and make sure the access tokens it issues are accepted by your IMAP/SMTP server
for XOAUTH2.
by default), and make sure the access tokens it issues are accepted by your IMAP/SMTP server
for XOAUTH2. Mail uses the full email address as the IMAP and SMTP username, so the server
must map the token to that login (for example via Dovecot's ``username_attribute``).

(optional) introspection endpoints entered manually.
- **Client ID** / **Client secret** -- the credentials of the OAuth client from step 1. The
secret is stored encrypted.
- **Scopes** -- defaults to ``openid email offline_access``.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If offline_access is missing or not granted, no refresh token is issued, and refresh() flags the account as soon as the access token expires.

Suggested change
- **Scopes** -- defaults to ``openid email offline_access``.
- **Scopes** -- defaults to ``openid email offline_access``. Without ``offline_access`` no
refresh token is issued, and users have to reconnect every time the access token expires.

Comment on lines +224 to +225
.. note:: Matching is by email domain, case-insensitive but otherwise exact. There can only
be one provider per domain.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes to a provider don't reach accounts that already exist. The server settings are only copied in when the account is created, and refresh looks up the provider by domain, so deleting a provider or changing its domain leaves connected accounts unable to refresh. The only sign of this is a warning in the server log.

Suggested change
.. note:: Matching is by email domain, case-insensitive but otherwise exact. There can only
be one provider per domain.
.. note:: Matching is by email domain, case-insensitive but otherwise exact. There can only
be one provider per domain.
.. warning:: The IMAP and SMTP settings are copied into an account when it is created, so
later changes to a provider do not affect existing accounts. Deleting a provider or changing
its email domain stops token refresh for accounts that are already connected.

Comment on lines +233 to +235
Refresh tokens keep the account syncing in the background. If a refresh token is revoked or
expires without being renewed, the affected account is flagged and the user is asked to
reconnect through the same consent popup the next time they open Mail.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This says more than the code does. In OidcIntegration::refresh(), a rejected refresh only flags the account if token introspection confirms the token is inactive. Other cases that flag it: no refresh token was ever issued, or the stored one can't be decrypted. Without an introspection endpoint (manual mode with the field empty, or a discovery document without introspection_endpoint), the failure is treated as temporary and the account is never flagged. Admins need this to decide whether to set the optional introspection endpoint.

Suggested change
Refresh tokens keep the account syncing in the background. If a refresh token is revoked or
expires without being renewed, the affected account is flagged and the user is asked to
reconnect through the same consent popup the next time they open Mail.
Refresh tokens keep the account syncing in the background. If a refresh is rejected, Mail asks
the identity provider via token introspection (RFC 7662) whether the token is still active.
Only when the provider confirms it is inactive is the account flagged, and the user is asked to
reconnect through the same consent popup the next time they open Mail. Without an introspection
endpoint, a failed refresh is always treated as a temporary error.

@LeahAuroraV

Copy link
Copy Markdown

Oops, wrong account, but that review came from me.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants