Review: Bug: Keycloak issuer mismatch blocks login via auth.palinks.app

review-1572-2026-06-23 Review

review needs-refinement

Verdict: NEEDS_REFINEMENT

Template Completeness

  • [x] Type -- Bug
  • [x] Lineage -- Standalone, discovered during session
  • [x] Repo -- ldraney/landscaping-assistant
  • [x] What Broke -- Issuer mismatch error with log evidence and code reference
  • [x] Repro Steps -- Clear 5-step repro
  • [x] Expected Behavior -- present
  • [x] Environment -- Cluster, pod env vars, Keycloak discovery issuer all documented
  • [x] Acceptance Criteria -- 4 criteria, testable
  • [x] Related -- file paths and docs referenced
All required sections for a Bug template are present and well-filled.

Traceability

  • [x] story:custom-domain label -- verified: "custom-domain" entry exists in project-landscaping-assistant user-stories section. Summary: "Access app via landscaping-assistant.app instead of Tailscale hostname."
  • [x] story note verified -- found in project-landscaping-assistant user-stories table
  • [ ] arch:rails-app label -- no matching arch note found in pal-e-docs (search for "arch-rails-app" returned empty). [SCOPE] Create architecture note arch-rails-app for the Rails application component.
  • [x] Forgejo issue -- ldraney/landscaping-assistant#259, open

File Targets

  • [x] config/initializers/omniauth.rb (line 20) -- verified: line 20 contains issuer: keycloak_configured ? "#{ENV["KEYCLOAK_URL"]}/realms/#{ENV["KEYCLOAK_REALM"]}" : "https://keycloak.test/realms/test". This is exactly where the mismatch originates.
  • [x] docs/auth-strategy.md -- verified: exists, documents Auth Code + PKCE architecture
  • [x] docs/keycloak-setup.md -- verified: exists, documents realm/client config. Notes KEYCLOAK_URL as https://keycloak.tail5b443a.ts.net (the old value before custom domain)

Repo Placement

ISSUE: The fix may not be fully contained in ldraney/landscaping-assistant. The issue states "KEYCLOAK_URL remains https://auth.palinks.app in the k8s secret (do NOT revert to Tailscale URL)." This means the fix must either:
  • Override the issuer in OmniAuth config to use a separate env var (e.g., KEYCLOAK_ISSUER_URL) pointing to the Tailscale URL, OR
  • Configure Keycloak's KC_HOSTNAME to recognize auth.palinks.app as its frontend URL -- this is a pal-e-platform/pal-e-services change.
Option (1) is a Rails-only fix in this repo. Option (2) is the proper fix but spans pal-e-platform and/or pal-e-services. The issue body does not clarify which approach to take. [BODY] Add a "Root Cause Fix" section specifying whether this is a Rails-side workaround (issuer override) or a Keycloak-side fix (KC_HOSTNAME), and if cross-repo, reference the companion issues.
Note: board item #1504 (pal-e-platform#455, type:bug, story:custom-domain) is in backlog and may be the companion Keycloak-side fix. If so, these two tickets should reference each other.

Dependencies

  • Board item #1504 (pal-e-platform#455, backlog, type:bug, story:custom-domain) -- likely the Keycloak server-side companion. If this ticket does a Rails-side workaround, #1504 may be the proper Keycloak fix. If this ticket expects a Keycloak fix, it is blocked by #1504.
  • Board item #1478 (landscaping-assistant#246, done) -- the previous OmniAuth redirect_uri fix. This ticket is a continuation of the custom-domain story.
  • Board item #1461 (landscaping-assistant#224, done) -- Rails config.hosts + Keycloak redirect URIs. Already completed, provides context.
  • Dependencies are not documented in the issue body. [BODY] Add a Dependencies section noting the relationship to pal-e-platform#455 and whether this ticket is blocked or independent.

Acceptance Criteria

The 4 criteria are testable:
  • AC1 (login via landscaping-assistant.app): verifiable by manual test or curl
  • AC2 (login via Tailscale URL): verifiable, good regression check
  • AC3 (endpoint specs pass): verifiable via bundle exec rspec
  • AC4 (KEYCLOAK_URL stays as auth.palinks.app): verifiable by inspecting k8s secret
Missing: No AC for logout working correctly. The sessions_controller.rb line 48 also uses KEYCLOAK_URL for the logout redirect URL. If the fix introduces a separate issuer URL, logout must also be verified. [BODY] Add AC: "Logout via auth.palinks.app still redirects correctly."
Missing: No AC for KeycloakAdminService. The app/services/keycloak_admin_service.rb uses KEYCLOAK_URL for admin API calls (profile updates). If a separate issuer env var is introduced, admin calls should still route through the correct URL. [BODY] Add AC: "Profile edit (KeycloakAdminService) still works via auth.palinks.app."

Blast Radius

  • KEYCLOAK_URL is referenced in 4 production files: omniauth.rb, application_controller.rb (presence check only), sessions_controller.rb (logout URL), keycloak_admin_service.rb (admin API base URL). All 4 use the same env var. If the fix splits issuer from base URL, only omniauth.rb should change -- the others should continue using the proxy URL.
  • 12+ spec files mock KEYCLOAK_URL. A new env var would need corresponding spec updates.
  • docs/keycloak-setup.md still documents KEYCLOAK_URL as https://keycloak.tail5b443a.ts.net -- this is stale now that production uses auth.palinks.app. Not in scope for this bug fix but worth noting.

Decomposition Assessment

2 file targets in 1 repo, 4 acceptance criteria. Estimated agent work under 5 minutes IF the approach is a Rails-side issuer override (add env var, update omniauth.rb, update specs). No decomposition needed for that approach. If the fix requires Keycloak-side changes (KC_HOSTNAME), that is a separate ticket in pal-e-platform -- but this ticket's scope is the Rails side only, so no decomposition needed here.

Recommendations

  • [BODY] Add a "Root Cause Fix" section specifying whether this is a Rails-side workaround (issuer override env var) or a Keycloak-side fix (KC_HOSTNAME), and if cross-repo, reference companion issues.
  • [BODY] Add a Dependencies section noting the relationship to pal-e-platform#455 and whether this ticket is blocked or independent.
  • [BODY] Add AC: "Logout via auth.palinks.app still redirects correctly."
  • [BODY] Add AC: "Profile edit (KeycloakAdminService) still works via auth.palinks.app."
  • [SCOPE] Create architecture note arch-rails-app for the Rails application component (missing from pal-e-docs).