Skip to content

Add Default "Access Denied" Page for SAML Users Without Backend Role #32365

Description

@DeanGonzalez

Problem Statement

When a user logs into dotCMS via SAML SSO successfully but does not have the dotcms_back_end_user role (i.e., lacks permission to access the admin UI), they are currently redirected to a blank dotCMS backend page that continuously reloads. This creates confusion and appears broken to the end user.

Steps to Reproduce

  1. Set up SAML SSO in dotCMS.
  2. Attempt to log in via SAML with a user that exists in the SSO provider but does not have the dotcms_back_end_user role.
  3. User is redirected to the backend admin page.
  4. The page remains blank and continuously refreshes.

Acceptance Criteria

Scope & staging. This issue targets a first fix stage focused on breaking the infinite redirect loop and giving the user a clear "access denied" experience with a diagnostic log line. Some criteria below may be split into follow-up stages / separate issues depending on effort — in particular anything that requires changing dotCMS's existing shared error-page infrastructure (e.g. adding a logout/sign-out link), and the larger RelayState / role-aware-landing work. Items expected to spill into later stages are marked (later stage).

Root-cause trace and rationale are in the comment thread below: front-end SAML users default to /dotAdmin/ and lose the original request due to DEFAULT_LOGIN_PATH = "/dotAdmin/" plus cross-site SameSite session loss on the IdP POST-back.

Stage 1 — break the loop + surface the denial (primary scope of this issue)

  • Once a valid SAML assertion has been consumed, an authorization failure (authenticated user lacks the role for the target — e.g. a front-end-only user hitting /dotAdmin) does not trigger a new SAML AuthnRequest; authentication is treated as terminal.
  • Such a request returns an appropriate HTTP status (403 for a backend/admin target) and renders an Access Denied page instead of a blank, continuously-reloading page.
  • A clear, identifiable log message is written identifying the denied SAML user and the missing role, sufficient to diagnose the case from logs alone. (covers the original ask)
  • A loop-termination guard ensures that if the flow would redirect to the IdP again immediately after consuming an assertion, it is detected and stopped (session marker/timestamp or bounded attempt counter), rendering the Access Denied / error page rather than looping.
  • Verified: a front-end-only user (DOTCMS_FRONT_END_USER, no backend role) authenticating against a live IdP SSO session reaches a terminal page within a bounded number of redirects — no ERR_TOO_MANY_REDIRECTS, no continuous reload.

No regressions (Stage 1)

  • A SAML user with the backend role still logs into /dotAdmin successfully, unchanged.
  • A genuinely anonymous / not-yet-authenticated user requesting a SAML-protected URL is still redirected to the IdP to log in (the legitimate REDIRECT_AFTER_LOGIN flow is preserved).
  • Existing back-end SAML SSO login (the primary current use case) is unaffected for authorized users.

Follow-up stages — may be split into separate issues

  • (later stage) The Access Denied page offers a logout / sign-out link so the user can terminate the SSO session and retry. This may require modifying dotCMS's existing shared error-page infrastructure, so it is called out as potentially separate work.
  • (later stage) The originally requested URL is carried through RelayState (round-tripped via the IdP) so the post-login redirect no longer depends on the session surviving the cross-site IdP POST-back. (Preferred robust direction — see comments.)
  • (later stage) Post-login landing is role-aware: backend-role users may land on /dotAdmin; front-end-only users land on a front-end destination (the RelayState target or a configured front-end landing) and are never defaulted into /dotAdmin/.

dotCMS Version

current

Proposed Objective

Customer Support

Proposed Priority

Priority 3 - Average

External Links... Slack Conversations, Support Tickets, Figma Designs, etc.

Assumptions & Initiation Needs

No response

Quality Assurance Notes & Workarounds

Interim workaround for front-end SSO deployments: set the IdP optional property redirect.after.login to a front-end URL, so the post-login redirect no longer defaults to /dotAdmin/.

Sub-Tasks & Estimates

No response

Metadata

Metadata

Assignees

Type

No type

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions