I am trying to understand how to use Plug.CSRFProtection in the intended way. So far I have written a custom plug:
In my endpoint:
plug(Plug.Session,
store: :cookie,
key: "session",
max_age: 43200,
http_only: true,
secure: true,
extra: "SameSite=Lax",
signing_salt: "my_signing_salt",
encryption_salt: "my_encryption_salt"
)
plug(:fetch_session)
plug(MyApp.Plugs.InitSession)
plug(Plug.CSRFProtection)
MyApp.Plugs.InitSession:
defmodule MyApp.Plugs.InitSession do
@behaviour Plug
import Plug.Conn
def init(opts), do: opts
def call(conn, _) do
if get_session(conn) == %{} do
init_session(conn)
else
conn
end
end
defp init_session(conn) do
csrf_token = generate_csrf_token()
unmasked_csrf_token = Process.get(:plug_unmasked_csrf_token)
conn
|> clear_session()
|> put_session("_csrf_token", unmasked_csrf_token)
|> put_csrf_resp_cookie(csrf_token)
end
defp generate_csrf_token() do
Plug.CSRFProtection.delete_csrf_token()
Plug.CSRFProtection.get_csrf_token()
end
defp put_csrf_resp_cookie(conn, csrf_token) do
put_resp_cookie(conn, "csrf_token", csrf_token)
end
end
On first access to the endpoint, the CSRF token is generated and put both in the session (the unmasked token) and sent back to the client (the masked token) via a cookie.
Is it the right way of using Plug.CSRFProtection? Should I access the process dictionary myself? Am I responsible to store the unmasked token in the session? The documentation states:
:session_key
- the name of the key in session to store the token under
so that makes me think that the plug was storing the token in the session automatically.
Sorry if I miss the obvious. After hours in the doc and the code of the plug, I still do not manage to understand it properly.