fix(grok): 防止 OAuth 客户端缺失导致崩溃

This commit is contained in:
IanShaw027
2026-08-07 16:38:26 +08:00
parent 21d0905c78
commit 769f1c2def
2 changed files with 31 additions and 2 deletions
+18 -2
View File
@@ -176,8 +176,8 @@ func (s *GrokOAuthService) ExchangeCode(ctx context.Context, input *GrokExchange
return nil, err
}
}
if s.oauthClient == nil {
return nil, infraerrors.New(http.StatusInternalServerError, "GROK_OAUTH_CLIENT_NOT_CONFIGURED", "oauth client is not configured")
if err := s.requireOAuthClient(); err != nil {
return nil, err
}
if !s.sessionStore.TryConsumeSession(input.SessionID) {
return nil, infraerrors.New(http.StatusBadRequest, "GROK_OAUTH_SESSION_ALREADY_USED", "oauth session has already been used")
@@ -195,11 +195,21 @@ func (s *GrokOAuthService) ExchangeCode(ctx context.Context, input *GrokExchange
return s.tokenInfoFromResponse(tokenResp, session.ClientID, nil), nil
}
func (s *GrokOAuthService) requireOAuthClient() error {
if s == nil || s.oauthClient == nil {
return infraerrors.New(http.StatusInternalServerError, "GROK_OAUTH_CLIENT_NOT_CONFIGURED", "oauth client is not configured")
}
return nil
}
func (s *GrokOAuthService) RefreshToken(ctx context.Context, refreshToken, proxyURL, clientID string) (*GrokTokenInfo, error) {
refreshToken = strings.TrimSpace(refreshToken)
if refreshToken == "" {
return nil, infraerrors.New(http.StatusBadRequest, "GROK_OAUTH_NO_REFRESH_TOKEN", "refresh_token is required")
}
if err := s.requireOAuthClient(); err != nil {
return nil, err
}
tokenResp, err := s.oauthClient.RefreshToken(ctx, refreshToken, proxyURL, clientID)
if err != nil {
return nil, err
@@ -226,6 +236,9 @@ func (s *GrokOAuthService) ValidateSSOToken(ctx context.Context, ssoToken string
if ssoToken == "" {
return nil, infraerrors.New(http.StatusBadRequest, "GROK_OAUTH_NO_SSO_TOKEN", "sso_token is required")
}
if err := s.requireOAuthClient(); err != nil {
return nil, err
}
proxyURL, err := s.proxyURL(ctx, proxyID)
if err != nil {
return nil, err
@@ -258,6 +271,9 @@ func (s *GrokOAuthService) AuthorizePassword(ctx context.Context, email, passwor
if strings.TrimSpace(password) == "" {
return nil, infraerrors.New(http.StatusBadRequest, "GROK_OAUTH_PASSWORD_REQUIRED", "password is required")
}
if err := s.requireOAuthClient(); err != nil {
return nil, err
}
proxyURL, err := s.proxyURL(ctx, proxyID)
if err != nil {
return nil, err
@@ -110,6 +110,19 @@ func TestGrokOAuthServiceExchangeCodeRejectsMissingClientWithoutConsumingSession
require.True(t, ok)
}
func TestGrokOAuthServiceExternalFlowsRejectMissingClient(t *testing.T) {
svc := NewGrokOAuthService(nil, nil)
defer svc.Stop()
_, err := svc.RefreshToken(context.Background(), "refresh-token", "", "")
require.Error(t, err)
require.Contains(t, err.Error(), "GROK_OAUTH_CLIENT_NOT_CONFIGURED")
_, err = svc.ValidateSSOToken(context.Background(), "sso-token", nil)
require.Error(t, err)
require.Contains(t, err.Error(), "GROK_OAUTH_CLIENT_NOT_CONFIGURED")
}
func TestGrokOAuthServiceBuildAccountCredentialsDefaultsToSubscriptionProxy(t *testing.T) {
svc := NewGrokOAuthService(nil, &grokOAuthClientStub{})
defer svc.Stop()