From b3a07aeae7cf20dab114f98a22911d1cc321c2e9 Mon Sep 17 00:00:00 2001 From: Heatherm Huang Date: Tue, 16 Jun 2026 19:17:11 +0800 Subject: [PATCH] fix: align grok oauth exchange with xai --- backend/internal/pkg/xai/oauth.go | 2 +- backend/internal/repository/grok_oauth_client.go | 4 +--- backend/internal/repository/grok_oauth_client_test.go | 5 ++--- backend/internal/service/grok_oauth_service.go | 2 +- backend/internal/service/oauth_service.go | 2 +- backend/internal/service/openai_gateway_grok.go | 4 +++- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/backend/internal/pkg/xai/oauth.go b/backend/internal/pkg/xai/oauth.go index 31ef793b33..8af0cfdb3c 100644 --- a/backend/internal/pkg/xai/oauth.go +++ b/backend/internal/pkg/xai/oauth.go @@ -14,7 +14,7 @@ import ( ) const ( - OAuthIssuer = "https://auth.x.ai" + OAuthIssuer = "https://accounts.x.ai" DiscoveryURL = OAuthIssuer + "/.well-known/openid-configuration" DefaultAuthorizeURL = OAuthIssuer + "/oauth2/authorize" DefaultTokenURL = OAuthIssuer + "/oauth2/token" diff --git a/backend/internal/repository/grok_oauth_client.go b/backend/internal/repository/grok_oauth_client.go index 0ea78b3221..a437b3889c 100644 --- a/backend/internal/repository/grok_oauth_client.go +++ b/backend/internal/repository/grok_oauth_client.go @@ -21,7 +21,7 @@ func NewGrokOAuthClient() service.GrokOAuthClient { return &grokOAuthClient{tokenURL: xai.EffectiveTokenURL()} } -func (c *grokOAuthClient) ExchangeCode(ctx context.Context, code, codeVerifier, codeChallenge, redirectURI, proxyURL, clientID string) (*xai.TokenResponse, error) { +func (c *grokOAuthClient) ExchangeCode(ctx context.Context, code, codeVerifier, redirectURI, proxyURL, clientID string) (*xai.TokenResponse, error) { client, err := createGrokReqClient(proxyURL) if err != nil { return nil, infraerrors.Newf(http.StatusBadGateway, "GROK_OAUTH_CLIENT_INIT_FAILED", "create HTTP client: %v", err) @@ -38,8 +38,6 @@ func (c *grokOAuthClient) ExchangeCode(ctx context.Context, code, codeVerifier, formData.Set("code", code) formData.Set("redirect_uri", xai.EffectiveRedirectURI(redirectURI)) formData.Set("code_verifier", codeVerifier) - formData.Set("code_challenge", codeChallenge) - formData.Set("code_challenge_method", "S256") var tokenResp xai.TokenResponse resp, err := client.R(). diff --git a/backend/internal/repository/grok_oauth_client_test.go b/backend/internal/repository/grok_oauth_client_test.go index 4851652ac1..b17256a5f3 100644 --- a/backend/internal/repository/grok_oauth_client_test.go +++ b/backend/internal/repository/grok_oauth_client_test.go @@ -25,8 +25,8 @@ func TestGrokOAuthClientExchangeAndRefreshUseFormFields(t *testing.T) { require.Equal(t, "auth-code", r.Form.Get("code")) require.Equal(t, "http://127.0.0.1:56121/callback", r.Form.Get("redirect_uri")) require.Equal(t, "verifier", r.Form.Get("code_verifier")) - require.Equal(t, "challenge", r.Form.Get("code_challenge")) - require.Equal(t, "S256", r.Form.Get("code_challenge_method")) + require.Empty(t, r.Form.Get("code_challenge")) + require.Empty(t, r.Form.Get("code_challenge_method")) _ = json.NewEncoder(w).Encode(map[string]any{ "access_token": "exchange-access", "refresh_token": "exchange-refresh", @@ -55,7 +55,6 @@ func TestGrokOAuthClientExchangeAndRefreshUseFormFields(t *testing.T) { context.Background(), "auth-code", "verifier", - "challenge", "http://127.0.0.1:56121/callback", "", "client-id", diff --git a/backend/internal/service/grok_oauth_service.go b/backend/internal/service/grok_oauth_service.go index f1aceefe4e..d926138613 100644 --- a/backend/internal/service/grok_oauth_service.go +++ b/backend/internal/service/grok_oauth_service.go @@ -135,7 +135,7 @@ func (s *GrokOAuthService) ExchangeCode(ctx context.Context, input *GrokExchange redirectURI = input.RedirectURI } - tokenResp, err := s.oauthClient.ExchangeCode(ctx, code, session.CodeVerifier, session.CodeChallenge, redirectURI, proxyURL, session.ClientID) + tokenResp, err := s.oauthClient.ExchangeCode(ctx, code, session.CodeVerifier, redirectURI, proxyURL, session.ClientID) if err != nil { return nil, err } diff --git a/backend/internal/service/oauth_service.go b/backend/internal/service/oauth_service.go index 7e749b65d9..c03ba912dc 100644 --- a/backend/internal/service/oauth_service.go +++ b/backend/internal/service/oauth_service.go @@ -20,7 +20,7 @@ type OpenAIOAuthClient interface { // GrokOAuthClient interface for xAI/Grok OAuth operations. type GrokOAuthClient interface { - ExchangeCode(ctx context.Context, code, codeVerifier, codeChallenge, redirectURI, proxyURL, clientID string) (*xai.TokenResponse, error) + ExchangeCode(ctx context.Context, code, codeVerifier, redirectURI, proxyURL, clientID string) (*xai.TokenResponse, error) RefreshToken(ctx context.Context, refreshToken, proxyURL, clientID string) (*xai.TokenResponse, error) } diff --git a/backend/internal/service/openai_gateway_grok.go b/backend/internal/service/openai_gateway_grok.go index 2ae5cc147e..a82dd29a5b 100644 --- a/backend/internal/service/openai_gateway_grok.go +++ b/backend/internal/service/openai_gateway_grok.go @@ -5,6 +5,7 @@ import ( "context" "encoding/json" "fmt" + "io" "net/http" "strings" "time" @@ -60,9 +61,11 @@ func (s *OpenAIGatewayService) forwardGrokResponses( if err != nil { return nil, s.handleOpenAIUpstreamTransportError(ctx, c, account, err, false) } + defer func() { _ = resp.Body.Close() }() if resp.StatusCode >= 400 { respBody := s.readUpstreamErrorBody(resp) + resp.Body = io.NopCloser(bytes.NewReader(respBody)) s.updateGrokUsageSnapshot(ctx, account.ID, xai.ParseQuotaHeaders(resp.Header, resp.StatusCode)) upstreamMsg := sanitizeUpstreamErrorMessage(extractUpstreamErrorMessage(respBody)) if upstreamMsg == "" { @@ -87,7 +90,6 @@ func (s *OpenAIGatewayService) forwardGrokResponses( } return s.handleErrorResponse(ctx, resp, c, account, patchedBody, upstreamModel) } - defer func() { _ = resp.Body.Close() }() s.updateGrokUsageSnapshot(ctx, account.ID, xai.ParseQuotaHeaders(resp.Header, resp.StatusCode))