|
1 | 1 | package oidctesting |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "context" |
4 | 5 | "fmt" |
5 | 6 | "net/http" |
6 | 7 | "net/http/httptest" |
7 | | - "strings" |
8 | | - "sync" |
9 | 8 | "testing" |
10 | 9 |
|
11 | 10 | "github.com/stretchr/testify/require" |
@@ -313,65 +312,91 @@ func runTestErrorHandler(t *testing.T, testName string, tester tester) { |
313 | 312 | op := optest.NewTesting(t) |
314 | 313 | defer op.Close(t) |
315 | 314 |
|
316 | | - var info struct { |
317 | | - sync.RWMutex |
318 | | - description options.ErrorDescription |
319 | | - err error |
320 | | - } |
321 | | - |
322 | | - setInfo := func(description options.ErrorDescription, err error) { |
323 | | - info.Lock() |
324 | | - info.description = description |
325 | | - info.err = err |
326 | | - info.Unlock() |
327 | | - } |
328 | | - |
329 | | - getInfo := func() (description options.ErrorDescription, err error) { |
330 | | - info.RLock() |
331 | | - defer info.RUnlock() |
332 | | - return info.description, info.err |
333 | | - } |
334 | | - |
335 | | - errorHandler := func(description options.ErrorDescription, err error) { |
336 | | - t.Logf("Description: %s\tError: %v", description, err) |
337 | | - setInfo(description, err) |
338 | | - } |
339 | | - |
340 | | - opts := []options.Option{ |
341 | | - options.WithIssuer(op.GetURL(t)), |
342 | | - options.WithRequiredAudience("test-client"), |
343 | | - options.WithRequiredTokenType("JWT+AT"), |
344 | | - options.WithErrorHandler(errorHandler), |
| 315 | + cases := []struct { |
| 316 | + testDescription string |
| 317 | + errorHandler options.ErrorHandler |
| 318 | + expectStatusCode int |
| 319 | + expectHeaders map[string]string |
| 320 | + expectBodyContains []byte |
| 321 | + }{ |
| 322 | + { |
| 323 | + testDescription: "no output", |
| 324 | + errorHandler: func(ctx context.Context, oidcErr *options.OidcError) *options.Response { return nil }, |
| 325 | + expectStatusCode: http.StatusBadRequest, |
| 326 | + expectHeaders: map[string]string{}, |
| 327 | + expectBodyContains: []byte{}, |
| 328 | + }, |
| 329 | + { |
| 330 | + testDescription: "basic propagation", |
| 331 | + errorHandler: func(ctx context.Context, oidcErr *options.OidcError) *options.Response { |
| 332 | + return &options.Response{ |
| 333 | + StatusCode: 418, |
| 334 | + Headers: map[string]string{}, |
| 335 | + Body: []byte("badness"), |
| 336 | + } |
| 337 | + }, |
| 338 | + expectStatusCode: http.StatusTeapot, |
| 339 | + expectHeaders: map[string]string{ |
| 340 | + "Content-Type": "application/octet-stream", |
| 341 | + }, |
| 342 | + expectBodyContains: []byte("bad"), |
| 343 | + }, |
| 344 | + { |
| 345 | + testDescription: "additional header", |
| 346 | + errorHandler: func(ctx context.Context, oidcErr *options.OidcError) *options.Response { |
| 347 | + return &options.Response{ |
| 348 | + StatusCode: 418, |
| 349 | + Headers: map[string]string{"some": "header"}, |
| 350 | + Body: []byte("badness"), |
| 351 | + } |
| 352 | + }, |
| 353 | + expectStatusCode: http.StatusTeapot, |
| 354 | + expectHeaders: map[string]string{ |
| 355 | + "Some": "header", |
| 356 | + "Content-Type": "application/octet-stream", |
| 357 | + }, |
| 358 | + expectBodyContains: []byte{}, |
| 359 | + }, |
| 360 | + { |
| 361 | + testDescription: "content type", |
| 362 | + errorHandler: func(ctx context.Context, oidcErr *options.OidcError) *options.Response { |
| 363 | + return &options.Response{ |
| 364 | + StatusCode: 418, |
| 365 | + Headers: map[string]string{"content-type": "application/json"}, |
| 366 | + Body: []byte("{}"), |
| 367 | + } |
| 368 | + }, |
| 369 | + expectStatusCode: http.StatusTeapot, |
| 370 | + expectHeaders: map[string]string{ |
| 371 | + "Content-Type": "application/json", |
| 372 | + }, |
| 373 | + expectBodyContains: []byte("{}"), |
| 374 | + }, |
345 | 375 | } |
| 376 | + for i := range cases { |
| 377 | + c := cases[i] |
| 378 | + t.Logf("Test iteration %d: %s", i, c.testDescription) |
| 379 | + opts := []options.Option{ |
| 380 | + options.WithIssuer(op.GetURL(t)), |
| 381 | + options.WithRequiredAudience("test-client"), |
| 382 | + options.WithRequiredTokenType("JWT+AT"), |
| 383 | + options.WithErrorHandler(c.errorHandler), |
| 384 | + } |
346 | 385 |
|
347 | | - oidcHandler, err := oidc.NewHandler[TestClaims](nil, opts...) |
348 | | - require.NoError(t, err) |
349 | | - |
350 | | - handler := tester.ToHandlerFn(oidcHandler.ParseToken, opts...) |
351 | | - |
352 | | - // Test without token |
353 | | - reqNoAuth := httptest.NewRequest(http.MethodGet, "/", nil) |
354 | | - recNoAuth := httptest.NewRecorder() |
355 | | - handler.ServeHTTP(recNoAuth, reqNoAuth) |
356 | | - |
357 | | - require.Equal(t, http.StatusBadRequest, recNoAuth.Result().StatusCode) |
| 386 | + oidcHandler, err := oidc.NewHandler[TestClaims](nil, opts...) |
| 387 | + require.NoError(t, err) |
358 | 388 |
|
359 | | - d, e := getInfo() |
| 389 | + handler := tester.ToHandlerFn(oidcHandler.ParseToken, opts...) |
360 | 390 |
|
361 | | - if !strings.Contains(t.Name(), "OidcEchoJwt") { |
362 | | - require.Equal(t, options.GetTokenErrorDescription, d) |
363 | | - require.EqualError(t, e, "unable to extract token: Authorization header empty") |
| 391 | + req := httptest.NewRequest(http.MethodGet, "/", nil) |
| 392 | + res := httptest.NewRecorder() |
| 393 | + handler.ServeHTTP(res, req) |
| 394 | + require.Equal(t, c.expectStatusCode, res.Result().StatusCode) |
| 395 | + for k, v := range c.expectHeaders { |
| 396 | + require.Equal(t, []string{v}, res.Result().Header[k]) |
| 397 | + } |
| 398 | + require.Subset(t, res.Body.Bytes(), c.expectBodyContains) |
364 | 399 | } |
365 | | - |
366 | | - // Test with fake token |
367 | | - token := op.GetToken(t) |
368 | | - token.AccessToken = "foobar" |
369 | | - testHttpWithAuthenticationFailure(t, token, handler) |
370 | | - |
371 | | - d, e = getInfo() |
372 | | - |
373 | | - require.Equal(t, options.ParseTokenErrorDescription, d) |
374 | | - require.EqualError(t, e, "unable to parse token signature: invalid compact serialization format: invalid number of segments") |
375 | 400 | }) |
376 | 401 | } |
377 | 402 |
|
|
0 commit comments