diff --git a/auth.lua b/auth.lua index 3754040..ba576e6 100644 --- a/auth.lua +++ b/auth.lua @@ -1,4 +1,6 @@ local openidc = require("resty.openidc") +local http = require("resty.http") +local cjson = require("cjson") local client_secret = os.getenv("KEYCLOAK_CLIENT_SECRET") if not client_secret then @@ -7,46 +9,57 @@ if not client_secret then end local opts = { + redirect_uri_path = "/redirect_uri", discovery = "https://kc.boomlab.party/realms/rhein-sw/.well-known/openid-configuration", client_id = "demo-sso", client_secret = client_secret, + scope = "openid email profile", ssl_verify = "no" } --- Extract token from session or request -local session = require("resty.session").start() -local access_token = session.data.access_token - -if not access_token then - -- fallback: try Authorization header - local auth_header = ngx.var.http_Authorization - if auth_header and auth_header:find("Bearer ") == 1 then - access_token = auth_header:sub(8) - end -end - -if not access_token then - ngx.status = 401 - ngx.say("Missing access token") - ngx.exit(ngx.HTTP_UNAUTHORIZED) -end - --- Introspect the token -local res, err = openidc.introspect(opts, access_token) - -if err then +-- Step 1: login flow +local auth_res, auth_err = openidc.authenticate(opts) +if auth_err then ngx.status = 403 - ngx.say("Token introspection failed: " .. err) + ngx.say("Authentication failed: " .. auth_err) ngx.exit(ngx.HTTP_FORBIDDEN) end -if not res.active then +-- Step 2: get token from session or result +local session = require("resty.session").start() +local access_token = session.data.access_token or auth_res.access_token + +if not access_token then ngx.status = 401 - ngx.say("Session expired or revoked") + ngx.say("Access token not available") ngx.exit(ngx.HTTP_UNAUTHORIZED) end --- Optionally set headers for upstream -ngx.req.set_header("X-User", res.username or "") -ngx.req.set_header("X-Email", res.email or "") -ngx.status = 204 +-- Step 3: validate token on each request via introspection +local httpc = http.new() +local res, err = httpc:request_uri("https://kc.boomlab.party/realms/rhein-sw/protocol/openid-connect/token/introspect", { + method = "POST", + body = "token=" .. access_token .. "&client_id=" .. opts.client_id .. "&client_secret=" .. opts.client_secret, + headers = { + ["Content-Type"] = "application/x-www-form-urlencoded" + }, + ssl_verify = false, +}) + +if not res or res.status ~= 200 then + ngx.status = 500 + ngx.say("Failed to introspect token: " .. (err or (res and res.body or "unknown error"))) + ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) +end + +local token_info = cjson.decode(res.body) +if not token_info.active then + local session = require("resty.session").start() + session:destroy() + return openidc.authenticate(opts) +end + +-- Step 4: allow proxying the request +ngx.req.set_header("X-User", auth_res.user.preferred_username or "") +ngx.req.set_header("X-Email", auth_res.user.email or "") +-- Don't return anything here — let NGINX continue to proxy the request