Repository navigation
feat(mail): document generic OIDC/XOAUTH2 integration - #16017
ChristophWurst wants to merge 1 commit into
Conversation
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>
|
cc @LeahAuroraV for review |
📖 Documentation Preview📄 2 changed documentation pagesLast updated: Thu, 05 Nov 2026 15:21:29 GMT |
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
left a comment
There was a problem hiding this comment.
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.
| by default), and make sure the access tokens it issues are accepted by your IMAP/SMTP server | ||
| for XOAUTH2. |
There was a problem hiding this comment.
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.
| 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``. |
There was a problem hiding this comment.
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.
| - **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. |
| .. note:: Matching is by email domain, case-insensitive but otherwise exact. There can only | ||
| be one provider per domain. |
There was a problem hiding this comment.
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.
| .. 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. |
| 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. |
There was a problem hiding this comment.
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.
| 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. |
|
Oops, wrong account, but that review came from me. |
Summary
Not in draft since the feature has already merged to
mainin nextcloud/mail.🤖 AI (if applicable)