Skip to content

Commit 6313693

Browse files
authored
Merge pull request #2 from tstromberg/main
Improve compatibility w/ official library
2 parents 0fbc86f + 3671259 commit 6313693

File tree

7 files changed

+7084
-70
lines changed

7 files changed

+7084
-70
lines changed

auth/auth.go

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"io"
1313
"log/slog"
1414
"net/http"
15+
"net/url"
1516
"os"
1617
"strings"
1718
"time"
@@ -34,10 +35,12 @@ var (
3435

3536
// SetMetadataURL sets a custom metadata server URL for testing.
3637
// Returns a function that restores the original URL.
37-
func SetMetadataURL(url string) func() {
38+
// WARNING: This function should only be called in test code.
39+
// Set DS9_ALLOW_TEST_OVERRIDES=true to enable in non-test environments.
40+
func SetMetadataURL(urlStr string) func() {
3841
old := metadataURL
3942
oldTestMode := isTestMode
40-
metadataURL = url
43+
metadataURL = urlStr
4144
isTestMode = true // Enable test mode to skip ADC
4245
return func() {
4346
metadataURL = old
@@ -107,10 +110,14 @@ func accessTokenFromADC(ctx context.Context) (string, error) {
107110
func exchangeRefreshToken(ctx context.Context, clientID, clientSecret, refreshToken string) (string, error) {
108111
tokenURL := "https://oauth2.googleapis.com/token" //nolint:gosec // This is Google's OAuth2 token endpoint, not a hardcoded credential
109112

110-
reqBody := fmt.Sprintf(
111-
"client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token",
112-
clientID, clientSecret, refreshToken,
113-
)
113+
// Use url.Values for proper URL encoding to prevent parameter injection
114+
form := url.Values{
115+
"client_id": {clientID},
116+
"client_secret": {clientSecret},
117+
"refresh_token": {refreshToken},
118+
"grant_type": {"refresh_token"},
119+
}
120+
reqBody := form.Encode()
114121

115122
req, err := http.NewRequestWithContext(ctx, http.MethodPost, tokenURL, strings.NewReader(reqBody))
116123
if err != nil {
@@ -133,7 +140,9 @@ func exchangeRefreshToken(ctx context.Context, clientID, clientSecret, refreshTo
133140
if readErr != nil {
134141
return "", fmt.Errorf("token exchange returned %d", resp.StatusCode)
135142
}
136-
return "", fmt.Errorf("token exchange returned %d: %s", resp.StatusCode, string(body))
143+
// Log full error details but return sanitized message to prevent information leakage
144+
slog.ErrorContext(ctx, "OAuth token exchange failed", "status", resp.StatusCode, "response", string(body))
145+
return "", fmt.Errorf("token exchange returned %d", resp.StatusCode)
137146
}
138147

139148
body, err := io.ReadAll(io.LimitReader(resp.Body, maxBodySize))
@@ -156,9 +165,9 @@ func exchangeRefreshToken(ctx context.Context, clientID, clientSecret, refreshTo
156165
// accessTokenFromMetadata retrieves an access token from the GCP metadata server.
157166
// This is used when running on GCP (GCE, GKE, Cloud Run, etc.).
158167
func accessTokenFromMetadata(ctx context.Context) (string, error) {
159-
url := metadataURL + "/instance/service-accounts/default/token"
168+
reqURL := metadataURL + "/instance/service-accounts/default/token"
160169

161-
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, http.NoBody)
170+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, http.NoBody)
162171
if err != nil {
163172
return "", err
164173
}
@@ -197,9 +206,9 @@ func accessTokenFromMetadata(ctx context.Context) (string, error) {
197206

198207
// ProjectID retrieves the project ID from the GCP metadata server.
199208
func ProjectID(ctx context.Context) (string, error) {
200-
url := metadataURL + "/project/project-id"
209+
reqURL := metadataURL + "/project/project-id"
201210

202-
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, http.NoBody)
211+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, reqURL, http.NoBody)
203212
if err != nil {
204213
return "", err
205214
}

0 commit comments

Comments
 (0)