Skip to content

docs: document six openid-connect config keys the app supports - #41846

Merged
phil-davis merged 1 commit into
masterfrom
docs/oidc-config-sample-keys
Sep 22, 2026
Merged

phil-davis merged 1 commit into
masterfrom
docs/oidc-config-sample-keys

Conversation

@oc-tmueller

Copy link
Copy Markdown
Contributor

The admin manual's OIDC parameter reference is generated from this file by owncloud/config-to-docs, so a key that is missing here is missing from the documentation — and a key documented only in the docs repo is deleted by the next regeneration. Six keys the openidconnect app reads were missing:

key read at note
audience lib/Client.php new; app 2.4.2 on this line, see owncloud/openidconnect#374
exchange-token-mode-before-introspection lib/Client.php RFC 8693 exchange before introspection
use-access-token-introspection-for-user-info lib/Client.php user info from the introspection response
ocis-routing-policy-claim lib/Controller/LoginFlowController.php default ocis.routing.policy
ocis-routing-policy-cookie same default owncloud-selector
ocis-routing-policy-cookie-directives same default path=/;

Every auto-provision subkey is already covered by the code samples further down (enabled, email-claim, display-name-claim, picture-claim, groups, provisioning-claim, provisioning-attribute, update), and the provider-params discovery endpoints likewise — so this adds top-level keys only, in the existing alphabetical order and comment style.

Why the audience entry is long

It is the one key here whose misconfiguration locks every user out, and the release history needs saying: the audience check shipped in app version 2.4.1 requiring the client-id in aud with no override, so a provider that names the resource there — Keycloak, ADFS, Entra ID issuing v1.0 tokens — could not authenticate at all with JWT access tokens. 2.4.2 adds this key plus acceptance of azp/appid/client_id. The entry says which is which, because an admin reading it may be on either.

Details checked against the app code rather than assumed

  • 'audience' => null behaves as if the key were absent (isset()), while any other unusable value is dropped and fails closed. The entry distinguishes them; they are not equivalent.
  • 2.4.1 does not check the audience of an opaque token verified through an introspection endpoint — its single verifyAudience() call sits in the JWT branch — so the lockout claim is scoped to JWT access tokens. 2.4.2 checks both paths.
  • The token exchange takes its subject from the OIDC login session while a session is verified, and from the client's current token when user information is read; with no session it fails on an empty subject rather than being skipped.
  • Setting audience also keeps ID tokens out, but only where the value differs from the client-id, since an ID token's aud is the client-id.
  • use-access-token-payload-for-user-info gains one clause: its "if false, the userinfo endpoint is used" is no longer the whole story once the introspection variant is documented, and it wins only for a JWT — an opaque token has no payload to read.

Two things a reviewer might flag

  • The + lines inside the audience entry are AsciiDoc paragraph continuations. They are required because this file's comments are published verbatim; no other entry needs them because no other entry runs to several paragraphs.
  • The doc link is version-explicit (/server/11.0/…) rather than this file's usual /server/latest/. latest cannot carry a deep link into a version-scoped section: it resolves to a 673-byte stub that redirects to the newest line without the fragment, and for the 10.16 counterpart it would send the reader into the wrong manual entirely. The trade-off is that this URL will point at the 11.0 manual once master becomes 11.1.

Testing

No syntax errors detected in config/config.apps.sample.php     # php 8.3

Comment-only change, no code paths touched. Verified end to end that the generator reproduces the manual page from this file: before the change, running config-to-docs against origin/master produced the committed page byte-identically (zero drift), and after it the diff is exactly these entries. owncloud/docs.owncloud.com#137 carries that regenerated output. No changelog entry, following the other docs: commits to this file.

🤖 Generated with Claude Code

The admin manual's parameter reference is generated from this file by
owncloud/config-to-docs, so a key missing here is missing from the documentation -
and a key documented only in the docs repo is deleted by the next regeneration.
These six the openidconnect app reads and this file did not mention:

- audience - the expected access token audience. Available from app version 2.4.2;
  the audience check itself shipped in 2.4.1, where the client-id had to appear in
  "aud" with no way to override it, which is why providers that name the resource
  there - Keycloak, ADFS, Entra ID with v1.0 tokens - could not authenticate with
  JWT access tokens on that version. See owncloud/openidconnect#373 and #374.
- exchange-token-mode-before-introspection - RFC 8693 token exchange before
  introspection, with the value selecting the subject token type (lib/Client.php).
- use-access-token-introspection-for-user-info - read user information from the
  introspection response rather than the userinfo endpoint (lib/Client.php).
- ocis-routing-policy-claim, ocis-routing-policy-cookie and
  ocis-routing-policy-cookie-directives - the claim, cookie name and cookie
  directives used to route users between Classic and Infinite Scale behind a proxy
  (lib/Controller/LoginFlowController.php). Defaults as in the code:
  ocis.routing.policy, owncloud-selector and "path=/;".

Every auto-provision subkey is already covered by the code samples further down, so
this only adds top-level keys, in the existing alphabetical order and style.

Two details the app's behaviour makes worth stating, both checked against the code
rather than assumed: 'audience' => null behaves as if the key were absent (isset()),
while any other unusable value is dropped and fails closed; and the exchange
subject comes from the login session while a session is verified but is the
presented token when user information is read, which is why the entry distinguishes
the two paths. The use-access-token-payload-for-user-info entry gains one clause,
because its "if false, the userinfo endpoint is used" is no longer the whole story
once the introspection variant is documented.

The doc link is version-explicit rather than following this file's /server/latest/
convention: latest is a redirect stub that drops the URL fragment and always points
at the newest server line, so a deep link into a version-scoped section needs the
real path.A second review round tightened three things further: the ID-token consequence of
setting the key holds only where the configured value differs from the client-id, so
it is stated conditionally rather than flat; a missing OIDC session makes the token
exchange fail with an empty subject rather than skipping it, and on the user-info path
the subject is the client's current token; and the sentence explaining that an ADFS
relying-party identifier is often the same GUID as the client-id but is not the client
is restored, since misreading exactly that produced issue owncloud/openidconnect#373.

Note for reviewers: the "+" lines inside the audience entry are AsciiDoc paragraph
continuations, required because this file's comments are published verbatim as the
manual's parameter reference. No other entry needs them because no other entry runs
to several paragraphs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Müller <323649642+oc-tmueller@users.noreply.github.com>
@oc-tmueller

Copy link
Copy Markdown
Contributor Author

Note on the red PHP Unit (8.3, oracle:23) job: it fails in Install Server, before PHPUnit runs, with

✗ oci8 Could not install oci8 on PHP 8.3.33

so the oci8 extension did not build in the runner. Unrelated to this change, which touches only PHP comments in a config sample:

A re-run should clear it.

@phil-davis
phil-davis merged commit afdbc44 into master Sep 22, 2026
54 of 55 checks passed
@phil-davis
phil-davis deleted the docs/oidc-config-sample-keys branch September 22, 2026 03:22
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.

2 participants