kong/spec/03-plugins/16-jwt/04-invalidations_spec.lua (200 lines of code) (raw):
local helpers = require "spec.helpers"
local cjson = require "cjson"
local jwt_encoder = require "kong.plugins.jwt.jwt_parser"
for _, strategy in helpers.each_strategy() do
describe("Plugin: jwt (invalidations) [#" .. strategy .. "]", function()
local admin_client
local proxy_client
local consumer
local route
local db
before_each(function()
local bp
bp, db = helpers.get_db_utils(strategy, {
"routes",
"services",
"plugins",
"consumers",
"jwt_secrets",
})
route = bp.routes:insert {
hosts = { "jwt.com" },
}
consumer = bp.consumers:insert {
username = "consumer1",
}
bp.plugins:insert {
name = "jwt",
config = {},
route = { id = route.id },
}
bp.jwt_secrets:insert {
key = "key123",
secret = "secret123",
consumer = { id = consumer.id },
}
assert(helpers.start_kong({
database = strategy,
nginx_conf = "spec/fixtures/custom_nginx.template",
}))
admin_client = helpers.admin_client()
proxy_client = helpers.proxy_client()
end)
after_each(function()
if admin_client and proxy_client then
admin_client:close()
proxy_client:close()
end
helpers.stop_kong()
end)
local PAYLOAD = {
iss = nil,
nbf = os.time(),
iat = os.time(),
exp = os.time() + 3600
}
local function get_authorization(key, secret)
PAYLOAD.iss = key
local jwt = jwt_encoder.encode(PAYLOAD, secret)
return "Bearer " .. jwt
end
describe("JWT Credentials entity invalidation", function()
it("should invalidate when JWT Auth Credential entity is deleted", function()
-- It should work
local res = assert(proxy_client:send {
method = "GET",
path = "/request",
headers = {
["Authorization"] = get_authorization("key123", "secret123"),
["Host"] = "jwt.com"
}
})
assert.res_status(200, res)
-- Check that cache is populated
local cache_key = db.jwt_secrets:cache_key("key123")
res = assert(admin_client:send {
method = "GET",
path = "/cache/" .. cache_key,
})
assert.res_status(200, res)
-- Retrieve credential ID
res = assert(admin_client:send {
method = "GET",
path = "/consumers/consumer1/jwt/",
})
local body = cjson.decode(assert.res_status(200, res))
local credential_id = body.data[1].id
assert.truthy(credential_id)
-- Delete JWT credential (which triggers invalidation)
res = assert(admin_client:send {
method = "DELETE",
path = "/consumers/consumer1/jwt/" .. credential_id,
})
assert.res_status(204, res)
-- Wait for cache to be invalidated
helpers.wait_for_invalidation(cache_key)
-- It should not work
res = assert(proxy_client:send {
method = "GET",
path = "/request",
headers = {
["Authorization"] = get_authorization("key123", "secret123"),
["Host"] = "jwt.com"
}
})
assert.res_status(401, res)
end)
it("should invalidate when JWT Auth Credential entity is updated", function()
-- It should work
local res = assert(proxy_client:send {
method = "GET",
path = "/request",
headers = {
["Authorization"] = get_authorization("key123", "secret123"),
["Host"] = "jwt.com"
}
})
assert.res_status(200, res)
-- It should not work
res = assert(proxy_client:send {
method = "GET",
path = "/request",
headers = {
["Authorization"] = get_authorization("keyhello", "secret123"),
["Host"] = "jwt.com"
}
})
assert.res_status(401, res)
-- Check that cache is populated
local cache_key = db.jwt_secrets:cache_key("key123")
res = assert(admin_client:send {
method = "GET",
path = "/cache/" .. cache_key,
})
assert.res_status(200, res)
-- Retrieve credential ID
res = assert(admin_client:send {
method = "GET",
path = "/consumers/consumer1/jwt/",
})
local body = cjson.decode(assert.res_status(200, res))
local credential_id = body.data[1].id
assert.truthy(credential_id)
-- Patch JWT credential (which triggers invalidation)
res = assert(admin_client:send {
method = "PATCH",
path = "/consumers/consumer1/jwt/" .. credential_id,
body = {
key = "keyhello"
},
headers = {
["Content-Type"] = "application/json"
}
})
assert.res_status(200, res)
-- Wait for cache to be invalidated
helpers.wait_for_invalidation(cache_key)
-- It should work
res = assert(proxy_client:send {
method = "GET",
path = "/request",
headers = {
["Authorization"] = get_authorization("keyhello", "secret123"),
["Host"] = "jwt.com"
}
})
assert.res_status(200, res)
-- It should not work
res = assert(proxy_client:send {
method = "GET",
path = "/request",
headers = {
["Authorization"] = get_authorization("key123", "secret123"),
["Host"] = "jwt.com"
}
})
assert.res_status(401, res)
end)
end)
describe("Consumer entity invalidation", function()
it("should invalidate when Consumer entity is deleted", function()
-- It should work
local res = assert(proxy_client:send {
method = "GET",
path = "/request",
headers = {
["Authorization"] = get_authorization("key123", "secret123"),
["Host"] = "jwt.com"
}
})
assert.res_status(200, res)
-- Check that cache is populated
local cache_key = db.jwt_secrets:cache_key("key123")
res = assert(admin_client:send {
method = "GET",
path = "/cache/" .. cache_key,
})
assert.res_status(200, res)
-- Delete Consumer (which triggers invalidation)
res = assert(admin_client:send {
method = "DELETE",
path = "/consumers/consumer1",
})
assert.res_status(204, res)
-- Wait for cache to be invalidated
helpers.wait_for_invalidation(cache_key)
-- It should not work
res = assert(proxy_client:send {
method = "GET",
path = "/request",
headers = {
["Authorization"] = get_authorization("key123", "secret123"),
["Host"] = "jwt.com"
}
})
assert.res_status(401, res)
end)
end)
end)
end