github.com/kyma-incubator/compass/components/director@v0.0.0-20230623144113-d764f56ff805/pkg/auth-middleware/middleware_test.go (about) 1 package authmiddleware 2 3 import ( 4 "bytes" 5 "context" 6 "encoding/json" 7 "fmt" 8 "io" 9 "net/http" 10 "net/http/httptest" 11 "strings" 12 "testing" 13 14 "github.com/kyma-incubator/compass/components/director/internal/authenticator" 15 "github.com/kyma-incubator/compass/components/director/internal/authenticator/claims" 16 "github.com/kyma-incubator/compass/components/director/pkg/auth-middleware/automock" 17 18 "github.com/kyma-incubator/compass/components/director/internal/domain/scenariogroups" 19 20 "github.com/kyma-incubator/compass/components/director/internal/nsadapter/httputil" 21 22 "github.com/stretchr/testify/mock" 23 24 "github.com/99designs/gqlgen/graphql" 25 "github.com/kyma-incubator/compass/components/director/internal/domain/client" 26 "github.com/vektah/gqlparser/v2/gqlerror" 27 28 "github.com/kyma-incubator/compass/components/director/pkg/apperrors" 29 30 "github.com/kyma-incubator/compass/components/director/pkg/consumer" 31 32 "github.com/lestrrat-go/jwx/jwk" 33 34 "github.com/kyma-incubator/compass/components/director/pkg/scope" 35 36 "github.com/form3tech-oss/jwt-go" 37 "github.com/kyma-incubator/compass/components/director/internal/domain/tenant" 38 39 "github.com/stretchr/testify/assert" 40 41 "github.com/stretchr/testify/require" 42 ) 43 44 const ( 45 ClientIDHeaderKey = "client_user" 46 ScenarioGroupsKey = "scenario_groups" 47 48 defaultTenant = "af9f84a9-1d3a-4d9f-ae0c-94f883b33b6e" 49 defaultExternalTenant = "bf9f84a9-1d3a-4d9f-ae0c-94f883b33b6e" 50 PrivateJWKSURL = "file://testdata/jwks-private.json" 51 PrivateJWKS2URL = "file://testdata/jwks-private2.json" 52 PrivateJWKS3URL = "file://testdata/jwks-private3.json" 53 PublicJWKSURL = "file://testdata/jwks-public.json" 54 PublicJWKS2URL = "file://testdata/jwks-public2.json" 55 PublicJWKS3URL = "file://testdata/jwks-public3.json" 56 fakeJWKSURL = "file://testdata/invalid.json" 57 ) 58 59 type mockRoundTripper struct{} 60 61 func (rt *mockRoundTripper) RoundTrip(*http.Request) (*http.Response, error) { 62 return &http.Response{ 63 StatusCode: http.StatusFound, 64 Header: map[string][]string{ 65 "Location": {"somewhere.else.gone"}, 66 }, 67 Body: io.NopCloser(bytes.NewBufferString("")), 68 }, nil 69 } 70 71 var httpClientWithoutRedirectsWithMockTransport = &http.Client{ 72 Transport: &mockRoundTripper{}, 73 CheckRedirect: func(req *http.Request, via []*http.Request) error { 74 return http.ErrUseLastResponse 75 }, 76 } 77 78 var httpClientWithoutRedirects = &http.Client{ 79 CheckRedirect: func(req *http.Request, via []*http.Request) error { 80 return http.ErrUseLastResponse 81 }, 82 } 83 84 func TestAuthenticator_SynchronizeJWKS(t *testing.T) { 85 t.Run("Success", func(t *testing.T) { 86 // GIVEN 87 auth := New(httpClientWithoutRedirects, PublicJWKSURL, true, ClientIDHeaderKey, claimsValidatorMock()) 88 // WHEN 89 err := auth.SynchronizeJWKS(context.TODO()) 90 91 // THEN 92 require.NoError(t, err) 93 }) 94 95 t.Run("Error when can't fetch JWKS", func(t *testing.T) { 96 // GIVEN 97 authFake := New(httpClientWithoutRedirects, fakeJWKSURL, true, ClientIDHeaderKey, nil) 98 99 // WHEN 100 err := authFake.SynchronizeJWKS(context.TODO()) 101 102 // THEN 103 require.Error(t, err) 104 assert.EqualError(t, err, fmt.Sprintf("while fetching JWKS from endpoint %s: failed to unmarshal JWK set: invalid character '<' looking for beginning of value", fakeJWKSURL)) 105 }) 106 } 107 108 func TestAuthenticator_Handler(t *testing.T) { 109 // GIVEN 110 scopes := "scope-a scope-b" 111 112 privateJWKS, err := authenticator.FetchJWK(context.TODO(), PrivateJWKSURL) 113 require.NoError(t, err) 114 115 privateJWKS2, err := authenticator.FetchJWK(context.TODO(), PrivateJWKS2URL) 116 require.NoError(t, err) 117 118 privateJWKS3, err := authenticator.FetchJWK(context.TODO(), PrivateJWKS3URL) 119 require.NoError(t, err) 120 121 t.Run("http client configured without redirects", func(t *testing.T) { 122 // WHEN 123 jwks, err := authenticator.FetchJWK(context.TODO(), "http://idonotexist.gone", jwk.WithHTTPClient(httpClientWithoutRedirectsWithMockTransport)) 124 125 // THEN 126 require.Nil(t, jwks) 127 require.Contains(t, err.Error(), "failed to fetch remote JWK (status = 302)") // the existing error is due to FetchJWK function logic and checking if response status code is different thann 200, in this case it's 302. But redirect was not performed 128 }) 129 130 t.Run("Success - token with signing method", func(t *testing.T) { 131 // GIVEN 132 middleware := createMiddleware(t, false, claimsValidatorMock()) 133 handler := testHandler(t, defaultTenant, scopes) 134 rr := httptest.NewRecorder() 135 req := fixEmptyRequest(t) 136 key, ok := privateJWKS.Get(0) 137 assert.True(t, ok) 138 139 keyID := key.KeyID() 140 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 141 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 142 143 // WHEN 144 middleware(handler).ServeHTTP(rr, req) 145 146 // THEN 147 assert.Equal(t, "OK", rr.Body.String()) 148 assert.Equal(t, http.StatusOK, rr.Code) 149 }) 150 151 t.Run("Success - token with no signing method when it's allowed", func(t *testing.T) { 152 // GIVEN 153 middleware := createMiddleware(t, true, claimsValidatorMock()) 154 handler := testHandler(t, defaultTenant, scopes) 155 rr := httptest.NewRecorder() 156 req := fixEmptyRequest(t) 157 158 token := createNotSingedToken(t, defaultTenant, scopes) 159 require.NoError(t, err) 160 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 161 162 // WHEN 163 middleware(handler).ServeHTTP(rr, req) 164 165 // THEN 166 assert.Equal(t, "OK", rr.Body.String()) 167 assert.Equal(t, http.StatusOK, rr.Code) 168 }) 169 170 t.Run("Success - with client user provided", func(t *testing.T) { 171 clientUser := "foo" 172 // GIVEN 173 middleware := createMiddleware(t, false, claimsValidatorMock()) 174 handler := testHandlerWithClientUser(t, defaultTenant, clientUser, scopes) 175 rr := httptest.NewRecorder() 176 req := fixEmptyRequest(t) 177 key, ok := privateJWKS.Get(0) 178 assert.True(t, ok) 179 180 keyID := key.KeyID() 181 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 182 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 183 req.Header.Add(ClientIDHeaderKey, clientUser) 184 185 // WHEN 186 middleware(handler).ServeHTTP(rr, req) 187 188 // THEN 189 assert.Equal(t, "OK", rr.Body.String()) 190 assert.Equal(t, http.StatusOK, rr.Code) 191 }) 192 193 t.Run("Success - with one scenario group provided", func(t *testing.T) { 194 scenarioGroups := []string{"FOO"} 195 scenarioGroupsHeaderValue := "foo" 196 // GIVEN 197 middleware := createMiddleware(t, false, claimsValidatorMock()) 198 handler := testHandlerWithScenarioGroups(t, defaultTenant, scenarioGroups, scopes) 199 rr := httptest.NewRecorder() 200 req := fixEmptyRequest(t) 201 key, ok := privateJWKS.Get(0) 202 assert.True(t, ok) 203 204 keyID := key.KeyID() 205 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 206 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 207 req.Header.Add(ScenarioGroupsKey, scenarioGroupsHeaderValue) 208 209 // WHEN 210 middleware(handler).ServeHTTP(rr, req) 211 212 // THEN 213 assert.Equal(t, "OK", rr.Body.String()) 214 assert.Equal(t, http.StatusOK, rr.Code) 215 }) 216 217 t.Run("Success - with two scenario groups provided", func(t *testing.T) { 218 scenarioGroups := []string{"FOO", "BAR"} 219 scenarioGroupsHeaderValue := "fOo,Bar" 220 // GIVEN 221 middleware := createMiddleware(t, false, claimsValidatorMock()) 222 handler := testHandlerWithScenarioGroups(t, defaultTenant, scenarioGroups, scopes) 223 rr := httptest.NewRecorder() 224 req := fixEmptyRequest(t) 225 key, ok := privateJWKS.Get(0) 226 assert.True(t, ok) 227 228 keyID := key.KeyID() 229 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 230 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 231 req.Header.Add(ScenarioGroupsKey, scenarioGroupsHeaderValue) 232 233 // WHEN 234 middleware(handler).ServeHTTP(rr, req) 235 236 // THEN 237 assert.Equal(t, "OK", rr.Body.String()) 238 assert.Equal(t, http.StatusOK, rr.Code) 239 }) 240 241 t.Run("Success - when tenant is empty", func(t *testing.T) { 242 // GIVEN 243 tnt := "" 244 middleware := createMiddleware(t, true, claimsValidatorMock()) 245 handler := testHandler(t, tnt, scopes) 246 rr := httptest.NewRecorder() 247 req := fixEmptyRequest(t) 248 249 token := createNotSingedToken(t, tnt, scopes) 250 require.NoError(t, err) 251 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 252 253 // WHEN 254 middleware(handler).ServeHTTP(rr, req) 255 256 // THEN 257 assert.Equal(t, "OK", rr.Body.String()) 258 assert.Equal(t, http.StatusOK, rr.Code) 259 }) 260 261 t.Run("Success - retry parsing token with synchronizing JWKS", func(t *testing.T) { 262 // GIVEN 263 auth := New(httpClientWithoutRedirects, PublicJWKSURL, false, ClientIDHeaderKey, claimsValidatorMock()) 264 err := auth.SynchronizeJWKS(context.TODO()) 265 require.NoError(t, err) 266 267 auth.SetJWKSEndpoint(PublicJWKS2URL) 268 269 middleware := auth.Handler() 270 271 handler := testHandler(t, defaultTenant, scopes) 272 rr := httptest.NewRecorder() 273 req := fixEmptyRequest(t) 274 275 key, ok := privateJWKS2.Get(0) 276 assert.True(t, ok) 277 278 keyID := key.KeyID() 279 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 280 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 281 282 // WHEN 283 middleware(handler).ServeHTTP(rr, req) 284 285 // THEN 286 assert.Equal(t, "OK", rr.Body.String()) 287 assert.Equal(t, http.StatusOK, rr.Code) 288 }) 289 290 t.Run("Success - when we have more than one JWKS and use the first key", func(t *testing.T) { 291 // GIVEN 292 auth := New(httpClientWithoutRedirects, PublicJWKS3URL, false, ClientIDHeaderKey, claimsValidatorMock()) 293 err := auth.SynchronizeJWKS(context.TODO()) 294 require.NoError(t, err) 295 296 middleware := auth.Handler() 297 298 handler := testHandler(t, defaultTenant, scopes) 299 rr := httptest.NewRecorder() 300 req := fixEmptyRequest(t) 301 302 key, ok := privateJWKS3.Get(0) 303 assert.True(t, ok) 304 305 keyID := key.KeyID() 306 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 307 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 308 309 // WHEN 310 middleware(handler).ServeHTTP(rr, req) 311 312 // THEN 313 assert.Equal(t, "OK", rr.Body.String()) 314 assert.Equal(t, http.StatusOK, rr.Code) 315 }) 316 317 t.Run("Success - when we have more than one JWKS and use the second key", func(t *testing.T) { 318 // GIVEN 319 auth := New(httpClientWithoutRedirects, PublicJWKS3URL, false, ClientIDHeaderKey, claimsValidatorMock()) 320 err := auth.SynchronizeJWKS(context.TODO()) 321 require.NoError(t, err) 322 323 middleware := auth.Handler() 324 325 handler := testHandler(t, defaultTenant, scopes) 326 rr := httptest.NewRecorder() 327 req := fixEmptyRequest(t) 328 329 key, ok := privateJWKS3.Get(1) 330 assert.True(t, ok) 331 332 keyID := key.KeyID() 333 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 334 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 335 336 // WHEN 337 middleware(handler).ServeHTTP(rr, req) 338 339 // THEN 340 assert.Equal(t, "OK", rr.Body.String()) 341 assert.Equal(t, http.StatusOK, rr.Code) 342 }) 343 344 t.Run("Error - retry parsing token with failing synchronizing JWKS", func(t *testing.T) { 345 // GIVEN 346 auth := New(httpClientWithoutRedirects, PublicJWKSURL, false, ClientIDHeaderKey, claimsValidatorMock()) 347 err := auth.SynchronizeJWKS(context.TODO()) 348 require.NoError(t, err) 349 350 auth.SetJWKSEndpoint("invalid.url.scheme") 351 352 middleware := auth.Handler() 353 354 handler := testHandler(t, defaultTenant, scopes) 355 rr := httptest.NewRecorder() 356 req := fixEmptyRequest(t) 357 358 key, ok := privateJWKS2.Get(0) 359 assert.True(t, ok) 360 361 keyID := key.KeyID() 362 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 363 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 364 365 // WHEN 366 middleware(handler).ServeHTTP(rr, req) 367 368 // THEN 369 var response graphql.Response 370 err = json.Unmarshal(rr.Body.Bytes(), &response) 371 require.NoError(t, err) 372 373 expected := fixGraphqlResponse("Internal Server Error: while synchronizing JWKS during parsing token: while fetching JWKS from endpoint invalid.url.scheme: invalid url scheme ", apperrors.InternalError) 374 assertGraphqlResponse(t, expected, response) 375 assert.Equal(t, http.StatusUnauthorized, rr.Code) 376 }) 377 378 t.Run("Error - token with no signing method when it's not allowed", func(t *testing.T) { 379 // GIVEN 380 middleware := createMiddleware(t, false, claimsValidatorMock()) 381 handler := testHandler(t, defaultTenant, scopes) 382 383 rr := httptest.NewRecorder() 384 req := fixEmptyRequest(t) 385 386 token := createNotSingedToken(t, defaultTenant, scopes) 387 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 388 389 // WHEN 390 middleware(handler).ServeHTTP(rr, req) 391 392 // THEN 393 assert.Equal(t, http.StatusUnauthorized, rr.Code) 394 395 var response graphql.Response 396 err = json.Unmarshal(rr.Body.Bytes(), &response) 397 require.NoError(t, err) 398 399 expected := fixGraphqlResponse("Unauthorized [reason=unexpected signing method: none]", apperrors.Unauthorized) 400 assertGraphqlResponse(t, expected, response) 401 }) 402 403 t.Run("Error - can't parse token", func(t *testing.T) { 404 // GIVEN 405 middleware := createMiddleware(t, false, claimsValidatorMock()) 406 handler := testHandler(t, defaultTenant, scopes) 407 rr := httptest.NewRecorder() 408 req := fixEmptyRequest(t) 409 410 req.Header.Add(AuthorizationHeaderKey, "Bearer fake-token") 411 412 // WHEN 413 middleware(handler).ServeHTTP(rr, req) 414 415 // THEN 416 assert.Equal(t, http.StatusUnauthorized, rr.Code) 417 418 var response graphql.Response 419 err = json.Unmarshal(rr.Body.Bytes(), &response) 420 require.NoError(t, err) 421 422 expected := fixGraphqlResponse("Unauthorized [reason=token contains an invalid number of segments]", apperrors.Unauthorized) 423 assertGraphqlResponse(t, expected, response) 424 }) 425 426 t.Run("Error - invalid header and bearer token", func(t *testing.T) { 427 // GIVEN 428 middleware := createMiddleware(t, false, claimsValidatorMock()) 429 handler := testHandler(t, defaultTenant, scopes) 430 rr := httptest.NewRecorder() 431 req := fixEmptyRequest(t) 432 433 req.Header.Add("invalidHeader", "Bearer fake-token") 434 435 // WHEN 436 middleware(handler).ServeHTTP(rr, req) 437 438 // THEN 439 assert.Equal(t, http.StatusBadRequest, rr.Code) 440 441 var response graphql.Response 442 err = json.Unmarshal(rr.Body.Bytes(), &response) 443 require.NoError(t, err) 444 445 expected := fixGraphqlResponse("Unauthorized [reason=invalid bearer token]", apperrors.Unauthorized) 446 assertGraphqlResponse(t, expected, response) 447 }) 448 449 t.Run("Error - token without signing key", func(t *testing.T) { 450 // GIVEN 451 middleware := createMiddleware(t, false, claimsValidatorMock()) 452 handler := testHandler(t, defaultTenant, scopes) 453 454 rr := httptest.NewRecorder() 455 req := fixEmptyRequest(t) 456 457 key, ok := privateJWKS2.Get(0) 458 assert.True(t, ok) 459 460 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, nil, false) 461 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 462 463 // WHEN 464 middleware(handler).ServeHTTP(rr, req) 465 466 // THEN 467 assert.Equal(t, http.StatusUnauthorized, rr.Code) 468 469 var response graphql.Response 470 err = json.Unmarshal(rr.Body.Bytes(), &response) 471 require.NoError(t, err) 472 473 expected := fixGraphqlResponse("Unauthorized [reason=while getting the key ID: Internal Server Error: unable to find the key ID in the token]", apperrors.Unauthorized) 474 assertGraphqlResponse(t, expected, response) 475 }) 476 477 t.Run("Error - after successful parsing claims are not valid", func(t *testing.T) { 478 // GIVEN 479 v := &automock.ClaimsValidator{} 480 v.On("Validate", mock.Anything, mock.Anything).Return(apperrors.NewTenantNotFoundError("externalTenantName")) 481 middleware := createMiddleware(t, false, v) 482 handler := testHandler(t, "", scopes) 483 484 rr := httptest.NewRecorder() 485 req := fixEmptyRequest(t) 486 487 key, ok := privateJWKS.Get(0) 488 assert.True(t, ok) 489 490 keyID := key.KeyID() 491 token := createTokenWithSigningMethod(t, "", scopes, key, &keyID, true) 492 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 493 494 // WHEN 495 middleware(handler).ServeHTTP(rr, req) 496 497 // THEN 498 assert.Equal(t, http.StatusBadRequest, rr.Code) 499 500 var response graphql.Response 501 err = json.Unmarshal(rr.Body.Bytes(), &response) 502 require.NoError(t, err) 503 504 expected := fixGraphqlResponse("Tenant not found [externalTenant=externalTenantName]", apperrors.TenantNotFound) 505 assertGraphqlResponse(t, expected, response) 506 }) 507 508 t.Run("Error - after successful parsing claims there are no scopes", func(t *testing.T) { 509 // GIVEN 510 requiredScopes := []string{"wanted-scope"} 511 auth := New(httpClientWithoutRedirects, PublicJWKSURL, false, ClientIDHeaderKey, claims.NewScopesValidator(requiredScopes)) 512 err := auth.SynchronizeJWKS(context.TODO()) 513 require.NoError(t, err) 514 middleware := auth.Handler() 515 handler := testHandler(t, "", scopes) 516 517 rr := httptest.NewRecorder() 518 req := fixEmptyRequest(t) 519 520 key, ok := privateJWKS.Get(0) 521 assert.True(t, ok) 522 523 keyID := key.KeyID() 524 token := createTokenWithSigningMethod(t, "", scopes, key, &keyID, true) 525 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 526 527 // WHEN 528 middleware(handler).ServeHTTP(rr, req) 529 530 // THEN 531 assert.Equal(t, http.StatusUnauthorized, rr.Code) 532 533 var response graphql.Response 534 err = json.Unmarshal(rr.Body.Bytes(), &response) 535 require.NoError(t, err) 536 537 expected := fixGraphqlResponse(fmt.Sprintf("Unauthorized [reason=Not all required scopes %q were found in claim with scopes %q]", requiredScopes, scopes), apperrors.Unauthorized) 538 assertGraphqlResponse(t, expected, response) 539 }) 540 541 t.Run("Error - Token signed with different key", func(t *testing.T) { 542 // GIVEN 543 middleware := createMiddleware(t, false, claimsValidatorMock()) 544 handler := testHandler(t, defaultTenant, scopes) 545 546 rr := httptest.NewRecorder() 547 req := fixEmptyRequest(t) 548 549 oldKey, ok := privateJWKS.Get(0) 550 assert.True(t, ok) 551 552 newKey, ok := privateJWKS2.Get(0) 553 assert.True(t, ok) 554 555 oldKeyID := oldKey.KeyID() 556 token := createTokenWithSigningMethod(t, defaultTenant, scopes, newKey, &oldKeyID, true) 557 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 558 559 // WHEN 560 middleware(handler).ServeHTTP(rr, req) 561 562 // THEN 563 assert.Equal(t, http.StatusUnauthorized, rr.Code) 564 var response graphql.Response 565 err = json.Unmarshal(rr.Body.Bytes(), &response) 566 require.NoError(t, err) 567 568 expected := fixGraphqlResponse("Unauthorized [reason=crypto/rsa: verification error]", apperrors.Unauthorized) 569 assertGraphqlResponse(t, expected, response) 570 }) 571 } 572 573 func TestAuthenticator_KymaAdapterHandler(t *testing.T) { 574 // GIVEN 575 scopes := "scope-a scope-b" 576 577 privateJWKS, err := authenticator.FetchJWK(context.TODO(), PrivateJWKSURL) 578 require.NoError(t, err) 579 580 privateJWKS2, err := authenticator.FetchJWK(context.TODO(), PrivateJWKS2URL) 581 require.NoError(t, err) 582 583 privateJWKS3, err := authenticator.FetchJWK(context.TODO(), PrivateJWKS3URL) 584 require.NoError(t, err) 585 586 t.Run("http client configured without redirects", func(t *testing.T) { 587 // WHEN 588 jwks, err := authenticator.FetchJWK(context.TODO(), "http://idonotexist.gone", jwk.WithHTTPClient(httpClientWithoutRedirectsWithMockTransport)) 589 590 // THEN 591 require.Nil(t, jwks) 592 require.Contains(t, err.Error(), "failed to fetch remote JWK (status = 302)") // the existing error is due to FetchJWK function logic and checking if response status code is different thann 200, in this case it's 302. But redirect was not performed 593 }) 594 595 t.Run("Success - token with signing method", func(t *testing.T) { 596 // GIVEN 597 middleware := createMiddleware(t, false, claimsValidatorMock()) 598 handler := testHandler(t, defaultTenant, scopes) 599 rr := httptest.NewRecorder() 600 req := fixEmptyRequest(t) 601 key, ok := privateJWKS.Get(0) 602 assert.True(t, ok) 603 604 keyID := key.KeyID() 605 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 606 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 607 608 // WHEN 609 middleware(handler).ServeHTTP(rr, req) 610 611 // THEN 612 assert.Equal(t, "OK", rr.Body.String()) 613 assert.Equal(t, http.StatusOK, rr.Code) 614 }) 615 616 t.Run("Success - token with no signing method when it's allowed", func(t *testing.T) { 617 // GIVEN 618 middleware := createMiddleware(t, true, claimsValidatorMock()) 619 handler := testHandler(t, defaultTenant, scopes) 620 rr := httptest.NewRecorder() 621 req := fixEmptyRequest(t) 622 623 token := createNotSingedToken(t, defaultTenant, scopes) 624 require.NoError(t, err) 625 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 626 627 // WHEN 628 middleware(handler).ServeHTTP(rr, req) 629 630 // THEN 631 assert.Equal(t, "OK", rr.Body.String()) 632 assert.Equal(t, http.StatusOK, rr.Code) 633 }) 634 635 t.Run("Success - with client user provided", func(t *testing.T) { 636 clientUser := "foo" 637 // GIVEN 638 middleware := createMiddleware(t, false, claimsValidatorMock()) 639 handler := testHandlerWithClientUser(t, defaultTenant, clientUser, scopes) 640 rr := httptest.NewRecorder() 641 req := fixEmptyRequest(t) 642 key, ok := privateJWKS.Get(0) 643 assert.True(t, ok) 644 645 keyID := key.KeyID() 646 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 647 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 648 req.Header.Add(ClientIDHeaderKey, clientUser) 649 650 // WHEN 651 middleware(handler).ServeHTTP(rr, req) 652 653 // THEN 654 assert.Equal(t, "OK", rr.Body.String()) 655 assert.Equal(t, http.StatusOK, rr.Code) 656 }) 657 658 t.Run("Success - with one scenario group provided", func(t *testing.T) { 659 scenarioGroups := []string{"FOO"} 660 scenarioGroupsHeaderValue := "foo" 661 // GIVEN 662 middleware := createMiddleware(t, false, claimsValidatorMock()) 663 handler := testHandlerWithScenarioGroups(t, defaultTenant, scenarioGroups, scopes) 664 rr := httptest.NewRecorder() 665 req := fixEmptyRequest(t) 666 key, ok := privateJWKS.Get(0) 667 assert.True(t, ok) 668 669 keyID := key.KeyID() 670 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 671 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 672 req.Header.Add(ScenarioGroupsKey, scenarioGroupsHeaderValue) 673 674 // WHEN 675 middleware(handler).ServeHTTP(rr, req) 676 677 // THEN 678 assert.Equal(t, "OK", rr.Body.String()) 679 assert.Equal(t, http.StatusOK, rr.Code) 680 }) 681 682 t.Run("Success - with two scenario groups provided", func(t *testing.T) { 683 scenarioGroups := []string{"FOO", "BAR"} 684 scenarioGroupsHeaderValue := "fOo,Bar" 685 // GIVEN 686 middleware := createMiddleware(t, false, claimsValidatorMock()) 687 handler := testHandlerWithScenarioGroups(t, defaultTenant, scenarioGroups, scopes) 688 rr := httptest.NewRecorder() 689 req := fixEmptyRequest(t) 690 key, ok := privateJWKS.Get(0) 691 assert.True(t, ok) 692 693 keyID := key.KeyID() 694 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 695 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 696 req.Header.Add(ScenarioGroupsKey, scenarioGroupsHeaderValue) 697 698 // WHEN 699 middleware(handler).ServeHTTP(rr, req) 700 701 // THEN 702 assert.Equal(t, "OK", rr.Body.String()) 703 assert.Equal(t, http.StatusOK, rr.Code) 704 }) 705 706 t.Run("Success - when tenant is empty", func(t *testing.T) { 707 // GIVEN 708 tnt := "" 709 middleware := createMiddleware(t, true, claimsValidatorMock()) 710 handler := testHandler(t, tnt, scopes) 711 rr := httptest.NewRecorder() 712 req := fixEmptyRequest(t) 713 714 token := createNotSingedToken(t, tnt, scopes) 715 require.NoError(t, err) 716 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 717 718 // WHEN 719 middleware(handler).ServeHTTP(rr, req) 720 721 // THEN 722 assert.Equal(t, "OK", rr.Body.String()) 723 assert.Equal(t, http.StatusOK, rr.Code) 724 }) 725 726 t.Run("Success - retry parsing token with synchronizing JWKS", func(t *testing.T) { 727 // GIVEN 728 auth := New(httpClientWithoutRedirects, PublicJWKSURL, false, ClientIDHeaderKey, claimsValidatorMock()) 729 err := auth.SynchronizeJWKS(context.TODO()) 730 require.NoError(t, err) 731 732 auth.SetJWKSEndpoint(PublicJWKS2URL) 733 734 middleware := auth.KymaAdapterHandler() 735 736 handler := testHandlerWithExternalTenant(t, defaultExternalTenant, scopes) 737 rr := httptest.NewRecorder() 738 req := fixEmptyRequest(t) 739 740 key, ok := privateJWKS2.Get(0) 741 assert.True(t, ok) 742 743 keyID := key.KeyID() 744 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 745 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 746 747 // WHEN 748 middleware(handler).ServeHTTP(rr, req) 749 750 // THEN 751 assert.Equal(t, "OK", rr.Body.String()) 752 assert.Equal(t, http.StatusOK, rr.Code) 753 }) 754 755 t.Run("Success - when we have more than one JWKS and use the first key", func(t *testing.T) { 756 // GIVEN 757 auth := New(httpClientWithoutRedirects, PublicJWKS3URL, false, ClientIDHeaderKey, claimsValidatorMock()) 758 err := auth.SynchronizeJWKS(context.TODO()) 759 require.NoError(t, err) 760 761 middleware := auth.KymaAdapterHandler() 762 763 handler := testHandlerWithExternalTenant(t, defaultExternalTenant, scopes) 764 rr := httptest.NewRecorder() 765 req := fixEmptyRequest(t) 766 767 key, ok := privateJWKS3.Get(0) 768 assert.True(t, ok) 769 770 keyID := key.KeyID() 771 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 772 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 773 774 // WHEN 775 middleware(handler).ServeHTTP(rr, req) 776 777 // THEN 778 assert.Equal(t, "OK", rr.Body.String()) 779 assert.Equal(t, http.StatusOK, rr.Code) 780 }) 781 782 t.Run("Success - when we have more than one JWKS and use the second key", func(t *testing.T) { 783 // GIVEN 784 auth := New(httpClientWithoutRedirects, PublicJWKS3URL, false, ClientIDHeaderKey, claimsValidatorMock()) 785 err := auth.SynchronizeJWKS(context.TODO()) 786 require.NoError(t, err) 787 788 middleware := auth.KymaAdapterHandler() 789 790 handler := testHandlerWithExternalTenant(t, defaultExternalTenant, scopes) 791 rr := httptest.NewRecorder() 792 req := fixEmptyRequest(t) 793 794 key, ok := privateJWKS3.Get(1) 795 assert.True(t, ok) 796 797 keyID := key.KeyID() 798 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 799 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 800 801 // WHEN 802 middleware(handler).ServeHTTP(rr, req) 803 804 // THEN 805 assert.Equal(t, "OK", rr.Body.String()) 806 assert.Equal(t, http.StatusOK, rr.Code) 807 }) 808 809 t.Run("Error - retry parsing token with failing synchronizing JWKS", func(t *testing.T) { 810 // GIVEN 811 auth := New(httpClientWithoutRedirects, PublicJWKSURL, false, ClientIDHeaderKey, claimsValidatorMock()) 812 err := auth.SynchronizeJWKS(context.TODO()) 813 require.NoError(t, err) 814 815 auth.SetJWKSEndpoint("invalid.url.scheme") 816 817 middleware := auth.KymaAdapterHandler() 818 819 handler := testHandler(t, defaultTenant, scopes) 820 rr := httptest.NewRecorder() 821 req := fixEmptyRequest(t) 822 823 key, ok := privateJWKS2.Get(0) 824 assert.True(t, ok) 825 826 keyID := key.KeyID() 827 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 828 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 829 830 // WHEN 831 middleware(handler).ServeHTTP(rr, req) 832 833 // THEN 834 var response graphql.Response 835 err = json.Unmarshal(rr.Body.Bytes(), &response) 836 require.NoError(t, err) 837 838 expected := fixGraphqlResponse("Internal Server Error: while synchronizing JWKS during parsing token: while fetching JWKS from endpoint invalid.url.scheme: invalid url scheme ", apperrors.InternalError) 839 assertGraphqlResponse(t, expected, response) 840 assert.Equal(t, http.StatusUnauthorized, rr.Code) 841 }) 842 843 t.Run("Error - token with no signing method when it's not allowed", func(t *testing.T) { 844 // GIVEN 845 middleware := createMiddleware(t, false, claimsValidatorMock()) 846 handler := testHandler(t, defaultTenant, scopes) 847 848 rr := httptest.NewRecorder() 849 req := fixEmptyRequest(t) 850 851 token := createNotSingedToken(t, defaultTenant, scopes) 852 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 853 854 // WHEN 855 middleware(handler).ServeHTTP(rr, req) 856 857 // THEN 858 assert.Equal(t, http.StatusUnauthorized, rr.Code) 859 860 var response graphql.Response 861 err = json.Unmarshal(rr.Body.Bytes(), &response) 862 require.NoError(t, err) 863 864 expected := fixGraphqlResponse("Unauthorized [reason=unexpected signing method: none]", apperrors.Unauthorized) 865 assertGraphqlResponse(t, expected, response) 866 }) 867 868 t.Run("Error - can't parse token", func(t *testing.T) { 869 // GIVEN 870 middleware := createMiddleware(t, false, claimsValidatorMock()) 871 handler := testHandler(t, defaultTenant, scopes) 872 rr := httptest.NewRecorder() 873 req := fixEmptyRequest(t) 874 875 req.Header.Add(AuthorizationHeaderKey, "Bearer fake-token") 876 877 // WHEN 878 middleware(handler).ServeHTTP(rr, req) 879 880 // THEN 881 assert.Equal(t, http.StatusUnauthorized, rr.Code) 882 883 var response graphql.Response 884 err = json.Unmarshal(rr.Body.Bytes(), &response) 885 require.NoError(t, err) 886 887 expected := fixGraphqlResponse("Unauthorized [reason=token contains an invalid number of segments]", apperrors.Unauthorized) 888 assertGraphqlResponse(t, expected, response) 889 }) 890 891 t.Run("Error - invalid header and bearer token", func(t *testing.T) { 892 // GIVEN 893 middleware := createMiddleware(t, false, claimsValidatorMock()) 894 handler := testHandler(t, defaultTenant, scopes) 895 rr := httptest.NewRecorder() 896 req := fixEmptyRequest(t) 897 898 req.Header.Add("invalidHeader", "Bearer fake-token") 899 900 // WHEN 901 middleware(handler).ServeHTTP(rr, req) 902 903 // THEN 904 assert.Equal(t, http.StatusBadRequest, rr.Code) 905 906 var response graphql.Response 907 err = json.Unmarshal(rr.Body.Bytes(), &response) 908 require.NoError(t, err) 909 910 expected := fixGraphqlResponse("Unauthorized [reason=invalid bearer token]", apperrors.Unauthorized) 911 assertGraphqlResponse(t, expected, response) 912 }) 913 914 t.Run("Error - token without signing key", func(t *testing.T) { 915 // GIVEN 916 middleware := createMiddleware(t, false, claimsValidatorMock()) 917 handler := testHandler(t, defaultTenant, scopes) 918 919 rr := httptest.NewRecorder() 920 req := fixEmptyRequest(t) 921 922 key, ok := privateJWKS2.Get(0) 923 assert.True(t, ok) 924 925 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, nil, false) 926 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 927 928 // WHEN 929 middleware(handler).ServeHTTP(rr, req) 930 931 // THEN 932 assert.Equal(t, http.StatusUnauthorized, rr.Code) 933 934 var response graphql.Response 935 err = json.Unmarshal(rr.Body.Bytes(), &response) 936 require.NoError(t, err) 937 938 expected := fixGraphqlResponse("Unauthorized [reason=while getting the key ID: Internal Server Error: unable to find the key ID in the token]", apperrors.Unauthorized) 939 assertGraphqlResponse(t, expected, response) 940 }) 941 942 t.Run("Error - after successful parsing claims are not valid", func(t *testing.T) { 943 // GIVEN 944 v := &automock.ClaimsValidator{} 945 v.On("Validate", mock.Anything, mock.Anything).Return(apperrors.NewTenantNotFoundError("externalTenantName")) 946 middleware := createMiddleware(t, false, v) 947 handler := testHandler(t, "", scopes) 948 949 rr := httptest.NewRecorder() 950 req := fixEmptyRequest(t) 951 952 key, ok := privateJWKS.Get(0) 953 assert.True(t, ok) 954 955 keyID := key.KeyID() 956 token := createTokenWithSigningMethod(t, "", scopes, key, &keyID, true) 957 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 958 959 // WHEN 960 middleware(handler).ServeHTTP(rr, req) 961 962 // THEN 963 assert.Equal(t, http.StatusBadRequest, rr.Code) 964 965 var response graphql.Response 966 err = json.Unmarshal(rr.Body.Bytes(), &response) 967 require.NoError(t, err) 968 969 expected := fixGraphqlResponse("Tenant not found [externalTenant=externalTenantName]", apperrors.TenantNotFound) 970 assertGraphqlResponse(t, expected, response) 971 }) 972 973 t.Run("Error - after successful parsing claims there are no scopes", func(t *testing.T) { 974 // GIVEN 975 requiredScopes := []string{"wanted-scope"} 976 auth := New(httpClientWithoutRedirects, PublicJWKSURL, false, ClientIDHeaderKey, claims.NewScopesValidator(requiredScopes)) 977 err := auth.SynchronizeJWKS(context.TODO()) 978 require.NoError(t, err) 979 middleware := auth.KymaAdapterHandler() 980 handler := testHandler(t, "", scopes) 981 982 rr := httptest.NewRecorder() 983 req := fixEmptyRequest(t) 984 985 key, ok := privateJWKS.Get(0) 986 assert.True(t, ok) 987 988 keyID := key.KeyID() 989 token := createTokenWithSigningMethod(t, "", scopes, key, &keyID, true) 990 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 991 992 // WHEN 993 middleware(handler).ServeHTTP(rr, req) 994 995 // THEN 996 assert.Equal(t, http.StatusUnauthorized, rr.Code) 997 998 var response graphql.Response 999 err = json.Unmarshal(rr.Body.Bytes(), &response) 1000 require.NoError(t, err) 1001 1002 expected := fixGraphqlResponse(fmt.Sprintf("Unauthorized [reason=Not all required scopes %q were found in claim with scopes %q]", requiredScopes, scopes), apperrors.Unauthorized) 1003 assertGraphqlResponse(t, expected, response) 1004 }) 1005 1006 t.Run("Error - Token signed with different key", func(t *testing.T) { 1007 // GIVEN 1008 middleware := createMiddleware(t, false, claimsValidatorMock()) 1009 handler := testHandler(t, defaultTenant, scopes) 1010 1011 rr := httptest.NewRecorder() 1012 req := fixEmptyRequest(t) 1013 1014 oldKey, ok := privateJWKS.Get(0) 1015 assert.True(t, ok) 1016 1017 newKey, ok := privateJWKS2.Get(0) 1018 assert.True(t, ok) 1019 1020 oldKeyID := oldKey.KeyID() 1021 token := createTokenWithSigningMethod(t, defaultTenant, scopes, newKey, &oldKeyID, true) 1022 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 1023 1024 // WHEN 1025 middleware(handler).ServeHTTP(rr, req) 1026 1027 // THEN 1028 assert.Equal(t, http.StatusUnauthorized, rr.Code) 1029 var response graphql.Response 1030 err = json.Unmarshal(rr.Body.Bytes(), &response) 1031 require.NoError(t, err) 1032 1033 expected := fixGraphqlResponse("Unauthorized [reason=crypto/rsa: verification error]", apperrors.Unauthorized) 1034 assertGraphqlResponse(t, expected, response) 1035 }) 1036 } 1037 1038 func TestAuthenticator_NSAdapterHandler(t *testing.T) { 1039 // GIVEN 1040 scopes := "scope-a scope-b" 1041 1042 privateJWKS, err := authenticator.FetchJWK(context.TODO(), PrivateJWKSURL) 1043 require.NoError(t, err) 1044 1045 privateJWKS2, err := authenticator.FetchJWK(context.TODO(), PrivateJWKS2URL) 1046 require.NoError(t, err) 1047 1048 privateJWKS3, err := authenticator.FetchJWK(context.TODO(), PrivateJWKS3URL) 1049 require.NoError(t, err) 1050 1051 t.Run("Success - token with signing method", func(t *testing.T) { 1052 // GIVEN 1053 middleware := createNSAdapterMiddleware(t, false, claimsValidatorMock()) 1054 handler := testHandlerNSAdapterMiddleware(t) 1055 rr := httptest.NewRecorder() 1056 req := fixEmptyRequest(t) 1057 key, ok := privateJWKS.Get(0) 1058 assert.True(t, ok) 1059 1060 keyID := key.KeyID() 1061 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 1062 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 1063 1064 // WHEN 1065 middleware(handler).ServeHTTP(rr, req) 1066 1067 // THEN 1068 assert.Equal(t, "OK", rr.Body.String()) 1069 assert.Equal(t, http.StatusOK, rr.Code) 1070 }) 1071 1072 t.Run("Success - token with no signing method when it's allowed", func(t *testing.T) { 1073 // GIVEN 1074 middleware := createNSAdapterMiddleware(t, true, claimsValidatorMock()) 1075 handler := testHandlerNSAdapterMiddleware(t) 1076 rr := httptest.NewRecorder() 1077 req := fixEmptyRequest(t) 1078 1079 token := createNotSingedToken(t, defaultTenant, scopes) 1080 require.NoError(t, err) 1081 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 1082 1083 // WHEN 1084 middleware(handler).ServeHTTP(rr, req) 1085 1086 // THEN 1087 assert.Equal(t, "OK", rr.Body.String()) 1088 assert.Equal(t, http.StatusOK, rr.Code) 1089 }) 1090 1091 t.Run("Success - retry parsing token with synchronizing JWKS", func(t *testing.T) { 1092 // GIVEN 1093 auth := New(httpClientWithoutRedirects, PublicJWKSURL, false, ClientIDHeaderKey, claimsValidatorMock()) 1094 err := auth.SynchronizeJWKS(context.TODO()) 1095 require.NoError(t, err) 1096 1097 auth.SetJWKSEndpoint(PublicJWKS2URL) 1098 1099 middleware := auth.NSAdapterHandler() 1100 1101 handler := testHandlerNSAdapterMiddleware(t) 1102 rr := httptest.NewRecorder() 1103 req := fixEmptyRequest(t) 1104 1105 key, ok := privateJWKS2.Get(0) 1106 assert.True(t, ok) 1107 1108 keyID := key.KeyID() 1109 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 1110 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 1111 1112 // WHEN 1113 middleware(handler).ServeHTTP(rr, req) 1114 1115 // THEN 1116 assert.Equal(t, "OK", rr.Body.String()) 1117 assert.Equal(t, http.StatusOK, rr.Code) 1118 }) 1119 1120 t.Run("Success - when we have more than one JWKS and use the first key", func(t *testing.T) { 1121 // GIVEN 1122 auth := New(httpClientWithoutRedirects, PublicJWKS3URL, false, ClientIDHeaderKey, claimsValidatorMock()) 1123 err := auth.SynchronizeJWKS(context.TODO()) 1124 require.NoError(t, err) 1125 1126 middleware := auth.Handler() 1127 1128 handler := testHandlerNSAdapterMiddleware(t) 1129 rr := httptest.NewRecorder() 1130 req := fixEmptyRequest(t) 1131 1132 key, ok := privateJWKS3.Get(0) 1133 assert.True(t, ok) 1134 1135 keyID := key.KeyID() 1136 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 1137 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 1138 1139 // WHEN 1140 middleware(handler).ServeHTTP(rr, req) 1141 1142 // THEN 1143 assert.Equal(t, "OK", rr.Body.String()) 1144 assert.Equal(t, http.StatusOK, rr.Code) 1145 }) 1146 1147 t.Run("Success - when we have more than one JWKS and use the second key", func(t *testing.T) { 1148 // GIVEN 1149 auth := New(httpClientWithoutRedirects, PublicJWKS3URL, false, ClientIDHeaderKey, claimsValidatorMock()) 1150 err := auth.SynchronizeJWKS(context.TODO()) 1151 require.NoError(t, err) 1152 1153 middleware := auth.Handler() 1154 1155 handler := testHandlerNSAdapterMiddleware(t) 1156 rr := httptest.NewRecorder() 1157 req := fixEmptyRequest(t) 1158 1159 key, ok := privateJWKS3.Get(1) 1160 assert.True(t, ok) 1161 1162 keyID := key.KeyID() 1163 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 1164 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 1165 1166 // WHEN 1167 middleware(handler).ServeHTTP(rr, req) 1168 1169 // THEN 1170 assert.Equal(t, "OK", rr.Body.String()) 1171 assert.Equal(t, http.StatusOK, rr.Code) 1172 }) 1173 1174 t.Run("Error - retry parsing token with failing synchronizing JWKS", func(t *testing.T) { 1175 // GIVEN 1176 auth := New(httpClientWithoutRedirects, PublicJWKSURL, false, ClientIDHeaderKey, claimsValidatorMock()) 1177 err := auth.SynchronizeJWKS(context.TODO()) 1178 require.NoError(t, err) 1179 1180 auth.SetJWKSEndpoint("invalid.url.scheme") 1181 1182 middleware := auth.NSAdapterHandler() 1183 1184 handler := testHandlerNSAdapterMiddleware(t) 1185 rr := httptest.NewRecorder() 1186 req := fixEmptyRequest(t) 1187 1188 key, ok := privateJWKS2.Get(0) 1189 assert.True(t, ok) 1190 1191 keyID := key.KeyID() 1192 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, &keyID, true) 1193 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 1194 1195 // WHEN 1196 middleware(handler).ServeHTTP(rr, req) 1197 1198 // THEN 1199 var response httputil.ErrorResponse 1200 err = json.Unmarshal(rr.Body.Bytes(), &response) 1201 require.NoError(t, err) 1202 1203 expected := fixErrorResponse("missing or invalid authorization token", http.StatusUnauthorized) 1204 assert.Equal(t, expected, response) 1205 assert.Equal(t, http.StatusUnauthorized, rr.Code) 1206 }) 1207 1208 t.Run("Error - token with no signing method when it's not allowed", func(t *testing.T) { 1209 // GIVEN 1210 middleware := createNSAdapterMiddleware(t, false, claimsValidatorMock()) 1211 handler := testHandlerNSAdapterMiddleware(t) 1212 1213 rr := httptest.NewRecorder() 1214 req := fixEmptyRequest(t) 1215 1216 token := createNotSingedToken(t, defaultTenant, scopes) 1217 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 1218 1219 // WHEN 1220 middleware(handler).ServeHTTP(rr, req) 1221 1222 // THEN 1223 assert.Equal(t, http.StatusUnauthorized, rr.Code) 1224 1225 var response httputil.ErrorResponse 1226 err = json.Unmarshal(rr.Body.Bytes(), &response) 1227 require.NoError(t, err) 1228 1229 expected := fixErrorResponse("missing or invalid authorization token", http.StatusUnauthorized) 1230 assert.Equal(t, expected, response) 1231 }) 1232 1233 t.Run("Error - can't parse token", func(t *testing.T) { 1234 // GIVEN 1235 middleware := createNSAdapterMiddleware(t, false, claimsValidatorMock()) 1236 handler := testHandlerNSAdapterMiddleware(t) 1237 rr := httptest.NewRecorder() 1238 req := fixEmptyRequest(t) 1239 1240 req.Header.Add(AuthorizationHeaderKey, "Bearer fake-token") 1241 1242 // WHEN 1243 middleware(handler).ServeHTTP(rr, req) 1244 1245 // THEN 1246 assert.Equal(t, http.StatusUnauthorized, rr.Code) 1247 1248 var response httputil.ErrorResponse 1249 err = json.Unmarshal(rr.Body.Bytes(), &response) 1250 require.NoError(t, err) 1251 1252 expected := fixErrorResponse("missing or invalid authorization token", http.StatusUnauthorized) 1253 assert.Equal(t, expected, response) 1254 }) 1255 1256 t.Run("Error - invalid header and bearer token", func(t *testing.T) { 1257 // GIVEN 1258 middleware := createNSAdapterMiddleware(t, false, claimsValidatorMock()) 1259 handler := testHandlerNSAdapterMiddleware(t) 1260 rr := httptest.NewRecorder() 1261 req := fixEmptyRequest(t) 1262 1263 req.Header.Add("invalidHeader", "Bearer fake-token") 1264 1265 // WHEN 1266 middleware(handler).ServeHTTP(rr, req) 1267 1268 // THEN 1269 assert.Equal(t, http.StatusUnauthorized, rr.Code) 1270 1271 var response httputil.ErrorResponse 1272 err = json.Unmarshal(rr.Body.Bytes(), &response) 1273 require.NoError(t, err) 1274 1275 expected := fixErrorResponse("missing or invalid authorization token", http.StatusUnauthorized) 1276 assert.Equal(t, expected, response) 1277 }) 1278 1279 t.Run("Error - token without signing key", func(t *testing.T) { 1280 // GIVEN 1281 middleware := createNSAdapterMiddleware(t, false, claimsValidatorMock()) 1282 handler := testHandlerNSAdapterMiddleware(t) 1283 1284 rr := httptest.NewRecorder() 1285 req := fixEmptyRequest(t) 1286 1287 key, ok := privateJWKS2.Get(0) 1288 assert.True(t, ok) 1289 1290 token := createTokenWithSigningMethod(t, defaultTenant, scopes, key, nil, false) 1291 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 1292 1293 // WHEN 1294 middleware(handler).ServeHTTP(rr, req) 1295 1296 // THEN 1297 assert.Equal(t, http.StatusUnauthorized, rr.Code) 1298 1299 var response httputil.ErrorResponse 1300 err = json.Unmarshal(rr.Body.Bytes(), &response) 1301 require.NoError(t, err) 1302 1303 expected := fixErrorResponse("missing or invalid authorization token", http.StatusUnauthorized) 1304 assert.Equal(t, expected, response) 1305 }) 1306 1307 t.Run("Error - after successful parsing claims are not valid", func(t *testing.T) { 1308 // GIVEN 1309 v := &automock.ClaimsValidator{} 1310 v.On("Validate", mock.Anything, mock.Anything).Return(apperrors.NewTenantNotFoundError("externalTenantName")) 1311 middleware := createNSAdapterMiddleware(t, false, v) 1312 handler := testHandlerNSAdapterMiddleware(t) 1313 1314 rr := httptest.NewRecorder() 1315 req := fixEmptyRequest(t) 1316 1317 key, ok := privateJWKS.Get(0) 1318 assert.True(t, ok) 1319 1320 keyID := key.KeyID() 1321 token := createTokenWithSigningMethod(t, "", scopes, key, &keyID, true) 1322 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 1323 1324 // WHEN 1325 middleware(handler).ServeHTTP(rr, req) 1326 1327 // THEN 1328 assert.Equal(t, http.StatusUnauthorized, rr.Code) 1329 1330 var response httputil.ErrorResponse 1331 err = json.Unmarshal(rr.Body.Bytes(), &response) 1332 require.NoError(t, err) 1333 1334 expected := fixErrorResponse("missing or invalid authorization token", http.StatusUnauthorized) 1335 assert.Equal(t, expected, response) 1336 }) 1337 1338 t.Run("Error - after successful parsing claims there is no tenant", func(t *testing.T) { 1339 // GIVEN 1340 auth := New(httpClientWithoutRedirects, PublicJWKSURL, false, ClientIDHeaderKey, claims.NewClaimsValidator()) 1341 err := auth.SynchronizeJWKS(context.TODO()) 1342 require.NoError(t, err) 1343 middleware := auth.NSAdapterHandler() 1344 handler := testHandlerNSAdapterMiddleware(t) 1345 1346 rr := httptest.NewRecorder() 1347 req := fixEmptyRequest(t) 1348 1349 key, ok := privateJWKS.Get(0) 1350 assert.True(t, ok) 1351 1352 keyID := key.KeyID() 1353 token := createTokenWithSigningMethod(t, "", "", key, &keyID, true) 1354 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 1355 1356 // WHEN 1357 middleware(handler).ServeHTTP(rr, req) 1358 1359 // THEN 1360 assert.Equal(t, http.StatusUnauthorized, rr.Code) 1361 1362 var response httputil.ErrorResponse 1363 err = json.Unmarshal(rr.Body.Bytes(), &response) 1364 require.NoError(t, err) 1365 1366 expected := fixErrorResponse("missing or invalid authorization token", http.StatusUnauthorized) 1367 assert.Equal(t, expected, response) 1368 }) 1369 1370 t.Run("Error - Token signed with different key", func(t *testing.T) { 1371 // GIVEN 1372 middleware := createNSAdapterMiddleware(t, false, claimsValidatorMock()) 1373 handler := testHandlerNSAdapterMiddleware(t) 1374 1375 rr := httptest.NewRecorder() 1376 req := fixEmptyRequest(t) 1377 1378 oldKey, ok := privateJWKS.Get(0) 1379 assert.True(t, ok) 1380 1381 newKey, ok := privateJWKS2.Get(0) 1382 assert.True(t, ok) 1383 1384 oldKeyID := oldKey.KeyID() 1385 token := createTokenWithSigningMethod(t, defaultTenant, scopes, newKey, &oldKeyID, true) 1386 req.Header.Add(AuthorizationHeaderKey, fmt.Sprintf("Bearer %s", token)) 1387 1388 // WHEN 1389 middleware(handler).ServeHTTP(rr, req) 1390 1391 // THEN 1392 assert.Equal(t, http.StatusUnauthorized, rr.Code) 1393 1394 var response httputil.ErrorResponse 1395 err = json.Unmarshal(rr.Body.Bytes(), &response) 1396 require.NoError(t, err) 1397 1398 expected := fixErrorResponse("missing or invalid authorization token", http.StatusUnauthorized) 1399 assert.Equal(t, expected, response) 1400 }) 1401 } 1402 1403 func createNotSingedToken(t *testing.T, tenant string, scopes string) string { 1404 tokenClaims := struct { 1405 Tenant string `json:"tenant"` 1406 Scopes string `json:"scopes"` 1407 ConsumerID string `json:"consumerID"` 1408 ConsumerType consumer.ConsumerType `json:"consumerType"` 1409 OnBehalfOf string `json:"onBehalfOf"` 1410 jwt.StandardClaims 1411 }{ 1412 Scopes: scopes, 1413 ConsumerID: "1e176e48-e258-4091-a584-feb1bf708b7e", 1414 ConsumerType: consumer.Runtime, 1415 } 1416 1417 tenantJSON, err := json.Marshal(map[string]string{"consumerTenant": tenant, "externalTenant": ""}) 1418 require.NoError(t, err) 1419 tokenClaims.Tenant = string(tenantJSON) 1420 1421 token := jwt.NewWithClaims(jwt.SigningMethodNone, tokenClaims) 1422 1423 signedToken, err := token.SignedString(jwt.UnsafeAllowNoneSignatureType) 1424 require.NoError(t, err) 1425 1426 return signedToken 1427 } 1428 1429 func createTokenWithSigningMethod(t *testing.T, tenant string, scopes string, key jwk.Key, keyID *string, isSigningKeyAvailable bool) string { 1430 tokenClaims := struct { 1431 Tenant string `json:"tenant"` 1432 Scopes string `json:"scopes"` 1433 ConsumerID string `json:"consumerID"` 1434 ConsumerType consumer.ConsumerType `json:"consumerType"` 1435 OnBehalfOf string `json:"onBehalfOf"` 1436 jwt.StandardClaims 1437 }{ 1438 Scopes: scopes, 1439 ConsumerID: "1e176e48-e258-4091-a584-feb1bf708b7e", 1440 ConsumerType: consumer.Runtime, 1441 } 1442 1443 tenantJSON, err := json.Marshal(map[string]string{"consumerTenant": tenant, "externalTenant": "externalTenantName", "providerTenant": tenant, "providerExternalTenant": defaultExternalTenant}) 1444 require.NoError(t, err) 1445 tokenClaims.Tenant = string(tenantJSON) 1446 1447 token := jwt.NewWithClaims(jwt.SigningMethodRS256, tokenClaims) 1448 1449 if isSigningKeyAvailable { 1450 token.Header[JwksKeyIDKey] = keyID 1451 } 1452 1453 var rawKey interface{} 1454 err = key.Raw(&rawKey) 1455 require.NoError(t, err) 1456 1457 signedToken, err := token.SignedString(rawKey) 1458 require.NoError(t, err) 1459 1460 return signedToken 1461 } 1462 1463 func createMiddleware(t *testing.T, allowJWTSigningNone bool, claimsValidatorMock ClaimsValidator) func(next http.Handler) http.Handler { 1464 auth := New(httpClientWithoutRedirects, PublicJWKSURL, allowJWTSigningNone, ClientIDHeaderKey, claimsValidatorMock) 1465 err := auth.SynchronizeJWKS(context.TODO()) 1466 require.NoError(t, err) 1467 return auth.Handler() 1468 } 1469 1470 func createNSAdapterMiddleware(t *testing.T, allowJWTSigningNone bool, claimsValidatorMock ClaimsValidator) func(next http.Handler) http.Handler { 1471 auth := New(httpClientWithoutRedirects, PublicJWKSURL, allowJWTSigningNone, ClientIDHeaderKey, claimsValidatorMock) 1472 err := auth.SynchronizeJWKS(context.TODO()) 1473 require.NoError(t, err) 1474 return auth.NSAdapterHandler() 1475 } 1476 1477 func testHandlerNSAdapterMiddleware(t *testing.T) http.HandlerFunc { 1478 return func(w http.ResponseWriter, r *http.Request) { 1479 _, err := w.Write([]byte("OK")) 1480 require.NoError(t, err) 1481 } 1482 } 1483 1484 func testHandler(t *testing.T, expectedTenant string, scopes string) http.HandlerFunc { 1485 return testHandlerWithClientUser(t, expectedTenant, "", scopes) 1486 } 1487 1488 func testHandlerWithClientUser(t *testing.T, expectedTenant, expectedClientUser, scopes string) http.HandlerFunc { 1489 return func(w http.ResponseWriter, r *http.Request) { 1490 tenantFromContext, err := tenant.LoadFromContext(r.Context()) 1491 if !apperrors.IsTenantRequired(err) { 1492 require.NoError(t, err) 1493 } 1494 clientUserFromContext, err := client.LoadFromContext(r.Context()) 1495 if expectedClientUser == "" { 1496 require.Error(t, err) 1497 } 1498 scopesFromContext, err := scope.LoadFromContext(r.Context()) 1499 require.NoError(t, err) 1500 1501 require.Equal(t, expectedTenant, tenantFromContext) 1502 require.Equal(t, expectedClientUser, clientUserFromContext) 1503 scopesArray := strings.Split(scopes, " ") 1504 require.ElementsMatch(t, scopesArray, scopesFromContext) 1505 1506 _, err = w.Write([]byte("OK")) 1507 require.NoError(t, err) 1508 } 1509 } 1510 1511 func testHandlerWithExternalTenant(t *testing.T, expectedTenant string, scopes string) http.HandlerFunc { 1512 return testHandlerWithClientUserAndExternalTenant(t, expectedTenant, "", scopes) 1513 } 1514 1515 func testHandlerWithClientUserAndExternalTenant(t *testing.T, expectedTenant, expectedClientUser, scopes string) http.HandlerFunc { 1516 return func(w http.ResponseWriter, r *http.Request) { 1517 tenantPairFromContext, err := tenant.LoadTenantPairFromContext(r.Context()) 1518 if !apperrors.IsTenantRequired(err) { 1519 require.NoError(t, err) 1520 } 1521 tenantFromContext := tenantPairFromContext.ExternalID 1522 clientUserFromContext, err := client.LoadFromContext(r.Context()) 1523 if expectedClientUser == "" { 1524 require.Error(t, err) 1525 } 1526 scopesFromContext, err := scope.LoadFromContext(r.Context()) 1527 require.NoError(t, err) 1528 1529 require.Equal(t, expectedTenant, tenantFromContext) 1530 require.Equal(t, expectedClientUser, clientUserFromContext) 1531 scopesArray := strings.Split(scopes, " ") 1532 require.ElementsMatch(t, scopesArray, scopesFromContext) 1533 1534 _, err = w.Write([]byte("OK")) 1535 require.NoError(t, err) 1536 } 1537 } 1538 1539 func testHandlerWithScenarioGroups(t *testing.T, expectedTenant string, expectedScenarioGroups []string, scopes string) http.HandlerFunc { 1540 return func(w http.ResponseWriter, r *http.Request) { 1541 tenantFromContext, err := tenant.LoadFromContext(r.Context()) 1542 if !apperrors.IsTenantRequired(err) { 1543 require.NoError(t, err) 1544 } 1545 scenarioGroupsFromContext := scenariogroups.LoadFromContext(r.Context()) 1546 1547 scopesFromContext, err := scope.LoadFromContext(r.Context()) 1548 require.NoError(t, err) 1549 1550 require.Equal(t, expectedTenant, tenantFromContext) 1551 require.Equal(t, expectedScenarioGroups, scenarioGroupsFromContext) 1552 scopesArray := strings.Split(scopes, " ") 1553 require.ElementsMatch(t, scopesArray, scopesFromContext) 1554 1555 _, err = w.Write([]byte("OK")) 1556 require.NoError(t, err) 1557 } 1558 } 1559 1560 func fixEmptyRequest(t *testing.T) *http.Request { 1561 req, err := http.NewRequest("GET", "/", nil) 1562 require.NoError(t, err) 1563 1564 return req 1565 } 1566 1567 func fixGraphqlResponse(msg string, errorType apperrors.ErrorType) graphql.Response { 1568 return graphql.Response{ 1569 Data: []byte("null"), 1570 Errors: []*gqlerror.Error{{ 1571 Message: msg, 1572 Extensions: map[string]interface{}{"error_code": errorType, "error": errorType.String()}}}} 1573 } 1574 1575 func fixErrorResponse(msg string, statusCode int) httputil.ErrorResponse { 1576 return httputil.ErrorResponse{ 1577 Error: httputil.Error{ 1578 Code: statusCode, 1579 Message: msg, 1580 }, 1581 } 1582 } 1583 1584 func assertGraphqlResponse(t *testing.T, expected, actual graphql.Response) { 1585 require.Len(t, expected.Errors, 1) 1586 require.Len(t, actual.Errors, 1) 1587 assert.Equal(t, expected.Errors[0].Extensions["error"], actual.Errors[0].Extensions["error"]) 1588 1589 errType, ok := expected.Errors[0].Extensions["error_code"].(apperrors.ErrorType) 1590 require.True(t, ok) 1591 actualErrCode := int(errType) 1592 1593 errCode, ok := actual.Errors[0].Extensions["error_code"].(float64) 1594 require.True(t, ok) 1595 expectedErrCode := int(errCode) 1596 assert.Equal(t, expectedErrCode, actualErrCode) 1597 assert.Equal(t, expected.Errors[0].Message, actual.Errors[0].Message) 1598 } 1599 1600 func claimsValidatorMock() ClaimsValidator { 1601 v := &automock.ClaimsValidator{} 1602 v.On("Validate", mock.Anything, mock.Anything).Return(nil) 1603 return v 1604 }