Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 30 additions & 37 deletions kong/plugins/frontier/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ local function check_request_permission(conf, cookies, bearer)
end


local function append_claims_as_headers(conf, user_token)
local function append_claims_as_headers(conf, claims)
local clear_header = kong.service.request.clear_header
local set_header = kong.service.request.set_header

Expand All @@ -215,14 +215,6 @@ local function append_claims_as_headers(conf, user_token)
end
end

local jwt, err = jwt_decoder.decode_token(user_token)
if err then
kong.log.warn("failed to decode token: ", err)
return fail_auth()
end

local claims = jwt.claims

local claims_are_readable = type(claims) == "table"

if not claims_are_readable then
Expand All @@ -241,33 +233,21 @@ local function append_claims_as_headers(conf, user_token)
end
end

local function verify_organization_id_header(conf, user_token)
local request_organization_id = kong.request.get_header(conf.request_organization_id_header)
local function verify_organization_id_header(conf, claims, request_organization_id)
local org_ids = type(claims) == "table" and claims[frontier_org_ids_claim_key] or nil
local org_id_header_verified = false

if request_organization_id then
local jwt, err = jwt_decoder.decode_token(user_token)
if err then
kong.log.warn("failed to decode token: ", err)
return fail_auth()
end

local claims = jwt.claims
local org_ids = type(claims) == "table" and claims[frontier_org_ids_claim_key] or nil

local org_id_header_verified = false

if type(org_ids) == "string" then
for word in string.gmatch(org_ids, '([^,]+)') do
if word == request_organization_id then
org_id_header_verified = true
end
if type(org_ids) == "string" then
for word in string.gmatch(org_ids, '([^,]+)') do
if word == request_organization_id then
org_id_header_verified = true
end
end
end

if not org_id_header_verified then
kong.log.info(conf.request_organization_id_header .. " header removed for request")
kong.service.request.clear_header(conf.request_organization_id_header)
end
if not org_id_header_verified then
kong.log.info(conf.request_organization_id_header .. " header removed for request")
kong.service.request.clear_header(conf.request_organization_id_header)
end
end

Expand All @@ -294,12 +274,25 @@ function _M.run(conf)
end
end

if #conf.token_claims_to_append_as_headers > 0 then
append_claims_as_headers(conf, user_token)
end
local wants_claim_headers = #conf.token_claims_to_append_as_headers > 0
local organization_id_to_verify = conf.verify_request_organization_id_header
and kong.request.get_header(conf.request_organization_id_header) or nil

if wants_claim_headers or organization_id_to_verify then
local jwt, err = jwt_decoder.decode_token(user_token)

if err then
kong.log.warn("failed to decode token: ", err)
return fail_auth()
end

if wants_claim_headers then
append_claims_as_headers(conf, jwt.claims)
end

if conf.verify_request_organization_id_header then
verify_organization_id_header(conf, user_token)
if organization_id_to_verify then
verify_organization_id_header(conf, jwt.claims, organization_id_to_verify)
end
end
end
end
Expand Down
56 changes: 55 additions & 1 deletion kong/plugins/spec/frontier-test/05-access_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ end
-- `answer` is either a token the server hands back in a 200, or a table
-- describing the raw reply so the failure paths can be driven.
local function run_plugin(conf, answer, request_headers)
local result = { set = {}, cleared = {}, status = nil, exit_headers = nil }
local result = { set = {}, cleared = {}, status = nil, exit_headers = nil, decodes = 0 }

local reply, reply_err
if type(answer) == "table" then
Expand Down Expand Up @@ -115,6 +115,15 @@ local function run_plugin(conf, answer, request_headers)
package.loaded["kong.plugins." .. PLUGIN_NAME .. "." .. mod] = nil
end

-- wraps the real decoder so the number of reads of one token is countable
local real_decoder = require("kong.plugins." .. PLUGIN_NAME .. ".jwt_decoder")
package.loaded["kong.plugins." .. PLUGIN_NAME .. ".jwt_decoder"] = {
decode_token = function(token)
result.decodes = result.decodes + 1
return real_decoder.decode_token(token)
end
}

local access = require("kong.plugins." .. PLUGIN_NAME .. ".access")

local ok, err = pcall(access.run, conf)
Expand Down Expand Up @@ -194,6 +203,51 @@ describe("Plugin: " .. PLUGIN_NAME .. " (access), ", function()
end)
end)

describe("reading the token", function()
local both_on = function()
local c = base_conf()
c.verify_request_organization_id_header = true
return c
end

it("reads the token once when both header steps run", function()
local out = run_plugin(both_on(), token_with_payload('{"sub":"u1","org_ids":"o1"}'),
{ ["x-organization-id"] = "o1" })

assert.is_nil(out.raised)
assert.equal(1, out.decodes)
end)

it("reads it once for the claim headers alone", function()
local out = run_plugin(base_conf(), token_with_payload('{"sub":"u1"}'), {})

assert.is_nil(out.raised)
assert.equal(1, out.decodes)
end)

it("reads it once for the organization check alone", function()
local c = both_on()
c.token_claims_to_append_as_headers = {}

local out = run_plugin(c, token_with_payload('{"org_ids":"o1"}'),
{ ["x-organization-id"] = "o1" })

assert.is_nil(out.raised)
assert.equal(1, out.decodes)
end)

it("does not read it at all when nothing needs the claims", function()
local c = both_on()
c.token_claims_to_append_as_headers = {}

-- the organization check is on but the client sent no header
local out = run_plugin(c, token_with_payload('{"sub":"u1"}'), {})

assert.is_nil(out.raised)
assert.equal(0, out.decodes)
end)
end)

describe("what the auth server answers", function()
it("a 200 with no token in it gives a 401, not a 500", function()
-- the one behaviour change in this work. it used to pass nil into
Expand Down