@@ -264,9 +264,7 @@ my $jwt = encode_jwt(payload => {
264264--- no_error_log
265265[error]
266266
267-
268-
269- === TEST 2: JWT verification fails when no alg is present in the jwk to match against jwt.header.alg
267+ === TEST 6: JWT verification does not fail when no alg is present in the jwk to match against jwt.header.alg
270268--- configuration env eval
271269use JSON qw(to_json);
272270
@@ -303,7 +301,7 @@ to_json({
303301 }
304302 }
305303--- request: GET /test
306- --- error_code: 403
304+ --- error_code: 200
307305--- more_headers eval
308306use Crypt::JWT qw(encode_jwt);
309307my $jwt = encode_jwt(payload => {
@@ -313,5 +311,132 @@ my $jwt = encode_jwt(payload => {
313311 iss => 'https://example.com/auth/realms/apicast',
314312 exp => time + 3600 }, key => \$::private_key, alg => 'RS256', extra_headers => { kid => 'somekid' });
315313"Authorization: Bearer $jwt"
314+ --- no_error_log
315+
316+ === TEST 7: JWT verification fails when jwk.alg exists AND does not match jwt.header.alg
317+ (see THREESCALE-8249 for steps to generate tampered JWT. rsa.pub from fixtures used to sign)
318+ --- configuration env eval
319+ use JSON qw(to_json);
320+
321+ to_json({
322+ services => [{
323+ id => 42,
324+ backend_version => 'oauth',
325+ backend_authentication_type => 'provider_key',
326+ backend_authentication_value => 'fookey',
327+ proxy => {
328+ authentication_method => 'oidc',
329+ oidc_issuer_endpoint => 'https://example.com/auth/realms/apicast',
330+ api_backend => "http://test:$TEST_NGINX_SERVER_PORT/",
331+ proxy_rules => [
332+ { pattern => '/', http_method => 'GET', metric_system_name => 'hits', delta => 1 }
333+ ]
334+ }
335+ }],
336+ oidc => [{
337+ issuer => 'https://example.com/auth/realms/apicast',
338+ config => { id_token_signing_alg_values_supported => [ 'RS256', 'HS256' ] },
339+ keys => { somekid => { pem => $::public_key, alg => 'RS256' } },
340+ }]
341+ });
342+ --- upstream
343+ location /test {
344+ echo "yes";
345+ }
346+ --- backend
347+ location = /transactions/oauth_authrep.xml {
348+ content_by_lua_block {
349+ local expected = "provider_key=fookey&service_id=42&usage%5Bhits%5D=1&app_id=appid"
350+ require('luassert').same(ngx.decode_args(expected), ngx.req.get_uri_args(0))
351+ }
352+ }
353+ --- request: GET /test
354+ --- error_code: 403
355+ --- more_headers eval
356+ use Crypt::JWT qw(encode_jwt);
357+ my $jwt = 'eyJraWQiOiJzb21la2lkIiwiYWxnIjoiSFMyNTYifQ.'.
358+ 'eyJleHAiOjcxNzA1MzE2NDMwLCJhenAiOiJhcHBpZCIsInN1YiI6In'.
359+ 'NvbWVvbmUiLCJhdWQiOiJzb21ldGhpbmciLCJpc3MiOiJodHRwczov'.
360+ 'L2V4YW1wbGUuY29tL2F1dGgvcmVhbG1zL2FwaWNhc3QifQ.1rFq5QN'.
361+ 'b99W6aqQjsx7GJGLDpdkDLI6-huZLzMAmxGQ';
362+ "Authorization: Bearer $jwt"
316363--- error_log
317364[jwt] alg mismatch
365+
366+ === TEST 8: Token was signed by a different key
367+ --- configuration env eval
368+ use JSON qw(to_json);
369+
370+ to_json({
371+ services => [{
372+ id => 42,
373+ backend_version => 'oauth',
374+ backend_authentication_type => 'provider_key',
375+ backend_authentication_value => 'fookey',
376+ proxy => {
377+ authentication_method => 'oidc',
378+ oidc_issuer_endpoint => 'https://example.com/auth/realms/a',
379+ api_backend => "http://test:$TEST_NGINX_SERVER_PORT/",
380+ proxy_rules => [
381+ { pattern => '/', http_method => 'GET', metric_system_name => 'hits', delta => 1 }
382+ ]
383+ }
384+ }],
385+ oidc => [{
386+ issuer => 'https://example.com/auth/realms/a',
387+ config => { id_token_signing_alg_values_supported => [ 'RS256' ] },
388+ keys => { somekid => { pem => $::public_key, alg => 'RS256' } },
389+ }]
390+ });
391+ --- request: GET /test
392+ --- error_code: 403
393+ --- more_headers eval
394+ use Crypt::JWT qw(encode_jwt);
395+ my $jwt = encode_jwt(payload => {
396+ aud => 'something',
397+ azp => 'appid',
398+ sub => 'someone',
399+ iss => 'https://example.com/auth/realms/b',
400+ exp => time + 3600 }, key => \$::private_key, alg => 'RS256', extra_headers => { kid => 'otherkid' });
401+ "Authorization: Bearer $jwt"
402+ --- error_log
403+ [jwk] not found, token might belong to a different realm
404+
405+ === TEST 9: Token was signed by a different issuer
406+ --- configuration env eval
407+ use JSON qw(to_json);
408+
409+ to_json({
410+ services => [{
411+ id => 42,
412+ backend_version => 'oauth',
413+ backend_authentication_type => 'provider_key',
414+ backend_authentication_value => 'fookey',
415+ proxy => {
416+ authentication_method => 'oidc',
417+ oidc_issuer_endpoint => 'https://example.com/auth/realms/apicast',
418+ api_backend => "http://test:$TEST_NGINX_SERVER_PORT/",
419+ proxy_rules => [
420+ { pattern => '/', http_method => 'GET', metric_system_name => 'hits', delta => 1 }
421+ ]
422+ }
423+ }],
424+ oidc => [{
425+ issuer => 'https://example.com/auth/realms/apicast',
426+ config => { id_token_signing_alg_values_supported => [ 'RS256' ] },
427+ keys => { somekid => { pem => $::public_key, alg => 'RS256' } },
428+ }]
429+ });
430+ --- request: GET /test
431+ --- error_code: 403
432+ --- more_headers eval
433+ use Crypt::JWT qw(encode_jwt);
434+ my $jwt = encode_jwt(payload => {
435+ aud => 'something',
436+ azp => 'appid',
437+ sub => 'someone',
438+ iss => 'unexpected_issuer',
439+ exp => time + 3600 }, key => \$::private_key, alg => 'RS256', extra_headers => { kid => 'somekid' });
440+ "Authorization: Bearer $jwt"
441+ --- error_log eval
442+ [ qr/Claim 'iss' \('unexpected_issuer'\) returned failure/ ]
0 commit comments