Packages
phauxth
1.0.2
2.5.1
retired
2.5.0
2.4.0
2.3.2
2.3.1
2.3.0
2.2.0
2.1.1
2.1.0
2.0.1
2.0.0
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
2.0.0-beta.1
2.0.0-beta.0
2.0.0-alpha.5
2.0.0-alpha.4
retired
2.0.0-alpha.3
retired
2.0.0-alpha.2
retired
2.0.0-alpha.1
retired
2.0.0-alpha.0
retired
1.2.9
1.2.8
1.2.7
1.2.6
1.2.5
1.2.4
1.2.3
1.2.1
1.2.0
1.1.3
1.1.2
1.1.1
1.1.0
1.0.3
1.0.2
1.0.1
1.0.0
0.17.1
0.17.0
0.16.0
0.15.1
0.15.0
0.14.0
0.13.0-rc.1
0.13.0-rc.0
0.12.1-rc.1
0.12.1-rc.0
0.12.0-rc
0.11.0
0.10.3
0.10.2
0.10.0
0.9.0
0.8.2
0.8.1
0.8.0
Authentication library for Phoenix, and other Plug-based, web applications
Current section
Files
Jump to
Current section
Files
lib/phauxth/authenticate/base.ex
defmodule Phauxth.Authenticate.Base do
@moduledoc """
Base module for authentication.
This is used by Phauxth.Authenticate and Phauxth.Remember.
It can also be used to produce a custom authentication module,
as outlined below.
## Custom authentication modules
One example of a custom authentication module is provided by the
Phauxth.Remember module, which uses this base module to provide the
'remember me' functionality.
### Graphql authentication
The following module is another example of how this Base module can
be extended, this time to provide authentication for absinthe-elixir:
defmodule AbsintheAuthenticate do
use Phauxth.Authenticate.Base
import Plug.Conn
def set_user(user, conn) do
put_private(conn, :absinthe, %{token: %{current_user: user}})
end
end
And in the `router.ex` file, call this plug in the pipeline you
want to authenticate (setting the method to :token).
pipeline :api do
plug :accepts, ["json"]
plug AbsintheAuthenticate, method: :token
end
### Custom session / token implementations
This module uses Plug sessions or Phauxth tokens (based on Phoenix.Token)
by default. To use custom sessions or tokens, you need to create your
own custom Authenticate module and override the `check_session` or
`check_token` function.
"""
@doc false
defmacro __using__(_) do
quote do
import unquote(__MODULE__)
import Plug.Conn
alias Phauxth.{Config, Log, Token, Utils}
@behaviour Plug
@doc false
def init(opts) do
{{Keyword.get(opts, :method, :session),
Keyword.get(opts, :max_age, 4 * 60 * 60),
Keyword.get(opts, :user_context, Utils.default_user_context())},
Keyword.get(opts, :log_meta, [])}
end
@doc false
def call(conn, {opts, log_meta}) do
get_user(conn, opts) |> report(log_meta) |> set_user(conn)
end
@doc """
Get the user based on the session id or token id.
This function also calls the database to get user information.
"""
def get_user(conn, {:session, _, user_context}) do
with user_id when not is_nil(user_id) <- check_session(conn),
do: user_context.get(user_id)
end
def get_user(%Plug.Conn{req_headers: headers} = conn,
{:token, max_age, user_context}) do
with {_, token} <- List.keyfind(headers, "authorization", 0),
{:ok, user_id} <- check_token(conn, token, max_age),
do: user_context.get(user_id)
end
@doc """
Check the session for the current user.
"""
def check_session(conn), do: get_session(conn, :user_id)
@doc """
Check the token for the current user.
"""
def check_token(conn, token, max_age) do
Token.verify(conn, token, max_age)
end
@doc """
Log the result of the authentication and return the user struct or nil.
"""
def report(%{} = user, meta) do
Log.info(%Log{user: user.id, message: "user authenticated", meta: meta})
Map.drop(user, Config.drop_user_keys)
end
def report({:error, message}, meta) do
Log.info(%Log{message: message, meta: meta}) && nil
end
def report(nil, meta) do
Log.info(%Log{meta: meta}) && nil
end
@doc """
Set the `current_user` variable.
"""
def set_user(user, conn) do
assign(conn, :current_user, user)
end
defoverridable [init: 1, call: 2, get_user: 2, check_session: 1,
check_token: 3, report: 2, set_user: 2]
end
end
end