local ngx = require("ngx") local b64 = require("ssso_base64") local util = require("ssso_util") local conf = require("ssso_config") local class__request = {} local function str_starts_with(str, begin) local i, _ = str:find(util.str_to_pattern(begin)) return 1 == i end function class__request:current() local vars = ngx.var local request = { referer = vars.http_referer, host = vars.host, method = vars.request_method, uri = vars.request_uri, } setmetatable(request, {__index = self}) if request.referer == "" then request.referer = nil end local target, qp = request.uri, {} local qm, _ = target:find("%?") if qm then qp = ngx.decode_args(target:sub(qm + 1)) target = target:sub(1, qm - 1) end request["target"] = target request["query_params"] = qp local https = vars.proxy_https or vars.https if https and https ~= "" then request["scheme"] = "https" else request["scheme"] = "http" end return request end function class__request:with_post_parameters() ngx.req.read_body() local args, _ = ngx.req.get_post_args() if args then for key, val in pairs(args) do self.query_params[key] = val end end return self end function class__request:has_method(method) return string.upper(method) == string.upper(self.method) end function class__request:is(url) return self.target == url end function class__request:matches(lua_pattern) return self.target:match(lua_pattern) end function class__request:starts_with(prefix) return str_starts_with(self.target, prefix) end function class__request:has_param(param, value) return self.query_params[param] ~= nil and (value == nil or self.query_params[param] == value) end local function get_basic_auth() local header = ngx.var.Authentication if (not header) or (#header < 7) or (not str_starts_with(header, "Basic ")) then return nil, nil end local text, _ = b64.decode_base64(header:sub(7)) if not text then ngx.log(ngx.DEBUG, "Invalid Authentication header: " .. header) return nil, nil end local colon colon, _ = text:find(":") if not colon then return nil, nil end local login, password = "", "" if colon > 1 then login = text:sub(1, colon - 1) end if colon < #text then password = text:sub(colon + 1, #text) end return login, password end local function get_jws_cookie() return ngx.var.cookie_SSSO_TOKEN end local function set_jws_cookie(jws, tslimit) ngx.header["Set-Cookie"] = "SSSO_TOKEN=" .. jws .. "; Path=/; Expires=" .. ngx.cookie_time(tslimit) .. "; Secure" end local function get_seconds_since_epoch() return math.floor(ngx.now()) end local function add_cookie(name, value) local cookie = name .. "=" .. value local old_cookie = ngx.var.http_cookie if old_cookie and old_cookie ~= "" then cookie = old_cookie .. "; " .. cookie end ngx.log(ngx.DEBUG, "Overriding request Cookie header: " .. cookie) ngx.req.set_header("Cookie", cookie) end local function add_header(name, value) ngx.log(ngx.DEBUG, "Setting request " .. name .. " header: " .. value) ngx.req.set_header(name, value) end local function answer_not_found(req_data) return ngx.exit(404) end local function answer_unexpected_error() ngx.log(ngx.ERROR, "Unexpected Simple-SSO error.") return ngx.exit(500) end local function redirect_to_page(uri) return ngx.redirect("https://" .. conf.get_sso_host() .. uri, 302) end local function redirect_to_login(req_data, status) return ngx.redirect("https://" .. conf.get_sso_host() .. conf.get_sso_prefix() .. "/login?back=" .. ngx.escape_uri(req_data.uri) .. "&cause=" .. tostring(status), 307) end local function redirect_to_portal() return ngx.redirect("https://" .. conf.get_sso_host() .. conf.get_sso_prefix() .. "/portal", 307) end local function return_contents(contents, mime_and_charset) ngx.header["Content-Type"] = mime_and_charset ngx.header["Content-Length"] = tostring(#contents) ngx.header["Cache-Control"] = "no-store,max-age=0" ngx.say(contents) -- TODO: CSRF return ngx.exit(200) end local function forward_request(req_data) return end return { add_cookie = add_cookie, add_header = add_header, answer_not_found = answer_not_found, class__request = class__request, forward_request = forward_request, get_basic_auth = get_basic_auth, get_jws_cookie = get_jws_cookie, get_seconds_since_epoch = get_seconds_since_epoch, redirect_to_login = redirect_to_login, redirect_to_page = redirect_to_page, redirect_to_portal = redirect_to_portal, return_contents = return_contents, set_jws_cookie = set_jws_cookie, answer_unexpected_error = answer_unexpected_error, }