defmodule AuthN.SessionStorage.SignedCookie do
@moduledoc ~S"""
Module for storing sessions into signed cookies.
This is the library's default storage mechanism for storing sessions.
"""
@remember_me_cookie "user_remember_me"
@behaviour AuthN.SessionStorage
import Plug.Conn
@type conn :: %Plug.Conn{}
@spec get_user_token(conn) :: {term | nil, conn}
def get_user_token(conn) do
if user_token = get_session(conn, :user_token) do
{user_token, conn}
else
conn = fetch_cookies(conn, signed: [@remember_me_cookie])
if user_token = conn.cookies[@remember_me_cookie] do
{user_token, put_session(conn, :user_token, user_token)}
else
{nil, conn}
end
end
end
@spec put_user_token(conn, term) :: conn
def put_user_token(conn, user_token, opts \\ []) do
conn
|> renew_session()
|> put_session(:user_token, user_token)
|> maybe_write_remember_me_cookie(user_token, opts)
end
defp maybe_write_remember_me_cookie(conn, token, max_days: max_days) when is_integer(max_days) do
put_resp_cookie(conn, @remember_me_cookie, token, [sign: true, max_age: max_days * 60 * 24 * 60])
end
defp maybe_write_remember_me_cookie(conn, _token, _opts) do
conn
end
@spec delete_user_token(conn, function) :: conn
def delete_user_token(conn, delete_session_token_fun \\ &(&1)) do
user_token = get_session(conn, :user_token)
user_token && delete_session_token_fun.(user_token)
conn
|> renew_session()
|> delete_resp_cookie(@remember_me_cookie)
end
defp renew_session(conn) do
conn
|> configure_session(renew: true)
|> clear_session()
end
end