Skip to content

Phase 2b: OIDC client registration at app install + {{ oidc.* }} template vars#149

Open
ClaydeCode wants to merge 1 commit into
feature/oidc-phase2a-providerfrom
feature/oidc-phase2b-install
Open

Phase 2b: OIDC client registration at app install + {{ oidc.* }} template vars#149
ClaydeCode wants to merge 1 commit into
feature/oidc-phase2a-providerfrom
feature/oidc-phase2b-install

Conversation

@ClaydeCode

Copy link
Copy Markdown
Contributor

Phase 2b of the multi-user identity rollout: apps get OIDC credentials automatically at install. Stacked on the phase-2a provider PR.

What this does

  • app_meta.json gains an optional oidc section (redirect_uris — may reference {{ portal.domain }} —, public_client, scope).
  • Client registration happens inside compose-template rendering: render_docker_compose_template registers/refreshes the app's OIDC client and passes {{ oidc.client_id }}, {{ oidc.client_secret }}, {{ oidc.issuer }} to the template. Because rendering runs at install, reinstall AND every startup, redirect URIs heal automatically (e.g. after a domain change) — no extra hook needed.
  • Credentials are stable: the upsert preserves client_id/client_secret on conflict, so reinstalls and re-renders never invalidate an app's configured client.
  • Uninstall removes the client row, cascading the app's codes and tokens.

Apps without an oidc section are untouched (oidc=None in the template context).

Companion PR

app-repository: paperless-ngx catalog entry using this mechanism (allauth openid_connect via env, auto-signup, SSO redirect) — the admin-vs-daily-account request from freeshard#141. Ships app-by-app; more apps follow independently. Immich needs its config-file/API mechanism and is deliberately not in this pass.

Tests

Three integration tests over the real install worker + Docker using a new oidc_app in the mock store: install registers the client with domain-rendered redirect URIs and renders creds into the compose file; reinstall keeps credentials; uninstall removes the client.

Recommended reading order

  1. shard_core/data_model/app_meta.pyOidcMeta
  2. shard_core/database/oidc.py — upsert preserves creds; get/remove by app_name
  3. shard_core/service/oidc_provider.pyensure_app_client(), issuer_for_domain()
  4. shard_core/service/app_installation/util.py — render hook
  5. shard_core/service/app_installation/worker.py — uninstall cleanup
  6. tests/mock_app_store/oidc_app/*, tests/test_oidc_app_install.py

🤖 Generated with Claude Code

Test status

New install tests 3/3 green; regression run over test_app_installation.py + test_oidc.py + test_users.py: 29 passed, 0 failed.

…} template vars

app_meta.json gains an optional oidc section (redirect_uris — may reference
{{ portal.domain }} —, public_client, scope). Compose-template rendering
registers/refreshes the app's OIDC client and passes oidc.client_id,
oidc.client_secret and oidc.issuer into the template. Registration lives in
the render step because rendering runs at install, reinstall and every
startup — redirect URIs heal automatically after a domain change with no
extra hook.

The client upsert preserves client_id/client_secret on conflict so
reinstalls and re-renders never invalidate an app's configured credentials.
Uninstalling an app removes its client row, cascading its codes and tokens.

Apps without an oidc section are unaffected (oidc=None in the context).

Phase 2b of the multi-user identity rollout; companion app-repository PR
adds the first catalog app (paperless-ngx) on this mechanism.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ClaydeCode
ClaydeCode force-pushed the feature/oidc-phase2a-provider branch from be5293b to ba1ea67 Compare July 27, 2026 11:14
@ClaydeCode
ClaydeCode force-pushed the feature/oidc-phase2b-install branch from b87d350 to 262ad43 Compare July 27, 2026 11:14
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