Skip to content

feat(control-plane): single sign-on gate - #111

Merged
evdatsion merged 1 commit into
mainfrom
claude/p6-5-sso
Oct 20, 2026
Merged

evdatsion merged 1 commit into
mainfrom
claude/p6-5-sso

Conversation

@evdatsion

Copy link
Copy Markdown
Member

What this does

Gates the control-plane dashboard with single sign-on.

  • The control plane sits behind the team's SSO or OIDC front, which authenticates the person and mints a short session it hands to the dashboard. makeSsoAuthorizer verifies that session: signature against a shared secret, expiry, and an optional subject allowlist.
  • The dashboard uses the SSO authorizer when COHORT_CP_SSO_SIGNING is set, and deny-all otherwise. COHORT_CP_SSO_SUBJECTS is an optional comma-separated allowlist.
  • The session is base64url(payload).base64url(hmacSHA256(payload)) with payload { sub, exp } in epoch seconds, the shape an SSO front would mint.

Closes #69.

Security

The boundary fails closed on every path: missing, malformed, unsigned, wrong-signature, expired, or disallowed sessions are all denied, and any error during verification is a denial. The signature check uses a constant-time comparison so it does not leak via timing. The signing secret is read from the environment and is never committed and never logged, consistent with the at-rest key hygiene from #66. SSO gates only the control plane: the open-core vault, server, and CLI never call this boundary and never depend on it, so a vault keeps working with no control plane and no identity provider at all (the acceptance criterion). No open-core source changed, and the cohort-mcp enforcement test still forbids the open-core packages from importing an sso or control-plane namespace.

Tests

Seven new tests: a valid unexpired session is allowed and carries the subject; a bad signature, an expired session, a missing or malformed session, a disallowed subject, unconfigured signing material, and a payload without a subject are each denied for the right reason. Control-plane suite: 14 tests, all pass. Build, lint, audit clean; local redaction scan clean.

Gate the control plane with SSO. The control plane sits behind the team's SSO or
OIDC front, which authenticates the person and mints a short session; the
control plane verifies that session's signature against a shared secret supplied
from the environment, checks it has not expired, and checks the subject against
an optional allowlist. It fails closed on anything missing, malformed, unsigned,
expired, or disallowed, and any verification error is a denial.

The dashboard uses the SSO authorizer when the signing material is configured
and deny-all otherwise. The signing secret is read from the environment and is
never logged. The open-core vault, server, and CLI never call this boundary and
never depend on it.

Closes #69

Signed-off-by: evdatsion <31140661+evdatsion@users.noreply.github.com>
@evdatsion evdatsion added this to the Phase 6 milestone Oct 20, 2026
@evdatsion evdatsion added phase-6 Phase 6: enterprise (hold) security Security-relevant work type:feat New feature labels Oct 20, 2026
@evdatsion
evdatsion merged commit ab69690 into main Oct 20, 2026
4 checks passed
@evdatsion
evdatsion deleted the claude/p6-5-sso branch October 20, 2026 15:34
@evdatsion evdatsion mentioned this pull request Oct 20, 2026
6 tasks done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

phase-6 Phase 6: enterprise (hold) security Security-relevant work type:feat New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

P6-5 feat: SSO

1 participant