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

oauth2: Add custom TTL to refresh tokens #2942

Merged
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
9 changes: 7 additions & 2 deletions kong/plugins/oauth2/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ local function generate_token(conf, api, credential, authenticated_userid, scope
refresh_token = utils.random_string()
end

local refresh_token_ttl
if conf.refresh_token_ttl and conf.refresh_token_ttl > 0 then
refresh_token_ttl = conf.refresh_token_ttl
end

local api_id
if not conf.global_credentials then
api_id = api.id
Expand All @@ -53,8 +58,8 @@ local function generate_token(conf, api, credential, authenticated_userid, scope
expires_in = token_expiration,
refresh_token = refresh_token,
scope = scope
}, {ttl = token_expiration > 0 and 1209600 or nil}) -- Access tokens (and their associated refresh token) are being
-- permanently deleted after 14 days (1209600 seconds)
}, {ttl = token_expiration > 0 and refresh_token_ttl or nil}) -- Access tokens (and their associated refresh token) are being
-- permanently deleted after 'refresh_token_ttl' seconds

if err then
return responses.send_HTTP_INTERNAL_SERVER_ERROR(err)
Expand Down
18 changes: 18 additions & 0 deletions kong/plugins/oauth2/migrations/cassandra.lua
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,22 @@ return {
end,
down = function(_, _, dao) end -- not implemented
},
{
name = "2017-10-11-oauth2_new_refresh_token_ttl_config_value",
up = function(_, _, dao)
for ok, config, update in plugin_config_iterator(dao, "oauth2") do
if not ok then
return config
end
if config.refresh_token_ttl == nil then
config.refresh_token_ttl = 1209600
local _, err = update(config)
if err then
return err
end
end
end
end,
down = function(_, _, dao) end -- not implemented
}
}
18 changes: 18 additions & 0 deletions kong/plugins/oauth2/migrations/postgres.lua
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,22 @@ return {
end,
down = function(_, _, dao) end -- not implemented
},
{
name = "2017-10-11-oauth2_new_refresh_token_ttl_config_value",
up = function(_, _, dao)
for ok, config, update in plugin_config_iterator(dao, "oauth2") do
if not ok then
return config
end
if config.refresh_token_ttl == nil then
config.refresh_token_ttl = 1209600
local _, err = update(config)
if err then
return err
end
end
end
end,
down = function(_, _, dao) end -- not implemented
}
}
1 change: 1 addition & 0 deletions kong/plugins/oauth2/schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ return {
anonymous = {type = "string", default = "", func = check_user},
global_credentials = {type = "boolean", default = false},
auth_header_name = {required = false, type = "string", default = "authorization"},
refresh_token_ttl = {required = true, type = "number", default = 1209600} -- original hardcoded value - 14 days
},
self_check = function(schema, plugin_t, dao, is_update)
if not plugin_t.enable_authorization_code and not plugin_t.enable_implicit_grant
Expand Down
7 changes: 7 additions & 0 deletions spec/03-plugins/26-oauth2/01-schema_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ describe("Plugin: oauth2 (schema)", function()
assert.equal("hello", t.provision_key)
assert.equal("custom_header_name", t.auth_header_name)
end)
it("sets refresh_token_ttl to default value if not set", function()
local t = {enable_authorization_code = true, mandatory_scope = false}
local ok, errors = validate_entity(t, oauth2_schema)
assert.True(ok)
assert.is_nil(errors)
assert.equal(1209600, t.refresh_token_ttl)
end)
describe("errors", function()
it("requires at least one flow", function()
local ok, _, err = validate_entity({}, oauth2_schema)
Expand Down
111 changes: 111 additions & 0 deletions spec/03-plugins/26-oauth2/03-access_spec.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
local cjson = require "cjson"
local helpers = require "spec.helpers"
local utils = require "kong.tools.utils"
local fmt = string.format
local dao_helpers = require "spec.02-integration.03-dao.helpers"

local function provision_code(host, extra_headers, client_id)
local request_client = helpers.proxy_ssl_client()
Expand Down Expand Up @@ -2522,3 +2524,112 @@ describe("Plugin: oauth2 (access)", function()
end)

end)

dao_helpers.for_each_dao(function(kong_config)
describe("Plugin: oauth2 (ttl) with #"..kong_config.database, function()

local client

setup(function()

local api11 = assert(helpers.dao.apis:insert {
name = "api-11",
hosts = { "oauth2_11.com" },
upstream_url = "http://mockbin.com"
})

assert(helpers.dao.plugins:insert {
name = "oauth2",
api_id = api11.id,
config = {
enable_authorization_code = true,
mandatory_scope = false,
provision_key = "provision123",
anonymous = "",
global_credentials = false,
refresh_token_ttl = 2
}
})

local api12 = assert(helpers.dao.apis:insert {
name = "api-12",
hosts = { "oauth2_12.com" },
upstream_url = "http://mockbin.com"
})

assert(helpers.dao.plugins:insert {
name = "oauth2",
api_id = api12.id,
config = {
enable_authorization_code = true,
mandatory_scope = false,
provision_key = "provision123",
anonymous = "",
global_credentials = false,
refresh_token_ttl = 0
}
})

local consumer = assert(helpers.dao.consumers:insert {
username = "bob"
})
assert(helpers.dao.oauth2_credentials:insert {
client_id = "clientid123",
client_secret = "secret123",
redirect_uri = "http://google.com/kong",
name = "testapp",
consumer_id = consumer.id
})
assert(helpers.start_kong())
client = helpers.proxy_client()
end)

teardown(function()
if client then client:close() end
helpers.stop_kong()
end)

local function assert_ttls_records_for_token(uuid, count)
local DB = require "kong.dao.db.postgres"
local _db = DB.new(kong_config)
local query = fmt("SELECT COUNT(*) FROM ttls where table_name='oauth2_tokens' AND primary_uuid_value = '%s'", tostring(uuid))
local result, error = _db:query(query)
assert.falsy(error)
assert.truthy(result[1].count == count)
end

describe("refresh token", function()
it("is deleted after defined TTL", function()
local token = provision_token("oauth2_11.com")
local token_entity = helpers.dao.oauth2_tokens:find_all { access_token = token.access_token }
assert.equal(1, #token_entity)

if kong_config.database == "postgres" then
assert_ttls_records_for_token(token_entity[1].id, 1)
end

ngx.sleep(3)

token_entity = helpers.dao.oauth2_tokens:find_all { access_token = token.access_token }
assert.equal(0, #token_entity)
end)

it("is not deleted when when TTL is 0 == never", function()
local token = provision_token("oauth2_12.com")
local token_entity = helpers.dao.oauth2_tokens:find_all { access_token = token.access_token }
assert.equal(1, #token_entity)

if kong_config.database == "postgres" then
assert_ttls_records_for_token(token_entity[1].id, 0)
end

ngx.sleep(3)

token_entity = helpers.dao.oauth2_tokens:find_all { access_token = token.access_token }
assert.equal(1, #token_entity)
end)
end)

end)

end)