parseClaudeCredentials parses Claude Code credential formats.
(data []byte, logger *zap.Logger)
| 119 | |
| 120 | // parseClaudeCredentials parses Claude Code credential formats. |
| 121 | func parseClaudeCredentials(data []byte, logger *zap.Logger) *AuthProfileCredential { |
| 122 | // Format 1: { "claudeAiOauth": { "accessToken": "...", "refreshToken": "...", "expiresAt": "..." } } |
| 123 | var format1 struct { |
| 124 | ClaudeAiOauth struct { |
| 125 | AccessToken string `json:"accessToken"` |
| 126 | RefreshToken string `json:"refreshToken"` |
| 127 | ExpiresAt string `json:"expiresAt"` |
| 128 | } `json:"claudeAiOauth"` |
| 129 | } |
| 130 | if err := json.Unmarshal(data, &format1); err == nil && format1.ClaudeAiOauth.AccessToken != "" { |
| 131 | var expires int64 |
| 132 | if t, err := time.Parse(time.RFC3339, format1.ClaudeAiOauth.ExpiresAt); err == nil { |
| 133 | expires = t.Unix() |
| 134 | } |
| 135 | if expires > 0 && time.Now().Unix() > expires { |
| 136 | logger.Debug(i18n.T("auth.sync.claude_expired")) |
| 137 | return nil |
| 138 | } |
| 139 | return &AuthProfileCredential{ |
| 140 | CredType: CredentialOAuth, |
| 141 | Provider: ProviderAnthropic, |
| 142 | Access: format1.ClaudeAiOauth.AccessToken, |
| 143 | Refresh: format1.ClaudeAiOauth.RefreshToken, |
| 144 | Expires: expires, |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | // Format 2: { "access_token": "...", "refresh_token": "...", "expires_at": 123456 } |
| 149 | var format2 struct { |
| 150 | AccessToken string `json:"access_token"` |
| 151 | RefreshToken string `json:"refresh_token"` |
| 152 | ExpiresAt int64 `json:"expires_at"` |
| 153 | } |
| 154 | if err := json.Unmarshal(data, &format2); err == nil && format2.AccessToken != "" { |
| 155 | if format2.ExpiresAt > 0 && time.Now().Unix() > format2.ExpiresAt { |
| 156 | logger.Debug(i18n.T("auth.sync.claude_cred_expired")) |
| 157 | return nil |
| 158 | } |
| 159 | return &AuthProfileCredential{ |
| 160 | CredType: CredentialOAuth, |
| 161 | Provider: ProviderAnthropic, |
| 162 | Access: format2.AccessToken, |
| 163 | Refresh: format2.RefreshToken, |
| 164 | Expires: format2.ExpiresAt, |
| 165 | } |
| 166 | } |
| 167 | |
| 168 | return nil |
| 169 | } |
| 170 | |
| 171 | // parseCodexCredentials parses Codex CLI credential formats. |
| 172 | func parseCodexCredentials(data []byte, logger *zap.Logger) *AuthProfileCredential { |
no test coverage detected