mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-19 04:40:52 +08:00
refactor(auth): export Codex constants and slim down handler
This commit is contained in:
@@ -11,7 +11,6 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -1346,73 +1345,25 @@ func (h *Handler) RequestCodexToken(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.Debug("Authorization code received, exchanging for tokens...")
|
log.Debug("Authorization code received, exchanging for tokens...")
|
||||||
// Extract client_id from authURL
|
// Exchange code for tokens using internal auth service
|
||||||
clientID := ""
|
bundle, errExchange := openaiAuth.ExchangeCodeForTokens(ctx, code, pkceCodes)
|
||||||
if u2, errP := url.Parse(authURL); errP == nil {
|
if errExchange != nil {
|
||||||
clientID = u2.Query().Get("client_id")
|
authErr := codex.NewAuthenticationError(codex.ErrCodeExchangeFailed, errExchange)
|
||||||
}
|
|
||||||
// Exchange code for tokens with redirect equal to mgmtRedirect
|
|
||||||
form := url.Values{
|
|
||||||
"grant_type": {"authorization_code"},
|
|
||||||
"client_id": {clientID},
|
|
||||||
"code": {code},
|
|
||||||
"redirect_uri": {"http://localhost:1455/auth/callback"},
|
|
||||||
"code_verifier": {pkceCodes.CodeVerifier},
|
|
||||||
}
|
|
||||||
httpClient := util.SetProxy(&h.cfg.SDKConfig, &http.Client{})
|
|
||||||
req, _ := http.NewRequestWithContext(ctx, "POST", "https://auth.openai.com/oauth/token", strings.NewReader(form.Encode()))
|
|
||||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
|
||||||
req.Header.Set("Accept", "application/json")
|
|
||||||
resp, errDo := httpClient.Do(req)
|
|
||||||
if errDo != nil {
|
|
||||||
authErr := codex.NewAuthenticationError(codex.ErrCodeExchangeFailed, errDo)
|
|
||||||
SetOAuthSessionError(state, "Failed to exchange authorization code for tokens")
|
SetOAuthSessionError(state, "Failed to exchange authorization code for tokens")
|
||||||
log.Errorf("Failed to exchange authorization code for tokens: %v", authErr)
|
log.Errorf("Failed to exchange authorization code for tokens: %v", authErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer func() { _ = resp.Body.Close() }()
|
|
||||||
respBody, _ := io.ReadAll(resp.Body)
|
// Extract additional info for filename generation
|
||||||
if resp.StatusCode != http.StatusOK {
|
claims, _ := codex.ParseJWTToken(bundle.TokenData.IDToken)
|
||||||
SetOAuthSessionError(state, fmt.Sprintf("Token exchange failed with status %d", resp.StatusCode))
|
|
||||||
log.Errorf("token exchange failed with status %d: %s", resp.StatusCode, string(respBody))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var tokenResp struct {
|
|
||||||
AccessToken string `json:"access_token"`
|
|
||||||
RefreshToken string `json:"refresh_token"`
|
|
||||||
IDToken string `json:"id_token"`
|
|
||||||
ExpiresIn int `json:"expires_in"`
|
|
||||||
}
|
|
||||||
if errU := json.Unmarshal(respBody, &tokenResp); errU != nil {
|
|
||||||
SetOAuthSessionError(state, "Failed to parse token response")
|
|
||||||
log.Errorf("failed to parse token response: %v", errU)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
claims, _ := codex.ParseJWTToken(tokenResp.IDToken)
|
|
||||||
email := ""
|
|
||||||
accountID := ""
|
|
||||||
planType := ""
|
planType := ""
|
||||||
if claims != nil {
|
|
||||||
email = claims.GetUserEmail()
|
|
||||||
accountID = claims.GetAccountID()
|
|
||||||
planType = strings.TrimSpace(claims.CodexAuthInfo.ChatgptPlanType)
|
|
||||||
}
|
|
||||||
hashAccountID := ""
|
hashAccountID := ""
|
||||||
if accountID != "" {
|
if claims != nil {
|
||||||
|
planType = strings.TrimSpace(claims.CodexAuthInfo.ChatgptPlanType)
|
||||||
|
if accountID := claims.GetAccountID(); accountID != "" {
|
||||||
digest := sha256.Sum256([]byte(accountID))
|
digest := sha256.Sum256([]byte(accountID))
|
||||||
hashAccountID = hex.EncodeToString(digest[:])[:8]
|
hashAccountID = hex.EncodeToString(digest[:])[:8]
|
||||||
}
|
}
|
||||||
// Build bundle compatible with existing storage
|
|
||||||
bundle := &codex.CodexAuthBundle{
|
|
||||||
TokenData: codex.CodexTokenData{
|
|
||||||
IDToken: tokenResp.IDToken,
|
|
||||||
AccessToken: tokenResp.AccessToken,
|
|
||||||
RefreshToken: tokenResp.RefreshToken,
|
|
||||||
AccountID: accountID,
|
|
||||||
Email: email,
|
|
||||||
Expire: time.Now().Add(time.Duration(tokenResp.ExpiresIn) * time.Second).Format(time.RFC3339),
|
|
||||||
},
|
|
||||||
LastRefresh: time.Now().Format(time.RFC3339),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create token storage and persist
|
// Create token storage and persist
|
||||||
|
|||||||
@@ -19,11 +19,12 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// OAuth configuration constants for OpenAI Codex
|
||||||
const (
|
const (
|
||||||
openaiAuthURL = "https://auth.openai.com/oauth/authorize"
|
AuthURL = "https://auth.openai.com/oauth/authorize"
|
||||||
openaiTokenURL = "https://auth.openai.com/oauth/token"
|
TokenURL = "https://auth.openai.com/oauth/token"
|
||||||
openaiClientID = "app_EMoamEEZ73f0CkXaXp7hrann"
|
ClientID = "app_EMoamEEZ73f0CkXaXp7hrann"
|
||||||
redirectURI = "http://localhost:1455/auth/callback"
|
RedirectURI = "http://localhost:1455/auth/callback"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CodexAuth handles the OpenAI OAuth2 authentication flow.
|
// CodexAuth handles the OpenAI OAuth2 authentication flow.
|
||||||
@@ -50,9 +51,9 @@ func (o *CodexAuth) GenerateAuthURL(state string, pkceCodes *PKCECodes) (string,
|
|||||||
}
|
}
|
||||||
|
|
||||||
params := url.Values{
|
params := url.Values{
|
||||||
"client_id": {openaiClientID},
|
"client_id": {ClientID},
|
||||||
"response_type": {"code"},
|
"response_type": {"code"},
|
||||||
"redirect_uri": {redirectURI},
|
"redirect_uri": {RedirectURI},
|
||||||
"scope": {"openid email profile offline_access"},
|
"scope": {"openid email profile offline_access"},
|
||||||
"state": {state},
|
"state": {state},
|
||||||
"code_challenge": {pkceCodes.CodeChallenge},
|
"code_challenge": {pkceCodes.CodeChallenge},
|
||||||
@@ -62,7 +63,7 @@ func (o *CodexAuth) GenerateAuthURL(state string, pkceCodes *PKCECodes) (string,
|
|||||||
"codex_cli_simplified_flow": {"true"},
|
"codex_cli_simplified_flow": {"true"},
|
||||||
}
|
}
|
||||||
|
|
||||||
authURL := fmt.Sprintf("%s?%s", openaiAuthURL, params.Encode())
|
authURL := fmt.Sprintf("%s?%s", AuthURL, params.Encode())
|
||||||
return authURL, nil
|
return authURL, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,13 +78,13 @@ func (o *CodexAuth) ExchangeCodeForTokens(ctx context.Context, code string, pkce
|
|||||||
// Prepare token exchange request
|
// Prepare token exchange request
|
||||||
data := url.Values{
|
data := url.Values{
|
||||||
"grant_type": {"authorization_code"},
|
"grant_type": {"authorization_code"},
|
||||||
"client_id": {openaiClientID},
|
"client_id": {ClientID},
|
||||||
"code": {code},
|
"code": {code},
|
||||||
"redirect_uri": {redirectURI},
|
"redirect_uri": {RedirectURI},
|
||||||
"code_verifier": {pkceCodes.CodeVerifier},
|
"code_verifier": {pkceCodes.CodeVerifier},
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "POST", openaiTokenURL, strings.NewReader(data.Encode()))
|
req, err := http.NewRequestWithContext(ctx, "POST", TokenURL, strings.NewReader(data.Encode()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create token request: %w", err)
|
return nil, fmt.Errorf("failed to create token request: %w", err)
|
||||||
}
|
}
|
||||||
@@ -163,13 +164,13 @@ func (o *CodexAuth) RefreshTokens(ctx context.Context, refreshToken string) (*Co
|
|||||||
}
|
}
|
||||||
|
|
||||||
data := url.Values{
|
data := url.Values{
|
||||||
"client_id": {openaiClientID},
|
"client_id": {ClientID},
|
||||||
"grant_type": {"refresh_token"},
|
"grant_type": {"refresh_token"},
|
||||||
"refresh_token": {refreshToken},
|
"refresh_token": {refreshToken},
|
||||||
"scope": {"openid profile email"},
|
"scope": {"openid profile email"},
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "POST", openaiTokenURL, strings.NewReader(data.Encode()))
|
req, err := http.NewRequestWithContext(ctx, "POST", TokenURL, strings.NewReader(data.Encode()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create refresh request: %w", err)
|
return nil, fmt.Errorf("failed to create refresh request: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user