Skip to content

Add the DTT SSO provider - #3

Merged
alexrunsk merged 1 commit into
masterfrom
dtt-sso-provider
Oct 1, 2026
Merged

alexrunsk merged 1 commit into
masterfrom
dtt-sso-provider

Conversation

@alexrunsk

Copy link
Copy Markdown

Adds a dtt-sso provider so oauth2-proxy can protect internal tools with our SSO (auth-server). Stacked on #2.

Upstream's generic oidc provider cannot be used: the SSO signs id_tokens with HS256 keyed on the client secret and publishes no JWKS, while upstream verifies only asymmetric keys.

How it works

  • Authorization code flow with scope=openid, the only scope the SSO accepts. Endpoints default to https://auth.thebestagent.pro; --login-url, --redeem-url and --validate-url point it elsewhere (e.g. stage).
  • Client credentials go to /oauth/token as unescaped HTTP Basic. The SSO compares them byte for byte, and golang.org/x/oauth2 URL-escapes them, which breaks base64 secrets.
  • The id_token is verified with golang-jwt: HS256 only, signature against the client secret, issuer = the login URL's origin, audience = client id, expiry. go-jose is not used because it rejects HMAC keys under 32 bytes, and SSO secrets can be shorter.
  • The session carries the email, the user UUID as the user, and the SSO role as the only group, so --allowed-group=dtt_admin restricts by role.
  • RefreshSession uses the refresh token and re-reads email and role; ValidateSession calls /oauth/check_token. With --cookie-refresh, a user deleted or signed out in the SSO loses access at the next refresh.

Each instance needs its own SSO client (one redirect URI per client) and its own --cookie-name, since the Atlassian proxy sets _oauth2_proxy on .thebestagent.pro. Docs: docs/docs/configuration/providers/dtt_sso.md.

Verified

  • 7 tests against a mock SSO, including tampered, unsigned and expired id_tokens and a secret shorter than 32 bytes; the full suite passes.
  • Live against the stage SSO (sso-master.dtt.stage.thebestagent.pro): sign-in, id_token verification, dtt_admin as a group, check_token, and a token refresh.

Merge with a merge commit, after #2.

🤖 Generated with Claude Code

Signs users in with the DTT SSO (auth-server) via the authorization code
flow with scope=openid:

- the token endpoint gets the client credentials as unescaped HTTP Basic,
  which the SSO compares byte for byte (golang.org/x/oauth2 escapes them)
- the HS256 id_token is verified with the client secret via golang-jwt;
  go-jose rejects HMAC keys under 32 bytes, and SSO secrets can be shorter
- the session carries the email, the user UUID as the user, and the role
  as the only group, so allowed_groups can restrict by role
- RefreshSession uses the refresh token and re-reads email and role;
  ValidateSession calls /oauth/check_token

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@alexrunsk
alexrunsk changed the base branch from upgrade-v7.15.4 to master October 1, 2026 08:56
@alexrunsk
alexrunsk merged commit 20d4e9c into master Oct 1, 2026
5 checks passed
@alexrunsk
alexrunsk deleted the dtt-sso-provider branch October 1, 2026 09:10
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.

1 participant