From 059bfee91b4e29a34337b2c8fcb700bb8fc7ac82 Mon Sep 17 00:00:00 2001 From: Luis Pater Date: Tue, 20 Jan 2026 11:36:29 +0800 Subject: [PATCH] feat(auth): add hashed account ID to credential filenames for team plans --- internal/auth/codex/filename.go | 10 ++++++---- sdk/auth/codex.go | 10 +++++++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/internal/auth/codex/filename.go b/internal/auth/codex/filename.go index fcf02802..26515fef 100644 --- a/internal/auth/codex/filename.go +++ b/internal/auth/codex/filename.go @@ -12,19 +12,21 @@ import ( // CredentialFileName returns the filename used to persist Codex OAuth credentials. // When planType is available (e.g. "plus", "team"), it is appended after the email // as a suffix to disambiguate subscriptions. -func CredentialFileName(email, planType string, includeProviderPrefix bool) string { +func CredentialFileName(email, planType, hashAccountID string, includeProviderPrefix bool) string { email = strings.TrimSpace(email) plan := normalizePlanTypeForFilename(planType) prefix := "" if includeProviderPrefix { - prefix = "codex-" + prefix = "codex" } if plan == "" { - return fmt.Sprintf("%s%s.json", prefix, email) + return fmt.Sprintf("%s-%s.json", prefix, email) + } else if plan == "team" { + return fmt.Sprintf("%s-%s-%s-%s.json", prefix, hashAccountID, email, plan) } - return fmt.Sprintf("%s%s-%s.json", prefix, email, plan) + return fmt.Sprintf("%s-%s-%s.json", prefix, email, plan) } func normalizePlanTypeForFilename(planType string) string { diff --git a/sdk/auth/codex.go b/sdk/auth/codex.go index 30a36f97..b655a239 100644 --- a/sdk/auth/codex.go +++ b/sdk/auth/codex.go @@ -2,6 +2,8 @@ package auth import ( "context" + "crypto/sha256" + "encoding/hex" "fmt" "net/http" "strings" @@ -192,12 +194,18 @@ waitForCallback: } planType := "" + hashAccountID := "" if tokenStorage.IDToken != "" { if claims, errParse := codex.ParseJWTToken(tokenStorage.IDToken); errParse == nil && claims != nil { planType = strings.TrimSpace(claims.CodexAuthInfo.ChatgptPlanType) + accountID := strings.TrimSpace(claims.CodexAuthInfo.ChatgptAccountID) + if accountID != "" { + digest := sha256.Sum256([]byte(accountID)) + hashAccountID = hex.EncodeToString(digest[:])[:8] + } } } - fileName := codex.CredentialFileName(tokenStorage.Email, planType, true) + fileName := codex.CredentialFileName(tokenStorage.Email, planType, hashAccountID, true) metadata := map[string]any{ "email": tokenStorage.Email, }