Skip to content

fix(auth): SAML endpoints refuse every request until assertions are verified (#866) - #868

Merged
alex-dembele merged 3 commits into
masterfrom
security/866-saml-fail-closed
Oct 2, 2026
Merged

alex-dembele merged 3 commits into
masterfrom
security/866-saml-fail-closed

Conversation

@alex-dembele

Copy link
Copy Markdown
Member

Closes #866

SAML sign-in is turned off until assertions are verified. POST /api/v1/auth/saml2/acs and GET /api/v1/auth/saml2/login now redirect to /login?error=provider_not_configured&provider=saml2 and create no user and no session. The login screen already explains that code in both languages. GET /api/v1/auth/saml2/metadata is unchanged.

The code that turned a posted assertion into a user, a group-mapped role and a session (provisionSAML2User, applyGroupRoleMapping, the hand-rolled assertion structs) is removed, not left unreachable. SAML should come back through a maintained library that verifies signed assertions, which needs an ADR and a dependency decision. Nothing in that code is worth keeping for the rewrite, and git history holds it.

SAML sign-in was never proven end to end (ROADMAP module 2), so no working flow is lost.

Verification

cd backend && go vet ./...            -> clean
cd backend && go test ./... -count=1  -> 79 packages ok, 0 FAIL

saml2_handler_test.go: a well-formed success response is refused, an empty POST is refused, and the login redirects even with SAML configured. Each check asserts the redirect and that no session cookie is set. Against master's handler the same tests fail, because the request reaches the database.

Interaction with #803

Both PRs touch SAML2ACS. Merged together in a scratch worktree, the one conflict is in saml2_handler.go, and the resolution is this PR's version (#803 only changed the line this PR deletes). The merged tree runs 79 ok, 0 FAIL. Whichever lands second needs that one-line resolution.

Docs

  • README: SAML2 is no longer listed among the SSO options.
  • API_COMPLETE_ENDPOINTS.md and ENDPOINTS.md now give what the two endpoints answer.
  • API_SECURITY_GUIDE.md and SAML_OAUTH2_INTEGRATION.md carry a "turned off" note.

Honest remainders

  • docs/PRICING.md (line 29) and docs/SELF_HOSTING.md (lines 119, 187) still list "SSO / SAML" in the plan tables. Pricing wording is the owner's call, so they are left as they are.
  • The SAML metadata still advertises WantAssertionsSigned="false". It is harmless while the ACS refuses everything, and it should change with the real implementation.

The SAML assertion consumer service read the email out of whatever XML
it was posted and opened a session for that account. It checked no
signature, issuer, audience, validity window or InResponseTo, and it was
mounted on every deployment whether or not SAML was configured.

SAML2ACS and SAML2InitiateLogin now redirect to
/login?error=provider_not_configured&provider=saml2, which the login
screen already explains, and create nothing. The code that turned an
assertion into a user, a group-mapped role and a session is removed
rather than left unreachable; real SAML support comes back through a
maintained library that verifies signed assertions. The metadata
endpoint is unchanged.

SAML sign-in was never proven end to end, so no working flow is lost.

Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
The README listed SAML2 among the SSO options, and the endpoint references said the ACS redirects with a token. Both now say SAML is turned off and what its endpoints answer. The pricing and self-hosting plan tables are left for the owner.

Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
@alex-dembele
alex-dembele merged commit ca8b27c into master Oct 2, 2026
12 of 25 checks passed
@alex-dembele
alex-dembele deleted the security/866-saml-fail-closed branch October 2, 2026 10:36
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.

security(auth): SAML endpoints refuse every request until assertions are verified

1 participant