luci-base: remove security token from urls
authorJo-Philipp Wich <jow@openwrt.org>
Tue, 20 Oct 2015 22:31:27 +0000 (00:31 +0200)
committerJo-Philipp Wich <jow@openwrt.org>
Tue, 20 Oct 2015 22:31:27 +0000 (00:31 +0200)
Now that sensitive urls require post requests and only accept them if a valid
security token is sent along the request, we can drop the global random url
token to improve LuCI usability.

The main improvement is the ability to use multiple tabs with the same login
session, but also deep linking to specific urls without the need for another
login becomes feasible, e.g. for documentation purposes.

Signed-off-by: Jo-Philipp Wich <jow@openwrt.org>
modules/luci-base/luasrc/dispatcher.lua

index df562dd5dadabfcc79439111bc900add4cd6d87a..bb02912f4b21543cec6524e49f030457b267683b 100644 (file)
@@ -113,24 +113,11 @@ function authenticator.htmlauth(validator, accs, default)
                return user
        end
 
-       if context.urltoken.stok then
-               context.urltoken.stok = nil
-
-               local cookie = 'sysauth=%s; expires=%s; path=%s/' %{
-                   http.getcookie('sysauth') or 'x',
-                       'Thu, 01 Jan 1970 01:00:00 GMT',
-                       build_url()
-               }
-
-               http.header("Set-Cookie", cookie)
-               http.redirect(build_url())
-       else
-               require("luci.i18n")
-               require("luci.template")
-               context.path = {}
-               http.status(403, "Forbidden")
-               luci.template.render("sysauth", {duser=default, fuser=user})
-       end
+       require("luci.i18n")
+       require("luci.template")
+       context.path = {}
+       http.status(403, "Forbidden")
+       luci.template.render("sysauth", {duser=default, fuser=user})
 
        return false
 
@@ -151,18 +138,8 @@ function httpdispatch(request, prefix)
                end
        end
 
-       local tokensok = true
        for node in pathinfo:gmatch("[^/]+") do
-               local tkey, tval
-               if tokensok then
-                       tkey, tval = node:match(";(%w+)=([a-fA-F0-9]*)")
-               end
-               if tkey then
-                       context.urltoken[tkey] = tval
-               else
-                       tokensok = false
-                       r[#r+1] = node
-               end
+               r[#r+1] = node
        end
 
        local stat, err = util.coxpcall(function()
@@ -311,13 +288,14 @@ function dispatch(request)
                   resource    = luci.config.main.resourcebase;
                   ifattr      = function(...) return _ifattr(...) end;
                   attr        = function(...) return _ifattr(true, ...) end;
-                  token       = ctx.urltoken.stok;
                   url         = build_url;
                }, {__index=function(table, key)
                        if key == "controller" then
                                return build_url()
                        elseif key == "REQUEST_URI" then
                                return build_url(unpack(ctx.requestpath))
+                       elseif key == "token" then
+                               return ctx.authtoken
                        else
                                return rawget(table, key) or _G[key]
                        end
@@ -340,20 +318,17 @@ function dispatch(request)
                local def  = (type(track.sysauth) == "string") and track.sysauth
                local accs = def and {track.sysauth} or track.sysauth
                local sess = ctx.authsession
-               local verifytoken = false
                if not sess then
                        sess = http.getcookie("sysauth")
                        sess = sess and sess:match("^[a-f0-9]*$")
-                       verifytoken = true
                end
 
                local sdat = (util.ubus("session", "get", { ubus_rpc_session = sess }) or { }).values
-               local user
+               local user, token
 
                if sdat then
-                       if not verifytoken or ctx.urltoken.stok == sdat.token then
-                               user = sdat.user
-                       end
+                       user = sdat.user
+                       token = sdat.token
                else
                        local eu = http.getenv("HTTP_AUTH_USER")
                        local ep = http.getenv("HTTP_AUTH_PASS")
@@ -390,8 +365,8 @@ function dispatch(request)
                                                   sess, build_url()
                                                })
 
-                                               ctx.urltoken.stok = token
                                                ctx.authsession = sess
+                                               ctx.authtoken = token
                                                ctx.authuser = user
 
                                                http.redirect(build_url(unpack(ctx.requestpath)))
@@ -403,6 +378,7 @@ function dispatch(request)
                        end
                else
                        ctx.authsession = sess
+                       ctx.authtoken = token
                        ctx.authuser = user
                end
        end
@@ -414,7 +390,7 @@ function dispatch(request)
                        return
                end
 
-               if http.formvalue("token") ~= ctx.urltoken.stok then
+               if http.formvalue("token") ~= ctx.authtoken then
                        http.status(403, "Forbidden")
                        luci.template.render("csrftoken")
                        return