feat(auth): Add stable label to Gemini Web tokens for logging

This commit is contained in:
hkfires
2025-09-25 10:32:06 +08:00
parent 7f2e2fee56
commit 20f3e62529
5 changed files with 31 additions and 11 deletions

View File

@@ -714,6 +714,8 @@ func (h *Handler) CreateGeminiWebToken(c *gin.Context) {
Secure1PSID: payload.Secure1PSID, Secure1PSID: payload.Secure1PSID,
Secure1PSIDTS: payload.Secure1PSIDTS, Secure1PSIDTS: payload.Secure1PSIDTS,
} }
// Provide a stable label (gemini-web-<hash>) for logging and identification
tokenStorage.Label = strings.TrimSuffix(fileName, ".json")
record := &sdkAuth.TokenRecord{ record := &sdkAuth.TokenRecord{
Provider: "gemini-web", Provider: "gemini-web",

View File

@@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"time" "time"
"github.com/router-for-me/CLIProxyAPI/v6/internal/misc" "github.com/router-for-me/CLIProxyAPI/v6/internal/misc"
@@ -20,12 +21,25 @@ type GeminiWebTokenStorage struct {
Secure1PSIDTS string `json:"secure_1psidts"` Secure1PSIDTS string `json:"secure_1psidts"`
Type string `json:"type"` Type string `json:"type"`
LastRefresh string `json:"last_refresh,omitempty"` LastRefresh string `json:"last_refresh,omitempty"`
// Label is a stable account identifier used for logging, e.g. "gemini-web-<hash>".
// It is derived from the auth file name when not explicitly set.
Label string `json:"label,omitempty"`
} }
// SaveTokenToFile serializes the Gemini Web token storage to a JSON file. // SaveTokenToFile serializes the Gemini Web token storage to a JSON file.
func (ts *GeminiWebTokenStorage) SaveTokenToFile(authFilePath string) error { func (ts *GeminiWebTokenStorage) SaveTokenToFile(authFilePath string) error {
misc.LogSavingCredentials(authFilePath) misc.LogSavingCredentials(authFilePath)
ts.Type = "gemini-web" ts.Type = "gemini-web"
// Auto-derive a stable label from the file name if missing.
if ts.Label == "" {
base := filepath.Base(authFilePath)
if strings.HasSuffix(strings.ToLower(base), ".json") {
base = strings.TrimSuffix(base, filepath.Ext(base))
}
if base != "" {
ts.Label = base
}
}
if ts.LastRefresh == "" { if ts.LastRefresh == "" {
ts.LastRefresh = time.Now().Format(time.RFC3339) ts.LastRefresh = time.Now().Format(time.RFC3339)
} }

View File

@@ -49,6 +49,10 @@ func DoGeminiWebAuth(cfg *config.Config) {
hasher.Write([]byte(secure1psid)) hasher.Write([]byte(secure1psid))
hash := hex.EncodeToString(hasher.Sum(nil)) hash := hex.EncodeToString(hasher.Sum(nil))
fileName := fmt.Sprintf("gemini-web-%s.json", hash[:16]) fileName := fmt.Sprintf("gemini-web-%s.json", hash[:16])
// Set a stable label for logging, e.g. gemini-web-<hash>
if tokenStorage != nil {
tokenStorage.Label = strings.TrimSuffix(fileName, ".json")
}
record := &sdkAuth.TokenRecord{ record := &sdkAuth.TokenRecord{
Provider: "gemini-web", Provider: "gemini-web",
FileName: fileName, FileName: fileName,

View File

@@ -286,7 +286,8 @@ func (m *Manager) executeWithProvider(ctx context.Context, provider string, req
} else if accountType == "oauth" { } else if accountType == "oauth" {
log.Debugf("Use OAuth %s for model %s", accountInfo, req.Model) log.Debugf("Use OAuth %s for model %s", accountInfo, req.Model)
} else if accountType == "cookie" { } else if accountType == "cookie" {
log.Debugf("Use Cookie %s for model %s", util.HideAPIKey(accountInfo), req.Model) // Only Gemini Web uses cookie; print stable account label as-is.
log.Debugf("Use Cookie %s for model %s", accountInfo, req.Model)
} }
tried[auth.ID] = struct{}{} tried[auth.ID] = struct{}{}
@@ -333,7 +334,7 @@ func (m *Manager) executeCountWithProvider(ctx context.Context, provider string,
} else if accountType == "oauth" { } else if accountType == "oauth" {
log.Debugf("Use OAuth %s for model %s", accountInfo, req.Model) log.Debugf("Use OAuth %s for model %s", accountInfo, req.Model)
} else if accountType == "cookie" { } else if accountType == "cookie" {
log.Debugf("Use Cookie %s for model %s", util.HideAPIKey(accountInfo), req.Model) log.Debugf("Use Cookie %s for model %s", accountInfo, req.Model)
} }
tried[auth.ID] = struct{}{} tried[auth.ID] = struct{}{}
@@ -380,7 +381,7 @@ func (m *Manager) executeStreamWithProvider(ctx context.Context, provider string
} else if accountType == "oauth" { } else if accountType == "oauth" {
log.Debugf("Use OAuth %s for model %s", accountInfo, req.Model) log.Debugf("Use OAuth %s for model %s", accountInfo, req.Model)
} else if accountType == "cookie" { } else if accountType == "cookie" {
log.Debugf("Use Cookie %s for model %s", util.HideAPIKey(accountInfo), req.Model) log.Debugf("Use Cookie %s for model %s", accountInfo, req.Model)
} }
tried[auth.ID] = struct{}{} tried[auth.ID] = struct{}{}

View File

@@ -129,6 +129,13 @@ func (a *Auth) AccountInfo() (string, string) {
return "", "" return "", ""
} }
if strings.ToLower(a.Provider) == "gemini-web" { if strings.ToLower(a.Provider) == "gemini-web" {
// Prefer explicit label written into auth file (e.g., gemini-web-<hash>)
if a.Metadata != nil {
if v, ok := a.Metadata["label"].(string); ok && strings.TrimSpace(v) != "" {
return "cookie", strings.TrimSpace(v)
}
}
// Minimal fallback to cookie value for backward compatibility
if a.Metadata != nil { if a.Metadata != nil {
if v, ok := a.Metadata["secure_1psid"].(string); ok && v != "" { if v, ok := a.Metadata["secure_1psid"].(string); ok && v != "" {
return "cookie", v return "cookie", v
@@ -137,14 +144,6 @@ func (a *Auth) AccountInfo() (string, string) {
return "cookie", v return "cookie", v
} }
} }
if a.Attributes != nil {
if v := a.Attributes["secure_1psid"]; v != "" {
return "cookie", v
}
if v := a.Attributes["api_key"]; v != "" {
return "cookie", v
}
}
} }
if a.Metadata != nil { if a.Metadata != nil {
if v, ok := a.Metadata["email"].(string); ok { if v, ok := a.Metadata["email"].(string); ok {