Files
2026-07-13 12:32:21 +08:00

116 lines
3.9 KiB
Lua

local url = require "socket.url"
local typedefs = require "kong.db.schema.typedefs"
local secret = require "kong.plugins.oauth2.secret"
local assert = assert
local function validate_uri(uri)
local parsed_uri = url.parse(uri)
if not (parsed_uri and parsed_uri.host and parsed_uri.scheme) then
return nil, "cannot parse '" .. uri .. "'"
end
if parsed_uri.fragment ~= nil then
return nil, "fragment not allowed in '" .. uri .. "'"
end
return true
end
local oauth2_credentials = {
primary_key = { "id" },
name = "oauth2_credentials",
cache_key = { "client_id" },
endpoint_key = "client_id",
workspaceable = true,
admin_api_name = "oauth2",
fields = {
{ id = typedefs.uuid },
{ created_at = typedefs.auto_timestamp_s },
{ consumer = { type = "foreign", reference = "consumers", required = true, on_delete = "cascade", }, },
{ name = { type = "string", required = true }, },
{ client_id = { type = "string", required = false, unique = true, auto = true }, },
{ client_secret = { type = "string", required = false, auto = true, encrypted = true }, }, -- encrypted = true is a Kong Enterprise Exclusive feature. It does nothing in Kong CE
{ hash_secret = { type = "boolean", required = true, default = false }, },
{ redirect_uris = {
type = "array",
required = false,
elements = {
type = "string",
custom_validator = validate_uri,
}, }, },
{ tags = typedefs.tags },
{ client_type = { type = "string", required = true, default = "confidential", one_of = { "confidential", "public" }, }, },
},
transformations = {
{
input = { "hash_secret" },
needs = { "client_secret" },
on_write = function(hash_secret, client_secret)
if not hash_secret then
return {}
end
local hash = assert(secret.hash(client_secret))
return {
client_secret = hash,
}
end,
},
},
}
local oauth2_authorization_codes = {
primary_key = { "id" },
name = "oauth2_authorization_codes",
ttl = true,
workspaceable = true,
generate_admin_api = false,
db_export = false,
fields = {
{ id = typedefs.uuid },
{ created_at = typedefs.auto_timestamp_s },
{ service = { type = "foreign", reference = "services", default = ngx.null, on_delete = "cascade", }, },
{ credential = { type = "foreign", reference = "oauth2_credentials", required = true, on_delete = "cascade", }, },
{ code = { type = "string", required = false, unique = true, auto = true }, }, -- FIXME immutable
{ authenticated_userid = { type = "string", required = false }, },
{ scope = { type = "string" }, },
{ challenge = { type = "string", required = false }},
{ challenge_method = { type = "string", required = false, one_of = { "S256" } }},
{ plugin = { type = "foreign", reference = "plugins", default = ngx.null, on_delete = "cascade", }, },
},
}
local BEARER = "bearer"
local oauth2_tokens = {
primary_key = { "id" },
name = "oauth2_tokens",
endpoint_key = "access_token",
cache_key = { "access_token" },
dao = "kong.plugins.oauth2.daos.oauth2_tokens",
ttl = true,
workspaceable = true,
fields = {
{ id = typedefs.uuid },
{ created_at = typedefs.auto_timestamp_s },
{ service = { type = "foreign", reference = "services", default = ngx.null, on_delete = "cascade", }, },
{ credential = { type = "foreign", reference = "oauth2_credentials", required = true, on_delete = "cascade", }, },
{ token_type = { type = "string", required = true, one_of = { BEARER }, default = BEARER }, },
{ expires_in = { type = "integer", required = true }, },
{ access_token = { type = "string", required = false, unique = true, auto = true }, },
{ refresh_token = { type = "string", required = false, unique = true }, },
{ authenticated_userid = { type = "string", required = false }, },
{ scope = { type = "string" }, },
},
}
return {
oauth2_credentials,
oauth2_authorization_codes,
oauth2_tokens,
}