From a1b95a6334a230c4e2d84f37760b9ca49a519c09 Mon Sep 17 00:00:00 2001 From: Anthony Kinsey Date: Fri, 17 Jan 2025 10:34:44 -1000 Subject: [PATCH 1/2] feat(api-key): check for api key on public routes --- config/runtime.exs | 1 + lib/epochtalk_server_web/endpoint.ex | 2 +- .../plugs/check_api_key.ex | 35 +++++++++++++++++++ lib/epochtalk_server_web/router.ex | 1 + 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 lib/epochtalk_server_web/plugs/check_api_key.ex diff --git a/config/runtime.exs b/config/runtime.exs index 7d023034..3df7c5fc 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -71,6 +71,7 @@ EpochtalkServer.RateLimiter.init() ## Frontend configurations config :epochtalk_server, :frontend_config, %{ + api_key: System.get_env("API_KEY", "ABC123"), frontend_url: System.get_env("FRONTEND_URL", "http://localhost:8000"), backend_url: System.get_env("BACKEND_URL", "http://localhost:4000"), newbie_enabled: get_env_cast_bool_with_default.("NEWBIE_ENABLED", "FALSE"), diff --git a/lib/epochtalk_server_web/endpoint.ex b/lib/epochtalk_server_web/endpoint.ex index 77ddca5a..815502fb 100644 --- a/lib/epochtalk_server_web/endpoint.ex +++ b/lib/epochtalk_server_web/endpoint.ex @@ -10,7 +10,7 @@ defmodule EpochtalkServerWeb.Endpoint do # origins: "*", origins: ~r{^https?://(.*\.)?epochtalk\.com$}, allow_headers: :all, - expose_headers: ["epoch-viewer"] + expose_headers: ["epoch-viewer", "api-key"] socket "/socket", EpochtalkServerWeb.UserSocket, websocket: true, diff --git a/lib/epochtalk_server_web/plugs/check_api_key.ex b/lib/epochtalk_server_web/plugs/check_api_key.ex new file mode 100644 index 00000000..f048589f --- /dev/null +++ b/lib/epochtalk_server_web/plugs/check_api_key.ex @@ -0,0 +1,35 @@ +defmodule EpochtalkServerWeb.Plugs.CheckAPIKey do + @moduledoc """ + Plug that tracks user IP address for PUT POST or PATCH operations + """ + use Plug.Builder + import Plug.Conn + + @env Mix.env() + @methods ~w(GET POST PUT PATCH) + + plug(:check_api_key) + + @doc """ + Validates and checks API key sent from frontend against one stored on backend + """ + def check_api_key(conn, _opts) do + %{method: method} = conn + + if method in @methods and @env != :test do + try_verify(conn) + else + conn + end + end + + defp try_verify(conn) do + config = Application.get_env(:epochtalk_server, :frontend_config) + api_key = config[:api_key] + [req_api_key] = get_req_header(conn, "api-key") + + if api_key == req_api_key, + do: conn, + else: raise(Plug.BadRequestError) + end +end diff --git a/lib/epochtalk_server_web/router.ex b/lib/epochtalk_server_web/router.ex index 98225547..4fea6b68 100644 --- a/lib/epochtalk_server_web/router.ex +++ b/lib/epochtalk_server_web/router.ex @@ -20,6 +20,7 @@ defmodule EpochtalkServerWeb.Router do plug EpochtalkServerWeb.Plugs.TrackIp # Track user last active plug EpochtalkServerWeb.Plugs.UserLastActive + plug EpochtalkServerWeb.Plugs.CheckAPIKey end pipeline :enforce_auth do From 88d062cc6432588f98702d25ad3c52f77be3b7ce Mon Sep 17 00:00:00 2001 From: Anthony Kinsey Date: Fri, 17 Jan 2025 10:36:30 -1000 Subject: [PATCH 2/2] feat(example-env): update to add api key --- example.env | 1 + 1 file changed, 1 insertion(+) diff --git a/example.env b/example.env index 0a9b3567..d0b7ec0a 100644 --- a/example.env +++ b/example.env @@ -4,3 +4,4 @@ AWS_REGION=us-west-2 IMAGES_MODE=S3 S3_BUCKET=xxxxxxxxxxxxx SECRET_KEY_BASE=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +API_KEY=ABC123