local M = {}
function M.client(url)
local base_url = url:gsub("/+$", "")
local function fetch_discovery()
local resp = http.get(base_url .. "/.well-known/openid-configuration", { headers = {} })
if resp.status ~= 200 then
error("dex.discovery: HTTP " .. resp.status .. ": " .. resp.body)
end
return json.parse(resp.body)
end
local c = {}
c.discovery = {}
function c.discovery:config()
return fetch_discovery()
end
function c.discovery:jwks()
local config = fetch_discovery()
if not config.jwks_uri then
error("dex.jwks: discovery response missing jwks_uri")
end
local resp = http.get(config.jwks_uri, { headers = {} })
if resp.status ~= 200 then
error("dex.jwks: HTTP " .. resp.status .. ": " .. resp.body)
end
return json.parse(resp.body)
end
function c.discovery:issuer()
local config = fetch_discovery()
return config.issuer
end
function c.discovery:has_endpoint(endpoint_name)
local config = fetch_discovery()
return config[endpoint_name] ~= nil
end
c.health = {}
function c.health:check()
local resp = http.get(base_url .. "/healthz", { headers = {} })
return resp.status == 200
end
function c.health:ready()
return c.health:check()
end
c.scopes = {}
function c.scopes:list()
local config = fetch_discovery()
return config.scopes_supported or {}
end
function c.scopes:supports(scope)
local scopes = c.scopes:list()
for _, s in ipairs(scopes) do
if s == scope then
return true
end
end
return false
end
c.grants = {}
function c.grants:list()
local config = fetch_discovery()
return config.grant_types_supported or {}
end
function c.grants:supports(grant_type)
local types = c.grants:list()
for _, gt in ipairs(types) do
if gt == grant_type then
return true
end
end
return false
end
function c.grants:response_types()
local config = fetch_discovery()
return config.response_types_supported or {}
end
function c:validate_config()
local errors = {}
local ok, config = pcall(fetch_discovery)
if not ok then
return { ok = false, errors = { "discovery failed: " .. tostring(config) } }
end
if not config.issuer then
errors[#errors + 1] = "missing issuer"
else
if config.issuer ~= base_url then
errors[#errors + 1] = "issuer mismatch: expected " .. base_url .. ", got " .. config.issuer
end
end
if not config.authorization_endpoint then
errors[#errors + 1] = "missing authorization_endpoint"
end
if not config.token_endpoint then
errors[#errors + 1] = "missing token_endpoint"
end
if not config.jwks_uri then
errors[#errors + 1] = "missing jwks_uri"
end
return { ok = #errors == 0, errors = errors }
end
function c:admin_version()
local ok, result = pcall(function()
local resp = http.get(base_url .. "/api/v1/version", { headers = {} })
if resp.status ~= 200 then
error("HTTP " .. resp.status)
end
return json.parse(resp.body)
end)
if ok then
return result
end
return nil
end
return c
end
return M