diff --git a/kong/plugins/oauth2/access.lua b/kong/plugins/oauth2/access.lua index 1eb79d3bf16..c2465b2e342 100644 --- a/kong/plugins/oauth2/access.lua +++ b/kong/plugins/oauth2/access.lua @@ -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 @@ -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) diff --git a/kong/plugins/oauth2/migrations/cassandra.lua b/kong/plugins/oauth2/migrations/cassandra.lua index 5817d0430cc..135cbae0189 100644 --- a/kong/plugins/oauth2/migrations/cassandra.lua +++ b/kong/plugins/oauth2/migrations/cassandra.lua @@ -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 + } } diff --git a/kong/plugins/oauth2/migrations/postgres.lua b/kong/plugins/oauth2/migrations/postgres.lua index 220b37bf97b..885e7d93130 100644 --- a/kong/plugins/oauth2/migrations/postgres.lua +++ b/kong/plugins/oauth2/migrations/postgres.lua @@ -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 + } } diff --git a/kong/plugins/oauth2/schema.lua b/kong/plugins/oauth2/schema.lua index f558bb90761..5406620eed9 100644 --- a/kong/plugins/oauth2/schema.lua +++ b/kong/plugins/oauth2/schema.lua @@ -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 diff --git a/spec/03-plugins/26-oauth2/01-schema_spec.lua b/spec/03-plugins/26-oauth2/01-schema_spec.lua index 41eeb9e604f..9ee294be503 100644 --- a/spec/03-plugins/26-oauth2/01-schema_spec.lua +++ b/spec/03-plugins/26-oauth2/01-schema_spec.lua @@ -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) diff --git a/spec/03-plugins/26-oauth2/03-access_spec.lua b/spec/03-plugins/26-oauth2/03-access_spec.lua index 2a8a804d2f6..496bc3b242e 100644 --- a/spec/03-plugins/26-oauth2/03-access_spec.lua +++ b/spec/03-plugins/26-oauth2/03-access_spec.lua @@ -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() @@ -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) \ No newline at end of file