Skip to content

Add DeleteOIDCAuthRequest so SSO state tokens can be single-use - #3

Open
neilLasrado wants to merge 1 commit into
v18.10.0-switchonfrom
feat/oidc-slice1-delete-auth-request
Open

neilLasrado wants to merge 1 commit into
v18.10.0-switchonfrom
feat/oidc-slice1-delete-auth-request

Conversation

@neilLasrado

Copy link
Copy Markdown
Member

Slice 1 of 6 toward self-hosted Google login. Standalone and additive — nothing calls the new method yet.

Why

lib/services/local/users.go has CreateOIDCAuthRequest and GetOIDCAuthRequest but no delete, and there is no Delete*AuthRequest for any SSO type in the tree. Upstream relies on TTL expiry alone.

That is not sufficient for the OIDC implementation landing in a later slice. The state token must be single-use: looked up once, then deleted immediately. Without a delete, a captured state token stays replayable for the whole TTL window.

Change

func (s *IdentityService) DeleteOIDCAuthRequest(ctx context.Context, stateToken string) error {
	if stateToken == "" {
		return trace.BadParameter("missing parameter stateToken")
	}
	return trace.Wrap(s.Delete(ctx, backend.NewKey(webPrefix, connectorsPrefix, oidcPrefix, requestsPrefix, stateToken)))
}

Same backend key construction as the neighbouring GetOIDCAuthRequest, same error-wrapping convention as the sibling DeleteWebauthnSessionData / DeleteMFASessionData. Added to the services.Identity interface directly below GetOIDCAuthRequest.

Interface change — other implementers checked

Adding a method to services.Identity can break anything that satisfies it, so this was checked rather than assumed. local.IdentityService is the only concrete implementer. Everything else (lib/authz/permissions_test.go, lib/services/local/suite_test.go, and the healthcheckconfigv1 / delegationv1 / usersv1 service tests) holds the interface as a field populated with a *local.IdentityService at runtime, so they auto-satisfy.

lib/auth/auth_with_roles.go, lib/auth/grpcserver.go and api/client/client.go also reference GetOIDCAuthRequest, but via the unrelated authclient.ClientI gRPC interface — no type there implements services.Identity.

Tests

TestIdentityService_OIDCAuthRequestCRUD — create, get, delete, get-returns-NotFound, plus delete-of-nonexistent and empty-token BadParameter.
TestIdentityService_OIDCAuthRequestTTLExpiry — clockwork.NewFakeClock() with clock.Advance, matching the surrounding tests.

Verification

Scoped builds only (GOFLAGS=-p=2 GOMAXPROCS=2, never ./...):

  • go vet clean on ./lib/services/local/, ./lib/services/, ./lib/authz/, and the three lib/auth/*v1/ service-test packages
  • go build ./lib/services/ — clean
  • Both new tests — PASS
  • go test ./lib/services/local/ — the full existing suite in the touched package, ok in 11.4s, nothing regressed

That last one matters: Slice 0 was described as a "safe no-op" and turned out to break nine subtests in another package, caught only by running the existing tests. Same check was applied here deliberately.

🤖 Generated with Claude Code

Storage had CreateOIDCAuthRequest and GetOIDCAuthRequest but no delete
for any SSO auth request type; upstream relies on TTL expiry alone. An
OIDC implementation needs to delete the request on read so a state token
cannot be replayed within its TTL window.

Adds DeleteOIDCAuthRequest to IdentityService and to the services.Identity
interface, using the same backend key construction and error conventions
as the neighbouring Get. local.IdentityService is the only concrete
implementer of services.Identity, so no other type required changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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