From 7c80ed298be15efe55a3e6d037a87d1f004164ab Mon Sep 17 00:00:00 2001 From: Felipe Ripoll Date: Wed, 1 Aug 2018 07:55:09 -0600 Subject: [PATCH] [#35] adding sessions endpoint over https --- .circleci/config.yml | 4 + config/prod.exs | 19 +++- config/test.exs | 16 +++- lib/poa_backend/application.ex | 2 +- lib/poa_backend/auth.ex | 18 +++- lib/poa_backend/auth/guardian.ex | 17 ++++ lib/poa_backend/auth/router.ex | 39 +++++++++ lib/poa_backend/auth/supervisor.ex | 29 +++++++ mix.exs | 6 +- mix.lock | 65 +++++++------- test/auth/api_test.exs | 134 +++++++++++++++++++++++++++++ 11 files changed, 313 insertions(+), 36 deletions(-) create mode 100644 lib/poa_backend/auth/guardian.ex create mode 100644 lib/poa_backend/auth/router.ex create mode 100644 lib/poa_backend/auth/supervisor.ex create mode 100644 test/auth/api_test.exs diff --git a/.circleci/config.yml b/.circleci/config.yml index 076d0a1..92689e3 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,6 +16,10 @@ jobs: - run: mix deps.get - run: env MIX_ENV=test mix ecto.create - run: env MIX_ENV=test mix ecto.migrate + - run: openssl genrsa -out localhost.key 2048 + - run: openssl req -new -x509 -key localhost.key -out localhost.cert -days 3650 -subj /CN=localhost + - run: mkdir priv/keys + - run: mv localhost.* priv/keys - run: mix test - run: mix credo - restore_cache: diff --git a/config/prod.exs b/config/prod.exs index 3f1040d..dcfbcb4 100644 --- a/config/prod.exs +++ b/config/prod.exs @@ -43,4 +43,21 @@ config :poa_backend, :subscriptions, [ {:dashboard_receiver, [:ethereum_metrics]} - ] \ No newline at end of file + ] + +# here we define the configuration for the Authorisation endpoint +config :poa_backend, + :auth_rest, + [ + {:scheme, :https}, + {:port, 4003}, + {:keyfile, "priv/keys/localhost.key"}, + {:certfile, "priv/keys/localhost.cert"} + ] + +config :poa_backend, POABackend.Auth.Guardian, + issuer: "poa_backend", + secret_key: "LQYmeqQfrphbxUjJltkwH4xnosLc+2S2e8KuYWctMenNY9bmgwnrH8r3ii9FP/8V" + +config :mnesia, + dir: 'priv/data/mnesia' # make sure this directory exists! \ No newline at end of file diff --git a/config/test.exs b/config/test.exs index 855f10a..634ef1b 100644 --- a/config/test.exs +++ b/config/test.exs @@ -37,5 +37,19 @@ config :poa_backend, {:dashboard_receiver, [:ethereum_metrics]} ] +# here we define the configuration for the Authorisation endpoint +config :poa_backend, + :auth_rest, + [ + {:scheme, :https}, + {:port, 4003}, + {:keyfile, "priv/keys/localhost.key"}, + {:certfile, "priv/keys/localhost.cert"} + ] + +config :poa_backend, POABackend.Auth.Guardian, + issuer: "poa_backend", + secret_key: "LQYmeqQfrphbxUjJltkwH4xnosLc+2S2e8KuYWctMenNY9bmgwnrH8r3ii9FP/8V" + config :mnesia, - dir: '_build/test' # make sure this directory exists! \ No newline at end of file + dir: '_build/test' # make sure this directory exists! diff --git a/lib/poa_backend/application.ex b/lib/poa_backend/application.ex index 0cab2a1..d43a6cd 100644 --- a/lib/poa_backend/application.ex +++ b/lib/poa_backend/application.ex @@ -7,7 +7,7 @@ defmodule POABackend.Application do import Supervisor.Spec children = [ - supervisor(POABackend.Auth.Repo, []), + supervisor(POABackend.Auth.Supervisor, []), supervisor(POABackend.CustomHandler.Supervisor, []), supervisor(POABackend.Metrics.Supervisor, []), supervisor(POABackend.Receivers.Supervisor, []) diff --git a/lib/poa_backend/auth.ex b/lib/poa_backend/auth.ex index f7646ef..e04f448 100644 --- a/lib/poa_backend/auth.ex +++ b/lib/poa_backend/auth.ex @@ -65,6 +65,22 @@ defmodule POABackend.Auth do """ @spec user_active?(User.t) :: Boolean.t def user_active?(%User{active: true}), do: true - def user_active?(%User{active: _}), do: false + def user_active?(%User{active: _}), do: false + + @doc """ + This function authenticates a user/password pair + """ + @spec authenticate_user(String.t, String.t) :: {:ok, User.t} | {:error, :notvalid} + def authenticate_user(user, password) do + alias Comeonin.Bcrypt + + with user <- get_user(user), + true <- Bcrypt.checkpw(password, user.password_hash) + do + {:ok, user} + else + _error -> {:error, :notvalid} + end + end end \ No newline at end of file diff --git a/lib/poa_backend/auth/guardian.ex b/lib/poa_backend/auth/guardian.ex new file mode 100644 index 0000000..6b38f03 --- /dev/null +++ b/lib/poa_backend/auth/guardian.ex @@ -0,0 +1,17 @@ +defmodule POABackend.Auth.Guardian do + @moduledoc false + use Guardian, otp_app: :poa_backend + + alias POABackend.Auth + + def subject_for_token(user, _claims) do + {:ok, to_string(user.user)} + end + + def resource_from_claims(%{"sub" => user}) do + case Auth.get_user(user) do + nil -> {:error, :resource_not_found} + user -> {:ok, user} + end + end +end \ No newline at end of file diff --git a/lib/poa_backend/auth/router.ex b/lib/poa_backend/auth/router.ex new file mode 100644 index 0000000..b9fc288 --- /dev/null +++ b/lib/poa_backend/auth/router.ex @@ -0,0 +1,39 @@ +defmodule POABackend.Auth.Router do + use Plug.Router + @moduledoc false + + alias POABackend.Auth + alias POABackend.CustomHandler.REST + import Plug.Conn + + plug REST.Plugs.Accept, ["application/json", "application/msgpack"] + plug Plug.Parsers, parsers: [Msgpax.PlugParser, :json], pass: ["application/msgpack", "application/json"], json_decoder: Poison + plug :match + plug :dispatch + + post "/session" do + with {"authorization", "Basic " <> base64} <- List.keyfind(conn.req_headers, "authorization", 0), + {:ok, decoded64} <- Base.decode64(base64), + [user_name, password] <- String.split(decoded64, ":"), + {:ok, user} <- Auth.authenticate_user(user_name, password) + do + {:ok, token, _} = POABackend.Auth.Guardian.encode_and_sign(user) + + {:ok, result} = + %{token: token} + |> Poison.encode + + send_resp(conn, 200, result) + else + _error -> + conn + |> send_resp(401, "") + |> halt + end + end + + match _ do + send_resp(conn, 404, "") + end + +end \ No newline at end of file diff --git a/lib/poa_backend/auth/supervisor.ex b/lib/poa_backend/auth/supervisor.ex new file mode 100644 index 0000000..65ae677 --- /dev/null +++ b/lib/poa_backend/auth/supervisor.ex @@ -0,0 +1,29 @@ +defmodule POABackend.Auth.Supervisor do + @moduledoc false + + alias POABackend.Auth + + def start_link do + Supervisor.start_link(__MODULE__, :ok, name: __MODULE__) + end + + def init(:ok) do + import Supervisor.Spec + + rest_options = Application.get_env(:poa_backend, :auth_rest) + cowboy_options = [ + port: rest_options[:port], + keyfile: rest_options[:keyfile], + certfile: rest_options[:certfile], + otp_app: :poa_backend + ] + + children = [ + supervisor(Auth.Repo, []), + Plug.Adapters.Cowboy.child_spec(scheme: rest_options[:scheme], plug: Auth.Router, options: cowboy_options) + ] + + opts = [strategy: :one_for_one] + Supervisor.init(children, opts) + end +end \ No newline at end of file diff --git a/mix.exs b/mix.exs index 9391d68..64908e5 100644 --- a/mix.exs +++ b/mix.exs @@ -40,7 +40,9 @@ defmodule POABackend.MixProject do {:hackney, "~> 1.12"}, {:msgpax, "~> 2.1"}, {:ecto_mnesia, "~> 0.9.1"}, - {:comeonin, "~> 3.2"}, + {:guardian, "~> 1.1"}, + {:comeonin, "~> 4.0"}, + {:bcrypt_elixir, "~> 0.12"}, # Tests {:credo, "~> 0.9", only: [:dev, :test], runtime: false}, @@ -51,7 +53,7 @@ defmodule POABackend.MixProject do {:websockex, "~> 0.4", only: [:test]}, # Docs - {:ex_doc, "~> 0.18", only: :dev, runtime: false}, + {:ex_doc, "~> 0.18.0", only: :dev, runtime: false}, # Releases {:distillery, "~> 1.5", runtime: false} diff --git a/mix.lock b/mix.lock index fb6aefc..d7d6ae3 100644 --- a/mix.lock +++ b/mix.lock @@ -1,40 +1,45 @@ %{ - "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"}, - "certifi": {:hex, :certifi, "2.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [:rebar3], [{:parse_trans, "3.2.0", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, - "comeonin": {:hex, :comeonin, "3.2.0", "cb10995a22aed6812667efb3856f548818c85d85394d8132bc116fbd6995c1ef", [], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"}, + "base64url": {:hex, :base64url, "0.0.1", "36a90125f5948e3afd7be97662a1504b934dd5dac78451ca6e9abf85a10286be", [], [], "hexpm"}, + "bcrypt_elixir": {:hex, :bcrypt_elixir, "0.12.1", "41ff5a4739fcff365fe840637462dc9e22beac07a9dcf3cb5e79b127f5b3a099", [], [{:elixir_make, "~> 0.4", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm"}, + "bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [], [], "hexpm"}, + "certifi": {:hex, :certifi, "2.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [], [{:parse_trans, "3.2.0", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"}, + "comeonin": {:hex, :comeonin, "4.1.1", "c7304fc29b45b897b34142a91122bc72757bc0c295e9e824999d5179ffc08416", [], [{:argon2_elixir, "~> 1.2", [hex: :argon2_elixir, repo: "hexpm", optional: true]}, {:bcrypt_elixir, "~> 0.12.1 or ~> 1.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: true]}, {:pbkdf2_elixir, "~> 0.12", [hex: :pbkdf2_elixir, repo: "hexpm", optional: true]}], "hexpm"}, "confex": {:hex, :confex, "3.3.1", "8febaf751bf293a16a1ed2cbd258459cdcc7ca53cfa61d3f83d49dd276a992b4", [], [], "hexpm"}, - "cowboy": {:hex, :cowboy, "1.0.4", "a324a8df9f2316c833a470d918aaf73ae894278b8aa6226ce7a9bf699388f878", [:make, :rebar], [{:cowlib, "~> 1.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"}, - "cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [:make], [], "hexpm"}, - "credo": {:hex, :credo, "0.9.3", "76fa3e9e497ab282e0cf64b98a624aa11da702854c52c82db1bf24e54ab7c97a", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:poison, ">= 0.0.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"}, + "cowboy": {:hex, :cowboy, "1.0.4", "a324a8df9f2316c833a470d918aaf73ae894278b8aa6226ce7a9bf699388f878", [], [{:cowlib, "~> 1.0.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm"}, + "cowlib": {:hex, :cowlib, "1.0.2", "9d769a1d062c9c3ac753096f868ca121e2730b9a377de23dec0f7e08b1df84ee", [], [], "hexpm"}, + "credo": {:hex, :credo, "0.10.0", "66234a95effaf9067edb19fc5d0cd5c6b461ad841baac42467afed96c78e5e9e", [], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, "decimal": {:hex, :decimal, "1.5.0", "b0433a36d0e2430e3d50291b1c65f53c37d56f83665b43d79963684865beab68", [], [], "hexpm"}, - "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [:mix], [], "hexpm"}, + "dialyxir": {:hex, :dialyxir, "0.5.1", "b331b091720fd93e878137add264bac4f644e1ddae07a70bf7062c7862c4b952", [], [], "hexpm"}, "distillery": {:hex, :distillery, "1.5.3", "b2f4fc34ec71ab4f1202a796f9290e068883b042319aa8c9aa45377ecac8597a", [], [], "hexpm"}, - "earmark": {:hex, :earmark, "1.2.5", "4d21980d5d2862a2e13ec3c49ad9ad783ffc7ca5769cf6ff891a4553fbaae761", [:mix], [], "hexpm"}, + "earmark": {:hex, :earmark, "1.2.5", "4d21980d5d2862a2e13ec3c49ad9ad783ffc7ca5769cf6ff891a4553fbaae761", [], [], "hexpm"}, "ecto": {:hex, :ecto, "2.1.6", "29b45f393c2ecd99f83e418ea9b0a2af6078ecb30f401481abac8a473c490f84", [], [{:db_connection, "~> 1.1", [hex: :db_connection, repo: "hexpm", optional: true]}, {:decimal, "~> 1.2", [hex: :decimal, repo: "hexpm", optional: false]}, {:mariaex, "~> 0.8.0", [hex: :mariaex, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.13.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:sbroker, "~> 1.0", [hex: :sbroker, repo: "hexpm", optional: true]}], "hexpm"}, "ecto_mnesia": {:hex, :ecto_mnesia, "0.9.1", "5887e3bcae972d9a26494a87cbd318d401a65b4af324480073d11df654d1b235", [], [{:confex, "~> 3.3", [hex: :confex, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 2.1.6", [hex: :ecto, repo: "hexpm", optional: false]}], "hexpm"}, "elixir_make": {:hex, :elixir_make, "0.4.2", "332c649d08c18bc1ecc73b1befc68c647136de4f340b548844efc796405743bf", [], [], "hexpm"}, - "ex_aws": {:hex, :ex_aws, "2.0.2", "8df2f96f58624a399abe5a0ce26db648ee848aca6393b9c65c939ece9ac07bfa", [:mix], [{:configparser_ex, "~> 2.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "1.6.3 or 1.6.5 or 1.7.1 or 1.8.6 or ~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8", [hex: :jsx, repo: "hexpm", optional: true]}, {:poison, ">= 1.2.0", [hex: :poison, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:xml_builder, "~> 0.1.0", [hex: :xml_builder, repo: "hexpm", optional: true]}], "hexpm"}, - "ex_aws_dynamo": {:hex, :ex_aws_dynamo, "2.0.0", "07b1117bbd1b1d04e2598190834c69c271db1d357cc21b82240d1a0b17194165", [:mix], [{:ex_aws, "~> 2.0.0", [hex: :ex_aws, repo: "hexpm", optional: false]}], "hexpm"}, - "ex_doc": {:hex, :ex_doc, "0.18.3", "f4b0e4a2ec6f333dccf761838a4b253d75e11f714b85ae271c9ae361367897b7", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, - "excoveralls": {:hex, :excoveralls, "0.9.1", "14fd20fac51ab98d8e79615814cc9811888d2d7b28e85aa90ff2e30dcf3191d6", [:mix], [{:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, - "gen_stage": {:hex, :gen_stage, "0.14.0", "65ae78509f85b59d360690ce3378d5096c3130a0694bab95b0c4ae66f3008fad", [:mix], [], "hexpm"}, - "hackney": {:hex, :hackney, "1.13.0", "24edc8cd2b28e1c652593833862435c80661834f6c9344e84b6a2255e7aeef03", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.2", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, - "httpoison": {:hex, :httpoison, "1.2.0", "2702ed3da5fd7a8130fc34b11965c8cfa21ade2f232c00b42d96d4967c39a3a3", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, - "idna": {:hex, :idna, "5.1.2", "e21cb58a09f0228a9e0b95eaa1217f1bcfc31a1aaa6e1fdf2f53a33f7dbd9494", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, - "jason": {:hex, :jason, "1.0.0", "0f7cfa9bdb23fed721ec05419bcee2b2c21a77e926bce0deda029b5adc716fe2", [], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, - "meck": {:hex, :meck, "0.8.10", "455aaef8403be46752272206613e7a15467c014d40994b22fb54cde4d1ff7075", [:rebar3], [], "hexpm"}, - "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"}, - "mime": {:hex, :mime, "1.3.0", "5e8d45a39e95c650900d03f897fbf99ae04f60ab1daa4a34c7a20a5151b7a5fe", [:mix], [], "hexpm"}, - "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"}, - "mock": {:hex, :mock, "0.3.1", "994f00150f79a0ea50dc9d86134cd9ebd0d177ad60bd04d1e46336cdfdb98ff9", [:mix], [{:meck, "~> 0.8.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"}, + "ex_aws": {:hex, :ex_aws, "2.1.0", "b92651527d6c09c479f9013caa9c7331f19cba38a650590d82ebf2c6c16a1d8a", [], [{:configparser_ex, "~> 2.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "1.6.3 or 1.6.5 or 1.7.1 or 1.8.6 or ~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8", [hex: :jsx, repo: "hexpm", optional: true]}, {:poison, ">= 1.2.0", [hex: :poison, repo: "hexpm", optional: true]}, {:sweet_xml, "~> 0.6", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:xml_builder, "~> 0.1.0", [hex: :xml_builder, repo: "hexpm", optional: true]}], "hexpm"}, + "ex_aws_dynamo": {:hex, :ex_aws_dynamo, "2.0.1", "fd472900779f3bb9cd2b59bde14b130404f751c1990e1fff8b6898150dc457da", [], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}], "hexpm"}, + "ex_doc": {:hex, :ex_doc, "0.18.4", "4406b8891cecf1352f49975c6d554e62e4341ceb41b9338949077b0d4a97b949", [], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}], "hexpm"}, + "excoveralls": {:hex, :excoveralls, "0.9.1", "14fd20fac51ab98d8e79615814cc9811888d2d7b28e85aa90ff2e30dcf3191d6", [], [{:hackney, ">= 0.12.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"}, + "gen_stage": {:hex, :gen_stage, "0.14.0", "65ae78509f85b59d360690ce3378d5096c3130a0694bab95b0c4ae66f3008fad", [], [], "hexpm"}, + "guardian": {:hex, :guardian, "1.1.0", "36c1ea356a1bac02bc120c3f91f4f0259c5aa0ee92cee0efe8def5d7401f1921", [], [{:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.0 or ~> 1.2 or ~> 1.3", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.3.3 or ~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}, {:poison, "~> 2.2 or ~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}, {:uuid, ">= 1.1.1", [hex: :uuid, repo: "hexpm", optional: false]}], "hexpm"}, + "hackney": {:hex, :hackney, "1.13.0", "24edc8cd2b28e1c652593833862435c80661834f6c9344e84b6a2255e7aeef03", [], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.2", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"}, + "httpoison": {:hex, :httpoison, "1.2.0", "2702ed3da5fd7a8130fc34b11965c8cfa21ade2f232c00b42d96d4967c39a3a3", [], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"}, + "idna": {:hex, :idna, "5.1.2", "e21cb58a09f0228a9e0b95eaa1217f1bcfc31a1aaa6e1fdf2f53a33f7dbd9494", [], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"}, + "jason": {:hex, :jason, "1.1.1", "d3ccb840dfb06f2f90a6d335b536dd074db748b3e7f5b11ab61d239506585eb2", [], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"}, + "jose": {:hex, :jose, "1.8.4", "7946d1e5c03a76ac9ef42a6e6a20001d35987afd68c2107bcd8f01a84e75aa73", [], [{:base64url, "~> 0.0.1", [hex: :base64url, repo: "hexpm", optional: false]}], "hexpm"}, + "meck": {:hex, :meck, "0.8.11", "2c39e15ec87d847da6cf69b4a1c4af3fd850ae2a272e719e0e8751a7fe54771f", [], [], "hexpm"}, + "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [], [], "hexpm"}, + "mime": {:hex, :mime, "1.3.0", "5e8d45a39e95c650900d03f897fbf99ae04f60ab1daa4a34c7a20a5151b7a5fe", [], [], "hexpm"}, + "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [], [], "hexpm"}, + "mock": {:hex, :mock, "0.3.1", "994f00150f79a0ea50dc9d86134cd9ebd0d177ad60bd04d1e46336cdfdb98ff9", [], [{:meck, "~> 0.8.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"}, "msgpax": {:hex, :msgpax, "2.1.1", "833bc9ce6d3e073cf966fec94d3f976ca7100685b4f0efb6e30ef512f2e8a4d7", [], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm"}, - "parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"}, - "plug": {:hex, :plug, "1.6.0", "90d338a44c8cd762c32d3ea324f6728445c6145b51895403854b77f1536f1617", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"}, - "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm"}, + "parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [], [], "hexpm"}, + "plug": {:hex, :plug, "1.6.1", "c62fe7623d035020cf989820b38490460e6903ab7eee29e234b7586e9b6c91d6", [], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"}, + "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [], [], "hexpm"}, "poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [], [], "hexpm"}, - "ranch": {:hex, :ranch, "1.5.0", "f04166f456790fee2ac1aa05a02745cc75783c2bfb26d39faf6aefc9a3d3a58a", [:rebar3], [], "hexpm"}, - "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"}, - "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"}, - "websockex": {:hex, :websockex, "0.4.1", "d7b7191ec3d5dd136683b60114405a5a130a175faade773a07cb52dbd98f9442", [:mix], [], "hexpm"}, - "worker_pool": {:hex, :worker_pool, "3.1.0", "c908627e04057cf29940ad0e79b89ab161db520eebc76942efd08a187babf93a", [:rebar3], [], "hexpm"}, + "ranch": {:hex, :ranch, "1.5.0", "f04166f456790fee2ac1aa05a02745cc75783c2bfb26d39faf6aefc9a3d3a58a", [], [], "hexpm"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [], [], "hexpm"}, + "unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [], [], "hexpm"}, + "uuid": {:hex, :uuid, "1.1.8", "e22fc04499de0de3ed1116b770c7737779f226ceefa0badb3592e64d5cfb4eb9", [], [], "hexpm"}, + "websockex": {:hex, :websockex, "0.4.1", "d7b7191ec3d5dd136683b60114405a5a130a175faade773a07cb52dbd98f9442", [], [], "hexpm"}, + "worker_pool": {:hex, :worker_pool, "3.1.1", "a9bf27cff366999784a3f0657f016ce3a57901490858cca3fb3be1208bf2110d", [], [], "hexpm"}, } diff --git a/test/auth/api_test.exs b/test/auth/api_test.exs new file mode 100644 index 0000000..ffe3b1d --- /dev/null +++ b/test/auth/api_test.exs @@ -0,0 +1,134 @@ +defmodule Auth.APITest do + use ExUnit.Case + alias POABackend.Auth + alias POABackend.Ancillary.Utils + + @base_url "https://localhost:4003" + @user "ferigis" + @password "1234567890" + + setup do + Utils.clear_db() + :ok = create_user() + + on_exit fn -> + Utils.clear_db() + end + + [] + end + + # ---------------------------------------- + # /session Endpoint Tests + # ---------------------------------------- + + test "get a valid JWT Token with [JSON]" do + url = @base_url <> "/session" + mime_type = "application/json" + headers = [ + {"Content-Type", mime_type}, + {"authorization", "Basic " <> Base.encode64(@user <> ":" <> @password)} + ] + + {200, %{"token" => jwt_token}} = + %{:'agent-id' => "agentID"} + |> Poison.encode!() + |> post(url, headers) + + user = Auth.get_user(@user) + {:ok, claims} = Auth.Guardian.decode_and_verify(jwt_token) + + assert {:ok, user, claims} == Auth.Guardian.resource_from_token(jwt_token) + end + + test "get a valid JWT Token with [MSGPACK]" do + url = @base_url <> "/session" + mime_type = "application/msgpack" + headers = [ + {"Content-Type", mime_type}, + {"authorization", "Basic " <> Base.encode64(@user <> ":" <> @password)} + ] + + {200, %{"token" => jwt_token}} = + %{:'agent-id' => "agentID"} + |> Msgpax.pack!() + |> post(url, headers) + + user = Auth.get_user(@user) + {:ok, claims} = Auth.Guardian.decode_and_verify(jwt_token) + + assert {:ok, user, claims} == Auth.Guardian.resource_from_token(jwt_token) + end + + test "try with wrong user/password [JSON]" do + url = @base_url <> "/session" + mime_type = "application/json" + headers = [ + {"Content-Type", mime_type}, + {"authorization", "Basic " <> Base.encode64(@user <> ":" <> "wrongpassword")} + ] + + result = + %{:'agent-id' => "agentID"} + |> Poison.encode!() + |> post(url, headers) + + assert {401, :nobody} == result + end + + test "try with wrong user/password [MSGPACK]" do + url = @base_url <> "/session" + mime_type = "application/msgpack" + headers = [ + {"Content-Type", mime_type}, + {"authorization", "Basic " <> Base.encode64(@user <> ":" <> "wrongpassword")} + ] + + result = + %{:'agent-id' => "agentID"} + |> Msgpax.pack!() + |> post(url, headers) + + assert {401, :nobody} == result + end + + test "testing an unnexisting endpoint" do + url = @base_url <> "/thisdoesntexist" + mime_type = "application/json" + headers = [ + {"Content-Type", mime_type} + ] + + result = + %{:'agent-id' => "agentID"} + |> Poison.encode!() + |> post(url, headers) + + assert {404, :nobody} == result + end + + # ---------------------------------------- + # Internal functions + # ---------------------------------------- + + defp create_user do + {:ok, _user} = Auth.create_user(@user, @password) + :ok + end + + defp post(data, url, headers) do + options = [ssl: [{:versions, [:'tlsv1.2']}], recv_timeout: 500] + {:ok, response} = HTTPoison.post(url, data, headers, options) + + body = case response.status_code do + 200 -> + {:ok, body} = Poison.decode(response.body) + body + _ -> + :nobody + end + + {response.status_code, body} + end + +end