Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JWT claim check policy: uri was not escape correctly #1428

Merged
merged 2 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -27,6 +27,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

- Fixed token instrospection field removed [PR #1438](https://github.com/3scale/APIcast/pull/1438) [THREESCALE-10591](https://issues.redhat.com/browse/THREESCALE-10591)

- Fixed issue with URL was not correctly escaped when using the JWT claim check policy [THREESCALE-10308](https://issues.redhat.com/browse/THREESCALE-10308) [PR #1428](https://github.com/3scale/APIcast/pull/1428)

### Added

- Detect number of CPU shares when running on Cgroups V2 [PR #1410](https://github.com/3scale/apicast/pull/1410) [THREESCALE-10167](https://issues.redhat.com/browse/THREESCALE-10167)
Expand Down
Expand Up @@ -5,6 +5,7 @@ local Condition = require('apicast.conditions.condition')
local MappingRule = require('apicast.mapping_rule')
local Operation = require('apicast.conditions.operation')
local TemplateString = require('apicast.template_string')
local escape = require("resty.http.uri_escape")

local ipairs = ipairs

Expand Down Expand Up @@ -58,6 +59,10 @@ end
local function is_rule_denied_request(rule, context)

local uri = context:get_uri()
-- URI need to be escaped to be able to match values with special characters
-- (like spaces)
-- Example: if URI is `/foo /bar` it will be translated to `/foo%20/bar`
local escaped_uri = escape.escape_uri(uri)
local request_method = ngx.req.get_method()

local resource = rule.resource:render(context)
Expand All @@ -71,7 +76,7 @@ local function is_rule_denied_request(rule, context)
-- the name of the metric is irrelevant
metric_system_name = 'hits'
})
if mapping_rule:matches(request_method, uri) then
if mapping_rule:matches(request_method, escaped_uri) then
mapping_rule_match = true
break
end
Expand Down
81 changes: 81 additions & 0 deletions t/apicast-policy-jwt-claim-check.t
Expand Up @@ -564,3 +564,84 @@ the URI is not longer valid at all, and JWT is not expected to work correctly.
["yay, api backend\n","Request blocked due to JWT claim policy\n"]
--- no_error_log
[error]



=== TEST 8: JWT claim reject request with invalid token and URI contain special characters
--- backend
location /transactions/oauth_authrep.xml {
content_by_lua_block {
ngx.exit(200)
}
}

--- configuration
{
"oidc": [
{
"issuer": "https://example.com/auth/realms/apicast",
"config": { "id_token_signing_alg_values_supported": [ "RS256" ] },
"keys": { "somekid": { "pem": "-----BEGIN PUBLIC KEY-----\nMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALClz96cDQ965ENYMfZzG+Acu25lpx2K\nNpAALBQ+catCA59us7+uLY5rjQR6SOgZpCz5PJiKNAdRPDJMXSmXqM0CAwEAAQ==\n-----END PUBLIC KEY-----", "alg": "RS256" } }
}
],
"services": [
{
"id": 42,
"backend_version": "oauth",
"backend_authentication_type": "service_token",
"backend_authentication_value": "token-value",
"proxy": {
"authentication_method": "oidc",
"oidc_issuer_endpoint": "https://example.com/auth/realms/apicast",
"api_backend": "http://test:$TEST_NGINX_SERVER_PORT/",
"proxy_rules": [
{ "pattern": "/groups/{groupID}$", "http_method": "GET", "metric_system_name": "hits", "delta": 1 }
],
"policy_chain": [
{
"name": "apicast.policy.jwt_claim_check",
"configuration": {
"rules" : [{
"operations": [
{"op": "==", "jwt_claim": "foo", "jwt_claim_type": "plain", "value": "1"}
],
"combine_op": "and",
"methods": ["GET"],
"resource": "/groups/{groupdID}$"
}]
}
},
{ "name": "apicast.policy.apicast" }
]
}
}
]
}
--- upstream
location /groups {
content_by_lua_block {
ngx.say('yay, api backend');
}
}
--- request eval
[
"GET /groups/%2020",
"GET /groups/%2020%0A30"
]
--- more_headers eval
::authorization_bearer_jwt('audience', {
realm_access => {
roles => [ 'director' ]
},
foo => "invalid",
}, 'somekid')
--- error_code eval
[403, 403]
--- response_body eval
[
"Request blocked due to JWT claim policy\x{0a}",
"Request blocked due to JWT claim policy\x{0a}"
]
--- no_error_log
[error]