TestOAuth2BearerTokenPrecedence tests token extraction precedence per RFC 6750 nolint:tparallel,paralleltest // Subtests share a DB; run sequentially to avoid Windows DB cleanup flake.
(t *testing.T)
| 233 | // |
| 234 | //nolint:tparallel,paralleltest // Subtests share a DB; run sequentially to avoid Windows DB cleanup flake. |
| 235 | func TestOAuth2BearerTokenPrecedence(t *testing.T) { |
| 236 | t.Parallel() |
| 237 | |
| 238 | db, _ := dbtestutil.NewDB(t) |
| 239 | user := dbgen.User(t, db, database.User{}) |
| 240 | |
| 241 | // Create a valid API key |
| 242 | key, validToken := dbgen.APIKey(t, db, database.APIKey{ |
| 243 | UserID: user.ID, |
| 244 | ExpiresAt: dbtime.Now().Add(testutil.WaitLong), |
| 245 | }) |
| 246 | |
| 247 | middleware := httpmw.ExtractAPIKeyMW(httpmw.ExtractAPIKeyConfig{ |
| 248 | DB: db, |
| 249 | }) |
| 250 | |
| 251 | handler := middleware(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { |
| 252 | apiKey := httpmw.APIKey(r) |
| 253 | rw.Header().Set("X-Key-ID", apiKey.ID) |
| 254 | rw.WriteHeader(http.StatusOK) |
| 255 | })) |
| 256 | |
| 257 | t.Run("CookieTakesPrecedenceOverBearer", func(t *testing.T) { |
| 258 | req := httptest.NewRequest("GET", "/test", nil) |
| 259 | // Set both cookie and Bearer header - cookie should take precedence |
| 260 | req.AddCookie(&http.Cookie{ |
| 261 | Name: codersdk.SessionTokenCookie, |
| 262 | Value: validToken, |
| 263 | }) |
| 264 | req.Header.Set("Authorization", "Bearer invalid-token") |
| 265 | rec := httptest.NewRecorder() |
| 266 | handler.ServeHTTP(rec, req) |
| 267 | |
| 268 | require.Equal(t, http.StatusOK, rec.Code) |
| 269 | require.Equal(t, key.ID, rec.Header().Get("X-Key-ID")) |
| 270 | }) |
| 271 | |
| 272 | t.Run("QueryParameterTakesPrecedenceOverBearer", func(t *testing.T) { |
| 273 | // Set both query parameter and Bearer header - query should take precedence |
| 274 | u, _ := url.Parse("/test") |
| 275 | q := u.Query() |
| 276 | q.Set(codersdk.SessionTokenCookie, validToken) |
| 277 | u.RawQuery = q.Encode() |
| 278 | |
| 279 | req := httptest.NewRequest("GET", u.String(), nil) |
| 280 | req.Header.Set("Authorization", "Bearer invalid-token") |
| 281 | rec := httptest.NewRecorder() |
| 282 | handler.ServeHTTP(rec, req) |
| 283 | |
| 284 | require.Equal(t, http.StatusOK, rec.Code) |
| 285 | require.Equal(t, key.ID, rec.Header().Get("X-Key-ID")) |
| 286 | }) |
| 287 | |
| 288 | t.Run("BearerHeaderFallback", func(t *testing.T) { |
| 289 | // Only set Bearer header - should be used as fallback |
| 290 | req := httptest.NewRequest("GET", "/test", nil) |
| 291 | req.Header.Set("Authorization", "Bearer "+validToken) |
| 292 | rec := httptest.NewRecorder() |
nothing calls this directly
no test coverage detected