Packages
pow
0.1.0-alpha.3
1.0.39
1.0.38
1.0.37
1.0.36
1.0.35
1.0.34
1.0.33
1.0.32
1.0.31
1.0.30
1.0.29
1.0.28
1.0.27
1.0.26
1.0.25
1.0.24
1.0.23
1.0.22
1.0.21
1.0.20
1.0.19
1.0.18
1.0.17
1.0.16
1.0.15
1.0.14
1.0.13
1.0.12
1.0.11
1.0.10
1.0.9
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
1.0.0-rc.4
1.0.0-rc.3
1.0.0-rc.2
1.0.0-rc.1
1.0.0-rc.0
0.1.0-rc.1
0.1.0-alpha.8
0.1.0-alpha.7
retired
0.1.0-alpha.6
0.1.0-alpha.5
0.1.0-alpha.4
0.1.0-alpha.3
0.1.0-alpha.2
0.1.0-alpha.1
0.1.0-alpha
Robust user authentication solution
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/extensions/persistent_session/plug/cookie.ex
defmodule PowPersistentSession.Plug.Cookie do
@moduledoc """
This plug will handle persistent user sessions with cookies.
By default, the cookie will expire after 30 days. The cookie expiration will
be renewed on every request. The token in the cookie can only be used once to
create a session.
## Example
defmodule MyAppWeb.Endpoint do
# ...
plug Pow.Plug.Session, otp_app: :my_app_web
plug PowPersistentSession.Plug.Cookie
#...
end
## Configuration options
* `:persistent_session_store` the persistent session store
* `:cache_store_backend` the backend cache store
* `:persistent_session_cookie_key` session key name
* `:persistent_session_cookie_max_age` max age for cookie
"""
use PowPersistentSession.Plug.Base
alias Plug.Conn
alias Pow.{Config, Plug}
@cookie_key "persistent_session_cookie"
@ttl Integer.floor_div(:timer.hours(24) * 30, 1000)
@doc """
Sets a persistent session cookie with an auto generated token, and sets the
token as a key in the persistent session cache with the credentials.
"""
@spec create(Conn.t(), map(), Config.t()) :: Conn.t()
def create(conn, %{id: user_id}, config) do
{store, store_config} = store(config)
cookie_key = cookie_key(config)
key = Pow.UUID.generate()
value = user_id
opts = session_opts(config)
store.put(store_config, key, value)
Conn.put_resp_cookie(conn, cookie_key, key, opts)
end
@doc """
If a persistent session cookie exists, it'll be expired, and the key in the
persistent session cache will be removed.
"""
@spec delete(Conn.t(), Config.t()) :: Conn.t()
def delete(conn, config) do
cookie_key = cookie_key(config)
case conn.req_cookies[cookie_key] do
nil -> conn
key_id -> do_delete(conn, cookie_key, key_id, config)
end
end
defp do_delete(conn, cookie_key, key_id, config) do
{store, store_config} = store(config)
value = ""
opts = [max_age: -1, path: "/"]
store.delete(store_config, key_id)
Conn.put_resp_cookie(conn, cookie_key, value, opts)
end
@doc """
If a persistent session cookie exists, it'll fetch the credentials from the
persistent session cache, and create a new session and persistent session
cookie. The old persistent session cookie and session cache credentials will
be removed.
The cookie expiration will automatically be renewed on every request.
"""
@spec authenticate(Conn.t(), Config.t()) :: Conn.t()
def authenticate(conn, config) do
user = Plug.current_user(conn)
conn
|> Conn.fetch_cookies()
|> maybe_authenticate(user, config)
|> maybe_renew(config)
end
defp maybe_authenticate(conn, nil, config) do
cookie_key = cookie_key(config)
case conn.req_cookies[cookie_key] do
nil -> conn
key_id -> do_authenticate(conn, key_id, config)
end
end
defp maybe_authenticate(conn, _user, _config), do: conn
defp do_authenticate(conn, key_id, config) do
{store, store_config} = store(config)
mod = config[:mod]
store_config
|> store.get(key_id)
|> maybe_fetch_user(config)
|> case do
nil ->
delete(conn, config)
user ->
conn
|> delete(config)
|> create(user, config)
|> mod.do_create(user)
end
end
defp maybe_fetch_user(:not_found, _config), do: nil
defp maybe_fetch_user(user_id, config) do
Pow.Operations.get_by(config, id: user_id)
end
defp maybe_renew(conn, config) do
cookie_key = cookie_key(config)
case conn.resp_cookies[cookie_key] do
nil -> renew(conn, cookie_key, config)
_any -> conn
end
end
defp renew(conn, cookie_key, config) do
opts = session_opts(config)
case conn.req_cookies[cookie_key] do
nil -> conn
value -> Conn.put_resp_cookie(conn, cookie_key, value, opts)
end
end
defp cookie_key(config) do
Config.get(config, :persistent_session_cookie_key, @cookie_key)
end
defp session_opts(config) do
max_age = Config.get(config, :persistent_session_cookie_max_age, @ttl)
[max_age: max_age, path: "/"]
end
end