Short circuit user verification if cookie is present.
authorRoger Braun <roger@rogerbraun.net>
Thu, 30 Mar 2017 13:29:49 +0000 (15:29 +0200)
committerRoger Braun <roger@rogerbraun.net>
Thu, 30 Mar 2017 13:29:49 +0000 (15:29 +0200)
lib/pleroma/plugs/authentication_plug.ex
test/plugs/authentication_plug_test.exs

index 90bd07b911bcca4dcb36872120b500fafcc0f562..a3317f432d5de1041b67e76ba754bfa3dc4c9073 100644 (file)
@@ -8,20 +8,28 @@ defmodule Pleroma.Plugs.AuthenticationPlug do
   def call(conn, opts) do
     with {:ok, username, password} <- decode_header(conn),
          {:ok, user} <- opts[:fetcher].(username),
-         {:ok, verified_user} <- verify(user, password)
+         saved_user_id <- get_session(conn, :user_id),
+         {:ok, verified_user} <- verify(user, password, saved_user_id)
     do
-      conn |> assign(:user, verified_user)
+      conn
+      |> assign(:user, verified_user)
+      |> put_session(:user_id, verified_user.id)
     else
       _ -> conn |> halt_or_continue(opts)
     end
   end
 
-  defp verify(nil, _password) do
+  # Short-circuit if we have a cookie with the id for the given user.
+  defp verify(%{id: id} = user, _password, id) do
+    {:ok, user}
+  end
+
+  defp verify(nil, _password, _user_id) do
     Comeonin.Pbkdf2.dummy_checkpw
     :error
   end
 
-  defp verify(user, password) do
+  defp verify(user, password, _user_id) do
     if Comeonin.Pbkdf2.checkpw(password, user.password_hash) do
       {:ok, user}
     else
index 3f2f769e73e1125ce13d5d425c004db252894306..6f1568ec39588f7c73234c0d363275f1330884b6 100644 (file)
@@ -13,6 +13,12 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
     password_hash: Comeonin.Pbkdf2.hashpwsalt("guy")
   }
 
+  @session_opts [
+    store: :cookie,
+    key: "_test",
+    signing_salt: "cooldude"
+  ]
+
   defp fetch_user(_name) do
     {:ok, @user}
   end
@@ -23,14 +29,20 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
 
   describe "without an authorization header" do
     test "it halts the application" do
-      conn = build_conn() |> AuthenticationPlug.call(%{})
+      conn = build_conn()
+      |> Plug.Session.call(Plug.Session.init(@session_opts))
+      |> fetch_session
+      |> AuthenticationPlug.call(%{})
 
       assert conn.status == 403
       assert conn.halted == true
     end
 
     test "it assigns a nil user if the 'optional' option is used" do
-      conn = build_conn() |> AuthenticationPlug.call(%{optional: true})
+      conn = build_conn()
+      |> Plug.Session.call(Plug.Session.init(@session_opts))
+      |> fetch_session
+      |> AuthenticationPlug.call(%{optional: true})
 
       assert %{ user: nil } == conn.assigns
     end
@@ -40,6 +52,8 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
     test "it halts the application" do
       conn =
         build_conn()
+        |> Plug.Session.call(Plug.Session.init(@session_opts))
+        |> fetch_session
         |> AuthenticationPlug.call(%{fetcher: &fetch_nil/1})
 
       assert conn.status == 403
@@ -49,6 +63,8 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
     test "it assigns a nil user if the 'optional' option is used" do
       conn =
         build_conn()
+        |> Plug.Session.call(Plug.Session.init(@session_opts))
+        |> fetch_session
         |> AuthenticationPlug.call(%{optional: true, fetcher: &fetch_nil/1 })
 
       assert %{ user: nil } == conn.assigns
@@ -65,6 +81,8 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
 
       conn =
         build_conn()
+        |> Plug.Session.call(Plug.Session.init(@session_opts))
+        |> fetch_session
         |> put_req_header("authorization", header)
         |> AuthenticationPlug.call(opts)
 
@@ -82,6 +100,8 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
 
       conn =
         build_conn()
+        |> Plug.Session.call(Plug.Session.init(@session_opts))
+        |> fetch_session
         |> put_req_header("authorization", header)
         |> AuthenticationPlug.call(opts)
 
@@ -90,7 +110,7 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
   end
 
   describe "with a correct authorization header for an existing user" do
-    test "it assigns the user" do
+    test "it assigns the user", %{conn: conn} do
       opts = %{
         optional: true,
         fetcher: &fetch_user/1
@@ -98,12 +118,35 @@ defmodule Pleroma.Plugs.AuthenticationPlugTest do
 
       header = basic_auth_enc("dude", "guy")
 
-      conn =
-        build_conn()
+      conn = conn
+        |> Plug.Session.call(Plug.Session.init(@session_opts))
+        |> fetch_session
+        |> put_req_header("authorization", header)
+        |> AuthenticationPlug.call(opts)
+
+      assert %{ user: @user } == conn.assigns
+      assert get_session(conn, :user_id) == @user.id
+      assert conn.halted == false
+    end
+  end
+  describe "with a user_id in the session for an existing user" do
+    test "it assigns the user", %{conn: conn} do
+      opts = %{
+        optional: true,
+        fetcher: &fetch_user/1
+      }
+
+      header = basic_auth_enc("dude", "THIS IS WRONG")
+
+      conn = conn
+        |> Plug.Session.call(Plug.Session.init(@session_opts))
+        |> fetch_session
+        |> put_session(:user_id, @user.id)
         |> put_req_header("authorization", header)
         |> AuthenticationPlug.call(opts)
 
       assert %{ user: @user } == conn.assigns
+      assert get_session(conn, :user_id) == @user.id
       assert conn.halted == false
     end
   end