Packages
guardian
1.0.0-beta.0
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_header.ex
if Code.ensure_loaded?(Plug) do
defmodule Guardian.Plug.VerifyHeader do
@moduledoc """
Looks for and validates a token found in the `Authorization` header.
In the case where:
a. The session is 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 decoded, the token and claims will be put onto the connection.
They will be available using `Guardian.Plug.current_claims/2` and `Guardian.Plug.current_token/2`
Options:
* `claims` - The literal claims to check to ensure that a token is valid
* `realm` - The prefix for the token in the Authorization header. Defaults to `Bearer`. `:none` will not use a prefix.
* `key` - The location to store the information in the connection. Defaults to: `default`
### Example
```elixir
# setup the upstream pipeline
plug Guardian.Plug.VerifyHeader, claims: %{typ: "access"}
```
This will check the authorization header for a token
`Authorization Bearer: <token>`
This token will be placed into the connection depending on the key and can be accessed with
`Guardian.Plug.current_token` and `Guardian.Plug.current_claims`
OR
`MyApp.ImplementationModule.current_token` and `MyApp.ImplementationModule.current_claims`
"""
alias Guardian.Plug, as: GPlug
alias GPlug.Pipeline
import Plug.Conn
@spec init(Keyword.t) :: Keyword.t
def init(opts \\ []) do
realm = Keyword.get(opts, :realm, "Bearer")
case realm do
"" -> opts
:none -> opts
_realm ->
{:ok, reg} = Regex.compile("#{realm}\:?\s+(.*)$", "i")
Keyword.put(opts, :realm_reg, reg)
end
end
@spec call(Plug.Conn.t, Keyword.t) :: Plug.Conn.t
def call(conn, opts) do
with nil <- GPlug.current_token(conn, opts),
{:ok, token} <- fetch_token_from_header(conn, opts),
module <- Pipeline.fetch_module!(conn, opts),
claims_to_check <- Keyword.get(opts, :claims, %{}),
key <- storage_key(conn, opts),
{:ok, claims} <- Guardian.decode_and_verify(module, token, claims_to_check, opts) do
conn
|> GPlug.put_current_token(token, key: key)
|> GPlug.put_current_claims(claims, key: key)
else
:no_token_found -> conn
{:error, reason} ->
conn
|> Pipeline.fetch_error_handler!(opts)
|> apply(:auth_error, [conn, {:invalid_token, reason}, opts])
_ -> conn
end
end
@spec fetch_token_from_header(Plug.Conn.t, Keyword.t) :: :no_token_found |
{:ok, String.t}
defp fetch_token_from_header(conn, opts) do
headers = get_req_header(conn, "authorization")
fetch_token_from_header(conn, opts, headers)
end
@spec fetch_token_from_header(Plug.Conn.t, Keyword.t, Keyword.t) :: :no_token_found |
{:ok, String.t}
defp fetch_token_from_header(_, _, []), do: :no_token_found
defp fetch_token_from_header(conn, opts, [token|tail]) do
reg = Keyword.get(opts, :realm_reg, ~r/^(.*)$/)
trimmed_token = String.trim(token)
case Regex.run(reg, trimmed_token) do
[_, match] -> {:ok, String.trim(match)}
_ -> fetch_token_from_header(conn, opts, tail)
end
end
@spec storage_key(Plug.Conn.t, Keyword.t) :: String.t
defp storage_key(conn, opts), do: Pipeline.fetch_key(conn, opts)
end
end