diff --git a/kong/plugins/oidc/handler.lua b/kong/plugins/oidc/handler.lua index 07f05af5..5465afd0 100644 --- a/kong/plugins/oidc/handler.lua +++ b/kong/plugins/oidc/handler.lua @@ -30,7 +30,7 @@ function handle(oidcConfig) if oidcConfig.introspection_endpoint then response = introspect(oidcConfig) if response then - utils.injectUser(response) + utils.injectUser(response, oidcConfig) end end @@ -38,7 +38,7 @@ function handle(oidcConfig) response = make_oidc(oidcConfig) if response then if (response.user) then - utils.injectUser(response.user) + utils.injectUser(response.user, oidcConfig) end if (response.access_token) then utils.injectAccessToken(response.access_token) @@ -65,7 +65,12 @@ end function introspect(oidcConfig) if utils.has_bearer_access_token() or oidcConfig.bearer_only == "yes" then - local res, err = require("resty.openidc").introspect(oidcConfig) + local res, err + if oidcConfig.use_jwks == "yes" then + res, err = require("resty.openidc").bearer_jwt_verify(oidcConfig) + else + res, err = require("resty.openidc").introspect(oidcConfig) + end if err then if oidcConfig.bearer_only == "yes" then ngx.header["WWW-Authenticate"] = 'Bearer realm="' .. oidcConfig.realm .. '",error="' .. err .. '"' diff --git a/kong/plugins/oidc/schema.lua b/kong/plugins/oidc/schema.lua index ffb55b37..c8328851 100644 --- a/kong/plugins/oidc/schema.lua +++ b/kong/plugins/oidc/schema.lua @@ -13,11 +13,13 @@ return { scope = { type = "string", required = true, default = "openid" }, response_type = { type = "string", required = true, default = "code" }, ssl_verify = { type = "string", required = true, default = "no" }, + use_jwks = { type = "string", required = true, default = "no" }, token_endpoint_auth_method = { type = "string", required = true, default = "client_secret_post" }, session_secret = { type = "string", required = false }, recovery_page_path = { type = "string" }, logout_path = { type = "string", required = false, default = '/logout' }, redirect_after_logout_uri = { type = "string", required = false, default = '/' }, - filters = { type = "string" } + filters = { type = "string" }, + mappings = { type = "array", default = {}, } } } diff --git a/kong/plugins/oidc/utils.lua b/kong/plugins/oidc/utils.lua index 3686bbf6..dfd19724 100644 --- a/kong/plugins/oidc/utils.lua +++ b/kong/plugins/oidc/utils.lua @@ -53,11 +53,13 @@ function M.get_options(config, ngx) scope = config.scope, response_type = config.response_type, ssl_verify = config.ssl_verify, + use_jwks = config.use_jwks, token_endpoint_auth_method = config.token_endpoint_auth_method, recovery_page_path = config.recovery_page_path, filters = parseFilters(config.filters), logout_path = config.logout_path, redirect_after_logout_uri = config.redirect_after_logout_uri, + mappings = config.mappings, } end @@ -76,13 +78,31 @@ function M.injectIDToken(idToken) ngx.req.set_header("X-ID-Token", ngx.encode_base64(tokenStr)) end -function M.injectUser(user) +function M.injectUser(user, oidcConfig) local tmp_user = user tmp_user.id = user.sub tmp_user.username = user.preferred_username ngx.ctx.authenticated_credential = tmp_user local userinfo = cjson.encode(user) ngx.req.set_header("X-Userinfo", ngx.encode_base64(userinfo)) + + if oidcConfig.mappings ~= nil then + for i, value in ipairs(oidcConfig.mappings) do + local f, from, to + f = string.gmatch(value, "[^:]+") + from = f() + to = f() + if from ~= nil and to ~= nil then + if user[from] ~= nil then + ngx.req.set_header(to, user[from]) + else + ngx.log(ngx.WARN, "Key '" .. from .. "' not present on token") + end + else + ngx.log(ngx.ERR, "Ignoring incorrect configuration: " .. value) + end + end + end end function M.has_bearer_access_token() diff --git a/test/unit/mockable_case.lua b/test/unit/mockable_case.lua index 66aa367c..1fa70c79 100644 --- a/test/unit/mockable_case.lua +++ b/test/unit/mockable_case.lua @@ -8,6 +8,7 @@ function MockableCase:setUp() self.mocked_ngx = { DEBUG = "debug", ERR = "error", + WARN = "warn", HTTP_UNAUTHORIZED = 401, ctx = {}, header = {}, diff --git a/test/unit/test_handler_mocking_openidc.lua b/test/unit/test_handler_mocking_openidc.lua index 1898d85d..f3d0de12 100644 --- a/test/unit/test_handler_mocking_openidc.lua +++ b/test/unit/test_handler_mocking_openidc.lua @@ -193,6 +193,25 @@ function TestHandler:test_bearer_only_with_bad_token() lu.assertFalse(self:log_contains("introspect succeeded")) end +function TestHandler:test_introspect_bearer_token_and_property_mapping() + self.module_resty.openidc.bearer_jwt_verify = function(opts) + return {foo = "bar"}, false + end + ngx.req.get_headers = function() return {Authorization = "Bearer xxx"} end + + ngx.encode_base64 = function(x) return "x" end + + local headers = {} + ngx.req.set_header = function(h, v) + headers[h] = v + end + + self.handler:access({introspection_endpoint = "x", bearer_only = "yes", use_jwks = "yes", mappings = {'foo:X-Foo', 'incorrect', 'not:present'}}) + lu.assertEquals(headers["X-Foo"], 'bar') + lu.assertTrue(self:log_contains("not present on token")) + lu.assertTrue(self:log_contains("Ignoring incorrect configuration")) +end + lu.run()