Current section
Files
Jump to
Current section
Files
lib/plug_jwt.ex
defmodule PlugJwt do
@moduledoc """
A JWT Plug
Usage:
#When reading from joken config block
plug PlugJwt
#or the module that implements `Joken.Config` can be set explicitly
plug PlugJwt, config_module: My.Joken.Config
Parameters:
PlugJWT will attempt to read from your joken config block. Settings can also be placed on the Plug itself
which overrides the joken configuration
* config_module: The module that implements Joken.Config
"""
import Plug.Conn
def init(opts) do
config_module = Keyword.get(opts, :config_module, Application.get_env(:joken, :config_module))
claims = Keyword.get(opts, :claims, [])
{config_module, claims}
end
def call(conn, config) do
parse_auth(conn, get_req_header(conn, "authorization"), config)
end
defp parse_auth(conn, ["Bearer " <> token], {config_module, claims}) do
case Joken.Token.decode(config_module, token) do
{:error, error} ->
create_401_response(conn, error, config_module)
{:ok, payload} ->
test_claims(payload, claims, conn, config_module)
end
end
defp parse_auth(conn, _, {config_module, _claims}) do
create_401_response(conn, "Unauthorized", config_module)
end
defp test_claims(payload, claims, conn, config_module) do
if Enum.all?(claims, fn({k,v})-> validate_claim(payload, k, v) == :ok end) do
conn |> assign(:claims, payload)
else
create_401_response(conn, "Unauthorized", config_module)
end
end
defp validate_claim(payload, claim_key, claim_value) do
cond do
Dict.get(payload, claim_key, nil) == claim_value ->
:ok
true ->
:error
end
end
defp create_401_response(conn, description, config_module) do
json = config_module.encode(%{error: "Unauthorized", description: description, status_code: 401})
send_resp(conn, 401, json) |> halt
end
end