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 ngx.log(ngx.ERR, "Missing KEYCLOAK_CLIENT_SECRET env variable") ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) 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" } -- Step 1: login flow local auth_res, auth_err = openidc.authenticate(opts) if auth_err then ngx.status = 403 ngx.say("Authentication failed: " .. auth_err) ngx.exit(ngx.HTTP_FORBIDDEN) end -- 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("Access token not available") ngx.exit(ngx.HTTP_UNAUTHORIZED) end -- 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