Packages
guardian
1.0.0-beta.1
2.4.0
2.3.2
2.3.1
2.3.0
2.2.4
2.2.3
2.2.2
2.2.1
2.2.0
2.1.2
2.1.1
2.0.0
1.2.1
1.2.0
retired
1.1.1
1.1.0
1.0.1
1.0.0
1.0.0-beta.1
1.0.0-beta.0
0.14.6
0.14.5
0.14.4
0.14.3
retired
0.14.2
0.14.1
0.14.0
0.13.0
0.12.0
0.11.1
0.10.1
0.10.0
0.9.1
0.9.0
0.8.1
0.8.0
0.7.4
0.7.2
0.7.1
0.7.0
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.0
0.4.1
0.4.0
0.3.1
0.3.0
0.2.0
0.1.1
0.1.0
Elixir Authentication framework
Current section
Files
Jump to
Current section
Files
lib/guardian/plug/verify_cookie.ex
if Code.ensure_loaded?(Plug) do
defmodule Guardian.Plug.VerifyCookie do
@moduledoc """
Looks for and validates a token found in the request cookies.
In the case where:
a. The cookies are not loaded
b. A token is already found for `:key`
This plug will not do anything.
This, like all other Guardian plugs, requires a Guardian pipeline to be setup.
It requires an implementation module, an error handler and a key.
These can be set either:
1. Upstream on the connection with `plug Guardian.Pipeline`
2. Upstream on the connection with `Guardian.Pipeline.{put_module, put_error_handler, put_key}`
3. Inline with an option of `:module`, `:error_handler`, `:key`
If a token is found but is invalid, the error handler will be called with
`auth_error(conn, {:invalid_token, reason}, opts)`
Once a token has been found it will be exchanged for an access (default) token.
This access token will be placed into the session and connection.
They will be available using `Guardian.Plug.current_claims/2` and `Guardian.Plug.current_token/2`
Tokens from cookies should be of type `refresh` and have a relatively long life.
They will be exchanged for `access` tokens (default)
Options:
* `:key` - The location of the token (default `:default`)
* `:exchange_from` - The type of the cookie (default `"refresh"`)
* `:exchange_to` - The type of token to provide. Defaults to the implementation modules `default_type`
* `:ttl` - The time to live of the exchanged token. Defaults to configured values.
"""
import Plug.Conn
import Guardian.Plug.Keys
alias Guardian.Plug, as: GPlug
alias GPlug.Pipeline
def init(opts), do: opts
@spec call(Plug.Conn.t, Keyword.t) :: Plug.Conn.t
def call(%{req_cookies: %Plug.Conn.Unfetched{}} = conn, _opts), do: conn
def call(conn, opts) do
with nil <- GPlug.current_token(conn, opts),
{:ok, token} <- find_token_from_cookies(conn, opts),
module <- Pipeline.fetch_module!(conn, opts),
key <- storage_key(conn, opts),
exchange_from <- Keyword.get(opts, :exchange_from, "refresh"),
default_type <- module.default_token_type(),
exchange_to <- Keyword.get(opts, :exchange_to, default_type),
active_session? <- GPlug.session_active?(conn),
{:ok, _old, {new_t, new_c}} <- Guardian.exchange(module, token, exchange_from, exchange_to, opts) do
conn
|> GPlug.put_current_token(new_t, key: key)
|> GPlug.put_current_claims(new_c, key: key)
|> maybe_put_in_session(active_session?, new_t, key)
else
:no_token_found -> conn
{:error, reason} ->
conn
|> Pipeline.fetch_error_handler!(opts)
|> apply(:auth_error, [conn, {:invalid_token, reason}, opts])
|> halt()
_ -> conn
end
end
defp find_token_from_cookies(conn, opts) do
key = conn |> storage_key(opts) |> token_key()
token = conn.req_cookies[key] || conn.req_cookies[to_string(key)]
if token, do: {:ok, token}, else: :no_token_found
end
defp maybe_put_in_session(conn, false, _, _), do: conn
defp maybe_put_in_session(conn, true, token, key), do: put_session(conn, key, token)
defp storage_key(conn, opts), do: Pipeline.fetch_key(conn, opts)
end
end