Files
CLIProxyAPIPlus/test_auth_js_style.go

238 lines
6.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 测试脚本 2模拟 kiro2Api_js 的认证方式
// 这个脚本完整模拟 kiro-gateway/temp/kiro2Api_js 的认证逻辑
// 运行方式: go run test_auth_js_style.go
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"time"
)
// 常量 - 来自 kiro2Api_js/src/kiro/auth.js
const (
REFRESH_URL_TEMPLATE = "https://prod.{{region}}.auth.desktop.kiro.dev/refreshToken"
REFRESH_IDC_URL_TEMPLATE = "https://oidc.{{region}}.amazonaws.com/token"
AUTH_METHOD_SOCIAL = "social"
AUTH_METHOD_IDC = "IdC"
)
func main() {
fmt.Println("=" + strings.Repeat("=", 59))
fmt.Println(" 测试脚本 2: kiro2Api_js 风格认证")
fmt.Println("=" + strings.Repeat("=", 59))
// Step 1: 加载 token 文件
fmt.Println("\n[Step 1] 加载 Token 文件")
fmt.Println("-" + strings.Repeat("-", 59))
tokenPaths := []string{
filepath.Join(os.Getenv("USERPROFILE"), ".aws", "sso", "cache", "kiro-auth-token.json"),
"E:/ai_project_2api/kiro-gateway/configs/kiro/kiro-auth-token-1768317098.json",
}
var tokenData map[string]interface{}
var loadedPath string
for _, p := range tokenPaths {
data, err := os.ReadFile(p)
if err == nil {
if err := json.Unmarshal(data, &tokenData); err == nil {
loadedPath = p
break
}
}
}
if tokenData == nil {
fmt.Println("❌ 无法加载任何 token 文件")
return
}
fmt.Printf("✅ 加载文件: %s\n", loadedPath)
// 提取字段 - 模拟 kiro2Api_js/src/kiro/auth.js initializeAuth
accessToken, _ := tokenData["accessToken"].(string)
refreshToken, _ := tokenData["refreshToken"].(string)
clientId, _ := tokenData["clientId"].(string)
clientSecret, _ := tokenData["clientSecret"].(string)
authMethod, _ := tokenData["authMethod"].(string)
region, _ := tokenData["region"].(string)
if region == "" {
region = "us-east-1"
fmt.Println("⚠️ Region 未设置,使用默认值 us-east-1")
}
fmt.Printf("\nToken 信息:\n")
fmt.Printf(" AuthMethod: %s\n", authMethod)
fmt.Printf(" Region: %s\n", region)
fmt.Printf(" 有 ClientID: %v\n", clientId != "")
fmt.Printf(" 有 ClientSecret: %v\n", clientSecret != "")
// Step 2: 测试当前 token
fmt.Println("\n[Step 2] 测试当前 AccessToken")
fmt.Println("-" + strings.Repeat("-", 59))
if testAPI(accessToken, region) {
fmt.Println("✅ 当前 AccessToken 有效")
return
}
fmt.Println("⚠️ 当前 AccessToken 无效,开始刷新...")
// Step 3: 根据 authMethod 选择刷新方式 - 模拟 doRefreshToken
fmt.Println("\n[Step 3] 刷新 Token (JS 风格)")
fmt.Println("-" + strings.Repeat("-", 59))
var refreshURL string
var requestBody map[string]interface{}
// 判断认证方式 - 模拟 kiro2Api_js auth.js doRefreshToken
if authMethod == AUTH_METHOD_SOCIAL {
// Social 认证
refreshURL = strings.Replace(REFRESH_URL_TEMPLATE, "{{region}}", region, 1)
requestBody = map[string]interface{}{
"refreshToken": refreshToken,
}
fmt.Println("使用 Social 认证方式")
} else {
// IdC 认证 (默认)
refreshURL = strings.Replace(REFRESH_IDC_URL_TEMPLATE, "{{region}}", region, 1)
requestBody = map[string]interface{}{
"refreshToken": refreshToken,
"clientId": clientId,
"clientSecret": clientSecret,
"grantType": "refresh_token",
}
fmt.Println("使用 IdC 认证方式")
}
fmt.Printf("刷新 URL: %s\n", refreshURL)
fmt.Printf("请求字段: %v\n", getKeys(requestBody))
// 发送刷新请求
body, _ := json.Marshal(requestBody)
req, _ := http.NewRequest("POST", refreshURL, bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
resp, err := client.Do(req)
if err != nil {
fmt.Printf("❌ 请求失败: %v\n", err)
return
}
defer resp.Body.Close()
respBody, _ := io.ReadAll(resp.Body)
fmt.Printf("\n响应状态: HTTP %d\n", resp.StatusCode)
if resp.StatusCode != 200 {
fmt.Printf("❌ 刷新失败: %s\n", string(respBody))
// 分析错误
var errResp map[string]interface{}
if err := json.Unmarshal(respBody, &errResp); err == nil {
if errType, ok := errResp["error"].(string); ok {
fmt.Printf("错误类型: %s\n", errType)
if errType == "invalid_grant" {
fmt.Println("\n💡 提示: refresh_token 可能已过期,需要重新授权")
}
}
if errDesc, ok := errResp["error_description"].(string); ok {
fmt.Printf("错误描述: %s\n", errDesc)
}
}
return
}
// 解析响应
var refreshResp map[string]interface{}
json.Unmarshal(respBody, &refreshResp)
newAccessToken, _ := refreshResp["accessToken"].(string)
newRefreshToken, _ := refreshResp["refreshToken"].(string)
expiresIn, _ := refreshResp["expiresIn"].(float64)
fmt.Println("✅ Token 刷新成功!")
fmt.Printf(" 新 AccessToken: %s...\n", truncate(newAccessToken, 50))
fmt.Printf(" ExpiresIn: %.0f 秒\n", expiresIn)
if newRefreshToken != "" {
fmt.Printf(" 新 RefreshToken: %s...\n", truncate(newRefreshToken, 50))
}
// Step 4: 验证新 token
fmt.Println("\n[Step 4] 验证新 Token")
fmt.Println("-" + strings.Repeat("-", 59))
if testAPI(newAccessToken, region) {
fmt.Println("✅ 新 Token 验证成功!")
// 保存新 token - 模拟 saveCredentialsToFile
tokenData["accessToken"] = newAccessToken
if newRefreshToken != "" {
tokenData["refreshToken"] = newRefreshToken
}
tokenData["expiresAt"] = time.Now().Add(time.Duration(expiresIn) * time.Second).Format(time.RFC3339)
saveData, _ := json.MarshalIndent(tokenData, "", " ")
newPath := strings.TrimSuffix(loadedPath, ".json") + "_js_refreshed.json"
os.WriteFile(newPath, saveData, 0644)
fmt.Printf("✅ 已保存到: %s\n", newPath)
} else {
fmt.Println("❌ 新 Token 验证失败")
}
fmt.Println("\n" + strings.Repeat("=", 60))
fmt.Println(" 测试完成")
fmt.Println(strings.Repeat("=", 60))
}
func testAPI(accessToken, region string) bool {
url := fmt.Sprintf("https://codewhisperer.%s.amazonaws.com", region)
payload := map[string]interface{}{
"origin": "AI_EDITOR",
"isEmailRequired": true,
"resourceType": "AGENTIC_REQUEST",
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/x-amz-json-1.0")
req.Header.Set("x-amz-target", "AmazonCodeWhispererService.GetUsageLimits")
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Accept", "application/json")
client := &http.Client{Timeout: 30 * time.Second}
resp, err := client.Do(req)
if err != nil {
return false
}
defer resp.Body.Close()
return resp.StatusCode == 200
}
func getKeys(m map[string]interface{}) []string {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
return keys
}
func truncate(s string, n int) string {
if len(s) <= n {
return s
}
return s[:n]
}