From c9a6d1656585556367915b0b8e3007d129ec9280 Mon Sep 17 00:00:00 2001 From: Kload Date: Fri, 31 Jan 2014 21:25:46 +0100 Subject: [PATCH] Improve cross-domain authentication --- access.lua | 138 +++++++++++++++-------------------------------------- 1 file changed, 38 insertions(+), 100 deletions(-) diff --git a/access.lua b/access.lua index bc37e85..4092d61 100644 --- a/access.lua +++ b/access.lua @@ -62,10 +62,16 @@ end function set_auth_cookie (user, domain) local maxAge = oneweek local expire = ngx.req.start_time() + maxAge + local session_key = cache:get("session_"..user) + if not session_key then + session_key = tostring(math.random(1111111, 9999999)) + cache:add("session_"..user, session_key) + end local hash = ngx.md5(srvkey.. "|" ..ngx.var.remote_addr.. "|"..user.. - "|"..expire) + "|"..expire.. + "|"..session_key) local cookie_str = "; Domain=."..domain.. "; Path=/".. "; Max-Age="..maxAge @@ -111,11 +117,15 @@ function is_logged_in () -- Check expire time if (ngx.req.start_time() <= tonumber(ngx.var.cookie_SSOwAuthExpire)) then -- Check hash - local hash = ngx.md5(srvkey.. - "|"..ngx.var.remote_addr.. - "|"..ngx.var.cookie_SSOwAuthUser.. - "|"..ngx.var.cookie_SSOwAuthExpire) - return hash == ngx.var.cookie_SSOwAuthHash + local session_key = cache:get("session_"..ngx.var.cookie_SSOwAuthUser) + if session_key and session_key ~= "" then + local hash = ngx.md5(srvkey.. + "|"..ngx.var.remote_addr.. + "|"..ngx.var.cookie_SSOwAuthUser.. + "|"..ngx.var.cookie_SSOwAuthExpire.. + "|"..session_key) + return hash == ngx.var.cookie_SSOwAuthHash + end end end @@ -451,20 +461,12 @@ function do_login () if authenticate(args.user, args.password) then ngx.status = ngx.HTTP_CREATED - local redirect_url = ngx.var.cookie_SSOwAuthRedirect + set_auth_cookie(args.user, ngx.var.host) if uri_args.r then - redirect_url = ngx.decode_base64(uri_args.r) + return redirect(portal_url.."?r="..uri_args.r) + else + return redirect(portal_url) end - if not redirect_url then redirect_url = portal_url end - login[args.user] = {} - login[args.user]["redirect_url"] = redirect_url - login[args.user]["domains"] = {} - for _, value in ipairs(conf["domains"]) do - table.insert(login[args.user]["domains"], value) - end - - -- Connect to the first domain (self) - return redirect(ngx.var.scheme.."://"..ngx.var.http_host.."/?ssologin="..args.user) else ngx.status = ngx.HTTP_UNAUTHORIZED flash("fail", "Wrong username/password combination") @@ -475,71 +477,12 @@ end function do_logout() local args = ngx.req.get_uri_args() if is_logged_in() then - local redirect_url = portal_url - if args.r then - redirect_url = ngx.decode_base64(args.r) - end - local user = ngx.var.cookie_SSOwAuthUser - logout[user] = {} - logout[user]["redirect_url"] = redirect_url - logout[user]["domains"] = {} - for _, value in ipairs(conf["domains"]) do - table.insert(logout[user]["domains"], value) - end - return redirect(ngx.var.scheme.."://"..ngx.var.http_host.."/?ssologout="..user) - else + cache:delete("session_"..ngx.var.cookie_SSOwAuthUser) flash("info", "Logged out") return redirect(portal_url) end end -function login_walkthrough (user) - -- Set Authentication cookies - set_auth_cookie(user, ngx.var.host) - -- Remove domain from login table - domain_key = is_in_table(login[user]["domains"], ngx.var.host) - table.remove(login[user]["domains"], domain_key) - - if table.getn(login[user]["domains"]) == 0 then - -- All the redirections has been made - local redirect_url = login[user]["redirect_url"] - login[user] = nil - if redirect_url == portal_url then - flash("win", "Logged in") - end - return redirect(redirect_url) - else - -- Redirect to the next domain - for _, domain in ipairs(login[user]["domains"]) do - return redirect(ngx.var.scheme.."://"..domain.."/?ssologin="..user) - end - end -end - -function logout_walkthrough (user) - -- Expire Authentication cookies - delete_cookie() - -- Remove domain from logout table - domain_key = is_in_table(logout[user]["domains"], ngx.var.host) - table.remove(logout[user]["domains"], domain_key) - - if table.getn(logout[user]["domains"]) == 0 then - -- All the redirections has been made - local redirect_url = logout[user]["redirect_url"] - logout[user] = nil - if redirect_url == portal_url then - flash("info", "Logged out") - end - return redirect(redirect_url) - else - -- Redirect to the next domain - for _, domain in ipairs(logout[user]["domains"]) do - return redirect(ngx.var.scheme.."://"..domain.."/?ssologout="..user) - end - end -end - - function redirect (url) ngx.header["Set-Cookie"] = cookies return ngx.redirect(url) @@ -556,26 +499,6 @@ end -- Routing -- --- Logging in/out --- i.e. http://mydomain.org/?ssologin=myuser - -if ngx.var.request_method == "GET" then - local args = ngx.req.get_uri_args() - - -- In login loop - local user = args.ssologin - if user and login[user] then - return login_walkthrough(user) - end - - -- In logout loop - user = args.ssologout - if user and logout[user] then - return logout_walkthrough(user) - end -end - - -- Portal -- i.e. http://mydomain.org/ssowat/* @@ -594,6 +517,11 @@ then -- Logout return do_logout() + elseif is_logged_in() and uri_args.r then + cda_key = tostring(math.random(1111111, 9999999)) + login[cda_key] = ngx.var.cookie_SSOwAuthUser + return redirect(ngx.decode_base64(uri_args.r).."~sso~"..cda_key) + elseif is_logged_in() -- Authenticated or ngx.var.uri == conf["portal_path"] -- OR Want to serve portal login or (string.starts(ngx.var.uri, conf["portal_path"].."assets") @@ -628,6 +556,18 @@ then end end +-- Logging in +-- i.e. http://mydomain.org/~sso~a6e5320f + +if string.match(ngx.var.uri, "~sso~%d+$") then + cda_key = string.sub(ngx.var.uri, -7) + if login[cda_key] then + set_auth_cookie(login[cda_key], ngx.var.host) + login[cda_key] = nil + return redirect(string.gsub(ngx.var.uri, "~sso~%d+$", "")) + end +end + -- Skipped urls -- i.e. http://mydomain.org/no_protection/ @@ -661,8 +601,6 @@ if is_logged_in() then end set_headers() return pass() -else - delete_cookie() end