Skip to content

fix: Preserve OIDC params across SAML session regeneration#631

Merged
H2CK merged 4 commits into
H2CK:masterfrom
abraxaswd:fix/preserve-oidc-params-across-saml-login
Mar 27, 2026
Merged

fix: Preserve OIDC params across SAML session regeneration#631
H2CK merged 4 commits into
H2CK:masterfrom
abraxaswd:fix/preserve-oidc-params-across-saml-login

Conversation

@abraxaswd
Copy link
Copy Markdown
Contributor

@abraxaswd abraxaswd commented Mar 24, 2026

Summary

  • Fixes OIDC authorization failure when users authenticate via a SAML backend
  • OIDC parameters (client_id, state, redirect_uri, etc.) are lost when SAML login regenerates the PHP session
  • Parameters are now passed via URL query params instead of relying solely on session storage
  • Session fallback is kept for backwards compatibility with non-SAML login flows

Problem

When Nextcloud acts as OIDC Identity Provider and authenticates users via SAML:

  1. authorize() stores OIDC params in session, redirects to login
  2. SAML handles login → session is regenerated (security measure against session fixation)
  3. PageController::index() reads null from session
  4. Redirect.vue redirects to /apps/oidc/authorize without parameters
  5. ClientMapper::getByIdentifier() throws: Argument #1 must be of type string, null given

Second login attempt always works because the SAML session is already established.

Solution

Pass OIDC authorization parameters as URL query parameters through the redirect chain, so they survive session regeneration. This does not weaken session fixation protection — the session is still regenerated, we just avoid storing routing data in it.

Files changed:

  • LoginRedirectorController.php — Include params in linkToRoute() call
  • PageController.php — Read from request first, fall back to session
  • templates/main.php — Pass params as data-* attributes on the DOM element
  • Redirect.vue — Read data-* attributes and append to authorize URL

Test plan

  • Test OIDC login with SAML backend — should succeed on first attempt
  • Test OIDC login with direct Nextcloud credentials — should still work (session fallback)
  • Test OIDC login with PKCE (code_challenge) — parameters must be preserved
  • Verify consent flow still works correctly

Fixes #628

…eration

When a user authenticates via a SAML backend, Nextcloud regenerates the
PHP session (as protection against session fixation attacks). This
destroys the OIDC authorization parameters (client_id, state,
redirect_uri, etc.) that were stored in the session before the login
redirect.

After SAML login, PageController::index() reads null values and
Redirect.vue redirects to /apps/oidc/authorize without parameters,
causing: ClientMapper::getByIdentifier(): Argument H2CK#1 must be of type
string, null given.

Fix: Pass all OIDC parameters as URL query parameters in the
redirect_url so they survive session regeneration. The session fallback
is kept for backwards compatibility with non-SAML login flows.

Changes:
- LoginRedirectorController: Include params in linkToRoute() call
- PageController: Read from request first, fall back to session
- templates/main.php: Pass params as data-* attributes on the DOM
- Redirect.vue: Read data-* attributes and append to authorize URL

Fixes H2CK#628
Copy link
Copy Markdown
Owner

@H2CK H2CK left a comment

Choose a reason for hiding this comment

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

Please update the code according to the requested changes per file.

Comment thread lib/Controller/LoginRedirectorController.php Outdated
Comment thread lib/Controller/PageController.php
- Wrap URL parameters in array_filter() to omit null values
- Use all-or-nothing approach for URL vs session parameters in
  PageController to avoid mixing data from different sources

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Owner

@H2CK H2CK left a comment

Choose a reason for hiding this comment

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

Changes are ok for me. How about the open tasks in the test plan, e.g. PKCE? Are you able to test it?
The last task about consent flow will fail (according to my tests). Necessary changes are already described in #630 in
https://github.com/H2CK/oidc/pull/630/changes#diff-fbdcb468be0d9575dfd4c1dd9f35ebd94c74a355dc7807e6927374b947866148
I included those changes with this PR, then it worked.

Copy link
Copy Markdown
Owner

@H2CK H2CK left a comment

Choose a reason for hiding this comment

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

Revert the code LoginRedirectController from line 226 on. Otherwise previous bugs will be opened up again.

Comment thread lib/Controller/LoginRedirectorController.php Outdated
  Revert the granular per-parameter fallback and guard clause as requested
  in review — these changes reintroduced previously fixed bugs.
  The original session fallback (triggered only when client_id is empty)
  is restored.

  All scenarios tested successfully:
  - SAML backend login (first attempt, no retry needed)
  - Direct Nextcloud login
  - PKCE flow (code_challenge preserved across SAML redirect)
  - Consent flow (ConsentController now passes all params via URL)
Copy link
Copy Markdown
Owner

@H2CK H2CK left a comment

Choose a reason for hiding this comment

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

The changes are ok for me.

@H2CK H2CK merged commit b25718b into H2CK:master Mar 27, 2026
3 checks passed
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.

OIDC parameters lost during SAML session regeneration

2 participants