From 889cf8aff3ac68fb0177b930122b331e50b8b29b Mon Sep 17 00:00:00 2001 From: Hans Kristian Flaatten Date: Wed, 17 Feb 2021 13:55:05 +0100 Subject: [PATCH] Adding support for JWKS-based token validation --- kong/plugins/oidc/handler.lua | 7 +++++- kong/plugins/oidc/schema.lua | 1 + kong/plugins/oidc/utils.lua | 3 ++- test/unit/test_handler_mocking_openidc.lua | 29 +++++++++++++++++----- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/kong/plugins/oidc/handler.lua b/kong/plugins/oidc/handler.lua index 2b2e652b..cbb51c8b 100644 --- a/kong/plugins/oidc/handler.lua +++ b/kong/plugins/oidc/handler.lua @@ -115,7 +115,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 7b5e58bd..e93432de 100644 --- a/kong/plugins/oidc/schema.lua +++ b/kong/plugins/oidc/schema.lua @@ -13,6 +13,7 @@ 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" }, diff --git a/kong/plugins/oidc/utils.lua b/kong/plugins/oidc/utils.lua index c531fc5b..76044ec5 100644 --- a/kong/plugins/oidc/utils.lua +++ b/kong/plugins/oidc/utils.lua @@ -58,6 +58,7 @@ 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 or "") .. "," .. (config.ignore_auth_filters or "")), @@ -155,7 +156,7 @@ function M.setCredentials(user) end function M.injectUser(user, headerName) - ngx.log(ngx.DEBUG, "Injecting " .. headerName) + ngx.log(ngx.DEBUG, "Injecting " .. headerName) local userinfo = cjson.encode(user) ngx.req.set_header(headerName, ngx.encode_base64(userinfo)) end diff --git a/test/unit/test_handler_mocking_openidc.lua b/test/unit/test_handler_mocking_openidc.lua index e988b746..e5b18969 100644 --- a/test/unit/test_handler_mocking_openidc.lua +++ b/test/unit/test_handler_mocking_openidc.lua @@ -36,7 +36,7 @@ function TestHandler:test_authenticate_ok_with_userinfo() ngx.encode_base64 = function(x) return "eyJzdWIiOiJzdWIifQ==" end - + local headers = {} ngx.req.set_header = function(h, v) headers[h] = v @@ -52,7 +52,7 @@ function TestHandler:test_authenticate_ok_with_no_accesstoken() self.module_resty.openidc.authenticate = function(opts) return {id_token = {sub = "sub"}}, true end - + local headers = {} ngx.req.set_header = function(h, v) headers[h] = v @@ -67,7 +67,7 @@ function TestHandler:test_authenticate_ok_with_accesstoken() self.module_resty.openidc.authenticate = function(opts) return {id_token = { sub = "sub" } , access_token = "ACCESS_TOKEN"}, true end - + local headers = {} ngx.req.set_header = function(h, v) headers[h] = v @@ -82,7 +82,7 @@ function TestHandler:test_authenticate_ok_with_no_idtoken() self.module_resty.openidc.authenticate = function(opts) return {}, true end - + local headers = {} ngx.req.set_header = function(h, v) headers[h] = v @@ -101,7 +101,7 @@ function TestHandler:test_authenticate_ok_with_idtoken() ngx.encode_base64 = function(x) return "eyJzdWIiOiJzdWIifQ==" end - + local headers = {} ngx.req.set_header = function(h, v) headers[h] = v @@ -205,6 +205,23 @@ function TestHandler:test_bearer_only_with_bad_token() lu.assertFalse(self:log_contains("introspect succeeded")) end -lu.run() +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()