mirror of
https://github.com/kevin-DL/phoenix_api_template.git
synced 2026-01-11 02:34:30 +00:00
Installed guardian
create authentication/password verification method
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -150,3 +150,4 @@ fabric.properties
|
||||
/config/*.secret.exs
|
||||
.elixir_ls/
|
||||
|
||||
.env
|
||||
@@ -23,6 +23,11 @@ config :logger, :console,
|
||||
format: "$time $metadata[$level] $message\n",
|
||||
metadata: [:request_id]
|
||||
|
||||
# Guardian config
|
||||
config :phoenix_api_template, PhoenixApiTemplateWeb.Auth.Guardian,
|
||||
issuer: "phoenix_api_template",
|
||||
secret_key: ""
|
||||
|
||||
# Use Jason for JSON parsing in Phoenix
|
||||
config :phoenix, :json_library, Jason
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import Config
|
||||
|
||||
Envar.load(".env")
|
||||
|
||||
# config/runtime.exs is executed for all environments, including
|
||||
# during releases. It is executed after compilation and before the
|
||||
# system starts, so it is typically used to load production configuration
|
||||
@@ -63,3 +65,9 @@ if config_env() == :prod do
|
||||
],
|
||||
secret_key_base: secret_key_base
|
||||
end
|
||||
|
||||
guardian_secret_key = System.get_env("GUARDIAN_SECRET_KEY")
|
||||
|
||||
config :phoenix_api_template, PhoenixApiTemplateWeb.Auth.Guardian,
|
||||
issuer: "phoenix_api_template",
|
||||
secret_key: guardian_secret_key
|
||||
|
||||
@@ -37,6 +37,25 @@ defmodule PhoenixApiTemplate.Accounts do
|
||||
"""
|
||||
def get_user!(id), do: Repo.get!(User, id)
|
||||
|
||||
@doc """
|
||||
Gets a single user by email
|
||||
|
||||
Returns `nil` if the account does not exist
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_user_by_email(test@email.com)
|
||||
%User{}
|
||||
|
||||
iex> get_user_by_email(nope@email.com)
|
||||
nil
|
||||
"""
|
||||
def get_user_by_email(email) do
|
||||
User
|
||||
|> where(email: ^email)
|
||||
|> Repo.one()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Creates a user.
|
||||
|
||||
|
||||
@@ -17,8 +17,17 @@ defmodule PhoenixApiTemplate.Accounts.User do
|
||||
user
|
||||
|> cast(attrs, [:email, :hashed_password])
|
||||
|> validate_required([:email, :hashed_password])
|
||||
|> unique_constraint(:email)
|
||||
|> validate_format(:email, ~r/^[^\s]+@[^\s]+$/, message: "must have the @ sign and no spaces")
|
||||
|> validate_length(:email, max: 250)
|
||||
|> unique_constraint(:email)
|
||||
|> put_password_hash()
|
||||
end
|
||||
|
||||
defp put_password_hash(
|
||||
%Ecto.Changeset{valid?: true, changes: %{hashed_password: hashed_password}} = changeset
|
||||
) do
|
||||
change(changeset, hashed_password: Bcrypt.hash_pwd_salt(hashed_password))
|
||||
end
|
||||
|
||||
defp put_password_hash(changeset), do: changeset
|
||||
end
|
||||
|
||||
46
lib/phoenix_api_template_web/auth/guardian.ex
Normal file
46
lib/phoenix_api_template_web/auth/guardian.ex
Normal file
@@ -0,0 +1,46 @@
|
||||
defmodule PhoenixApiTemplateWeb.Auth.Guardian do
|
||||
use Guardian, otp_app: :phoenix_api_template
|
||||
alias PhoenixApiTemplate.Accounts
|
||||
|
||||
def subject_for_token(%{id: id}, _claims) do
|
||||
sub = to_string(id)
|
||||
{:ok, sub}
|
||||
end
|
||||
|
||||
def subject_for_token(_, _) do
|
||||
{:error, :no_id_provided}
|
||||
end
|
||||
|
||||
def resource_from_claims(%{"sub" => id}) do
|
||||
case Accounts.get_user!(id) do
|
||||
nil -> {:error, :not_found}
|
||||
resource -> {:ok, resource}
|
||||
end
|
||||
end
|
||||
|
||||
def resource_from_claims(_claims) do
|
||||
{:error, :no_id_provided}
|
||||
end
|
||||
|
||||
def authenticate(email, password) do
|
||||
case Accounts.get_user_by_email(email) do
|
||||
nil ->
|
||||
{:error, :unauthorized}
|
||||
|
||||
user ->
|
||||
case validate_password(password, user.hashed_password) do
|
||||
true -> create_token(user)
|
||||
false -> {:error, :unauthorized}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp validate_password(password, hashed_password) do
|
||||
Bcrypt.verify_pass(password, hashed_password)
|
||||
end
|
||||
|
||||
defp create_token(user) do
|
||||
{:ok, token, _claims} = encode_and_sign(user)
|
||||
{:ok, user, token}
|
||||
end
|
||||
end
|
||||
5
mix.exs
5
mix.exs
@@ -41,7 +41,10 @@ defmodule PhoenixApiTemplate.MixProject do
|
||||
{:telemetry_poller, "~> 1.0"},
|
||||
{:gettext, "~> 0.18"},
|
||||
{:jason, "~> 1.2"},
|
||||
{:plug_cowboy, "~> 2.5"}
|
||||
{:plug_cowboy, "~> 2.5"},
|
||||
{:guardian, "~> 2.0"},
|
||||
{:bcrypt_elixir, "~> 3.0"},
|
||||
{:envar, "~> 1.1.0"}
|
||||
]
|
||||
end
|
||||
|
||||
|
||||
6
mix.lock
6
mix.lock
@@ -1,5 +1,7 @@
|
||||
%{
|
||||
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.0.1", "9be815469e6bfefec40fa74658ecbbe6897acfb57614df1416eeccd4903f602c", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "486bb95efb645d1efc6794c1ddd776a186a9a713abf06f45708a6ce324fb96cf"},
|
||||
"castore": {:hex, :castore, "1.0.0", "c25cd0794c054ebe6908a86820c8b92b5695814479ec95eeff35192720b71eec", [:mix], [], "hexpm", "577d0e855983a97ca1dfa33cbb8a3b6ece6767397ffb4861514343b078fc284b"},
|
||||
"comeonin": {:hex, :comeonin, "5.3.3", "2c564dac95a35650e9b6acfe6d2952083d8a08e4a89b93a481acb552b325892e", [:mix], [], "hexpm", "3e38c9c2cb080828116597ca8807bb482618a315bfafd98c90bc22a821cc84df"},
|
||||
"connection": {:hex, :connection, "1.1.0", "ff2a49c4b75b6fb3e674bfc5536451607270aac754ffd1bdfe175abe4a6d7a68", [:mix], [], "hexpm", "722c1eb0a418fbe91ba7bd59a47e28008a189d47e37e0e7bb85585a016b2869c"},
|
||||
"cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"},
|
||||
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"},
|
||||
@@ -8,9 +10,13 @@
|
||||
"decimal": {:hex, :decimal, "2.0.0", "a78296e617b0f5dd4c6caf57c714431347912ffb1d0842e998e9792b5642d697", [:mix], [], "hexpm", "34666e9c55dea81013e77d9d87370fe6cb6291d1ef32f46a1600230b1d44f577"},
|
||||
"ecto": {:hex, :ecto, "3.9.4", "3ee68e25dbe0c36f980f1ba5dd41ee0d3eb0873bccae8aeaf1a2647242bffa35", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "de5f988c142a3aa4ec18b85a4ec34a2390b65b24f02385c1144252ff6ff8ee75"},
|
||||
"ecto_sql": {:hex, :ecto_sql, "3.9.2", "34227501abe92dba10d9c3495ab6770e75e79b836d114c41108a4bf2ce200ad5", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.9.2", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16.0 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "1eb5eeb4358fdbcd42eac11c1fbd87e3affd7904e639d77903c1358b2abd3f70"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.6.3", "bc07d53221216838d79e03a8019d0839786703129599e9619f4ab74c8c096eac", [:mix], [], "hexpm", "f5cbd651c5678bcaabdbb7857658ee106b12509cd976c2c2fca99688e1daf716"},
|
||||
"envar": {:hex, :envar, "1.1.0", "105bcac5a03800a1eb21e2c7e229edc687359b0cc184150ec1380db5928c115c", [:mix], [], "hexpm", "97028ab4a040a5c19e613fdf46a41cf51c6e848d99077e525b338e21d2993320"},
|
||||
"expo": {:hex, :expo, "0.3.0", "13127c1d5f653b2927f2616a4c9ace5ae372efd67c7c2693b87fd0fdc30c6feb", [:mix], [], "hexpm", "fb3cd4bf012a77bc1608915497dae2ff684a06f0fa633c7afa90c4d72b881823"},
|
||||
"gettext": {:hex, :gettext, "0.22.0", "a25d71ec21b1848957d9207b81fd61cb25161688d282d58bdafef74c2270bdc4", [:mix], [{:expo, "~> 0.3.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "cb0675141576f73720c8e49b4f0fd3f2c69f0cd8c218202724d4aebab8c70ace"},
|
||||
"guardian": {:hex, :guardian, "2.3.1", "2b2d78dc399a7df182d739ddc0e566d88723299bfac20be36255e2d052fd215d", [:mix], [{:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "bbe241f9ca1b09fad916ad42d6049d2600bbc688aba5b3c4a6c82592a54274c3"},
|
||||
"jason": {:hex, :jason, "1.4.0", "e855647bc964a44e2f67df589ccf49105ae039d4179db7f6271dfd3843dc27e6", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "79a3791085b2a0f743ca04cec0f7be26443738779d09302e01318f97bdb82121"},
|
||||
"jose": {:hex, :jose, "1.11.5", "3bc2d75ffa5e2c941ca93e5696b54978323191988eb8d225c2e663ddfefd515e", [:mix, :rebar3], [], "hexpm", "dcd3b215bafe02ea7c5b23dafd3eb8062a5cd8f2d904fd9caa323d37034ab384"},
|
||||
"mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"},
|
||||
"phoenix": {:hex, :phoenix, "1.6.15", "0a1d96bbc10747fd83525370d691953cdb6f3ccbac61aa01b4acb012474b047d", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 1.0 or ~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d70ab9fbf6b394755ea88b644d34d79d8b146e490973151f248cacd122d20672"},
|
||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.4.0", "0672ed4e4808b3fbed494dded89958e22fb882de47a97634c0b13e7b0b5f7720", [:mix], [{:ecto, "~> 3.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "09864e558ed31ee00bd48fcc1d4fc58ae9678c9e81649075431e69dbabb43cc1"},
|
||||
|
||||
Reference in New Issue
Block a user