Skip to content

Commit e95be10

Browse files
committed
fix(auth): validate antigravity token userinfo email
1 parent f3d58fa commit e95be10

File tree

3 files changed

+57
-32
lines changed

3 files changed

+57
-32
lines changed

internal/api/handlers/management/auth_files.go

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,13 +1148,9 @@ func (h *Handler) RequestGeminiCLIToken(c *gin.Context) {
11481148
}
11491149

11501150
ifToken["token_uri"] = "https://oauth2.googleapis.com/token"
1151-
ifToken["client_id"] = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com"
1152-
ifToken["client_secret"] = "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"
1153-
ifToken["scopes"] = []string{
1154-
"https://www.googleapis.com/auth/cloud-platform",
1155-
"https://www.googleapis.com/auth/userinfo.email",
1156-
"https://www.googleapis.com/auth/userinfo.profile",
1157-
}
1151+
ifToken["client_id"] = geminiAuth.ClientID
1152+
ifToken["client_secret"] = geminiAuth.ClientSecret
1153+
ifToken["scopes"] = geminiAuth.Scopes
11581154
ifToken["universe_domain"] = "googleapis.com"
11591155

11601156
ts := geminiAuth.GeminiTokenStorage{
@@ -1478,20 +1474,29 @@ func (h *Handler) RequestAntigravityToken(c *gin.Context) {
14781474
return
14791475
}
14801476

1481-
email := ""
1482-
if strings.TrimSpace(tokenResp.AccessToken) != "" {
1483-
fetchedEmail, errInfo := authSvc.FetchUserInfo(ctx, tokenResp.AccessToken)
1484-
if errInfo != nil {
1485-
log.Errorf("Failed to fetch user info: %v", errInfo)
1486-
SetOAuthSessionError(state, "Failed to fetch user info")
1487-
return
1488-
}
1489-
email = strings.TrimSpace(fetchedEmail)
1477+
accessToken := strings.TrimSpace(tokenResp.AccessToken)
1478+
if accessToken == "" {
1479+
log.Error("antigravity: token exchange returned empty access token")
1480+
SetOAuthSessionError(state, "Failed to exchange token")
1481+
return
1482+
}
1483+
1484+
email, errInfo := authSvc.FetchUserInfo(ctx, accessToken)
1485+
if errInfo != nil {
1486+
log.Errorf("Failed to fetch user info: %v", errInfo)
1487+
SetOAuthSessionError(state, "Failed to fetch user info")
1488+
return
1489+
}
1490+
email = strings.TrimSpace(email)
1491+
if email == "" {
1492+
log.Error("antigravity: user info returned empty email")
1493+
SetOAuthSessionError(state, "Failed to fetch user info")
1494+
return
14901495
}
14911496

14921497
projectID := ""
1493-
if strings.TrimSpace(tokenResp.AccessToken) != "" {
1494-
fetchedProjectID, errProject := authSvc.FetchProjectID(ctx, tokenResp.AccessToken)
1498+
if accessToken != "" {
1499+
fetchedProjectID, errProject := authSvc.FetchProjectID(ctx, accessToken)
14951500
if errProject != nil {
14961501
log.Warnf("antigravity: failed to fetch project ID: %v", errProject)
14971502
} else {

internal/auth/antigravity/auth.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,18 +100,19 @@ func (o *AntigravityAuth) ExchangeCodeForTokens(ctx context.Context, code, redir
100100

101101
// FetchUserInfo retrieves user email from Google
102102
func (o *AntigravityAuth) FetchUserInfo(ctx context.Context, accessToken string) (string, error) {
103-
if strings.TrimSpace(accessToken) == "" {
104-
return "", nil
103+
accessToken = strings.TrimSpace(accessToken)
104+
if accessToken == "" {
105+
return "", fmt.Errorf("antigravity userinfo: missing access token")
105106
}
106107
req, err := http.NewRequestWithContext(ctx, http.MethodGet, UserInfoEndpoint, nil)
107108
if err != nil {
108-
return "", err
109+
return "", fmt.Errorf("antigravity userinfo: create request: %w", err)
109110
}
110111
req.Header.Set("Authorization", "Bearer "+accessToken)
111112

112113
resp, errDo := o.httpClient.Do(req)
113114
if errDo != nil {
114-
return "", errDo
115+
return "", fmt.Errorf("antigravity userinfo: execute request: %w", errDo)
115116
}
116117
defer func() {
117118
if errClose := resp.Body.Close(); errClose != nil {
@@ -120,13 +121,25 @@ func (o *AntigravityAuth) FetchUserInfo(ctx context.Context, accessToken string)
120121
}()
121122

122123
if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
123-
return "", nil
124+
bodyBytes, errRead := io.ReadAll(io.LimitReader(resp.Body, 8<<10))
125+
if errRead != nil {
126+
return "", fmt.Errorf("antigravity userinfo: read response: %w", errRead)
127+
}
128+
body := strings.TrimSpace(string(bodyBytes))
129+
if body == "" {
130+
return "", fmt.Errorf("antigravity userinfo: request failed: status %d", resp.StatusCode)
131+
}
132+
return "", fmt.Errorf("antigravity userinfo: request failed: status %d: %s", resp.StatusCode, body)
124133
}
125134
var info userInfo
126135
if errDecode := json.NewDecoder(resp.Body).Decode(&info); errDecode != nil {
127-
return "", errDecode
136+
return "", fmt.Errorf("antigravity userinfo: decode response: %w", errDecode)
137+
}
138+
email := strings.TrimSpace(info.Email)
139+
if email == "" {
140+
return "", fmt.Errorf("antigravity userinfo: response missing email")
128141
}
129-
return info.Email, nil
142+
return email, nil
130143
}
131144

132145
// FetchProjectID retrieves the project ID for the authenticated user via loadCodeAssist

sdk/auth/antigravity.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,24 @@ waitForCallback:
153153
return nil, fmt.Errorf("antigravity: token exchange failed: %w", errToken)
154154
}
155155

156-
email := ""
157-
if tokenResp.AccessToken != "" {
158-
if fetchedEmail, errInfo := authSvc.FetchUserInfo(ctx, tokenResp.AccessToken); errInfo == nil && strings.TrimSpace(fetchedEmail) != "" {
159-
email = strings.TrimSpace(fetchedEmail)
160-
}
156+
accessToken := strings.TrimSpace(tokenResp.AccessToken)
157+
if accessToken == "" {
158+
return nil, fmt.Errorf("antigravity: token exchange returned empty access token")
159+
}
160+
161+
email, errInfo := authSvc.FetchUserInfo(ctx, accessToken)
162+
if errInfo != nil {
163+
return nil, fmt.Errorf("antigravity: fetch user info failed: %w", errInfo)
164+
}
165+
email = strings.TrimSpace(email)
166+
if email == "" {
167+
return nil, fmt.Errorf("antigravity: empty email returned from user info")
161168
}
162169

163170
// Fetch project ID via loadCodeAssist (same approach as Gemini CLI)
164171
projectID := ""
165-
if tokenResp.AccessToken != "" {
166-
fetchedProjectID, errProject := authSvc.FetchProjectID(ctx, tokenResp.AccessToken)
172+
if accessToken != "" {
173+
fetchedProjectID, errProject := authSvc.FetchProjectID(ctx, accessToken)
167174
if errProject != nil {
168175
log.Warnf("antigravity: failed to fetch project ID: %v", errProject)
169176
} else {

0 commit comments

Comments
 (0)