Protect API behind a bearer token
This commit is contained in:
+1
-1
@@ -11,7 +11,7 @@ config :music_library,
|
||||
ecto_repos: [MusicLibrary.Repo],
|
||||
generators: [timestamp_type: :utc_datetime, binary_id: true]
|
||||
|
||||
config :music_library, MusicLibraryWeb, login_password: "change me"
|
||||
config :music_library, MusicLibraryWeb, login_password: "change me", api_token: "change me"
|
||||
|
||||
# Configures the endpoint
|
||||
config :music_library, MusicLibraryWeb.Endpoint,
|
||||
|
||||
+7
-1
@@ -69,10 +69,16 @@ if config_env() == :prod do
|
||||
environment variable LOGIN_PASSWORD is missing.
|
||||
"""
|
||||
|
||||
api_token =
|
||||
System.get_env("API_TOKEN") ||
|
||||
raise """
|
||||
environment variable API_TOKEN is missing.
|
||||
"""
|
||||
|
||||
host = System.get_env("PHX_HOST") || "example.com"
|
||||
port = String.to_integer(System.get_env("PORT") || "4000")
|
||||
|
||||
config :music_library, MusicLibraryWeb, login_password: login_password
|
||||
config :music_library, MusicLibraryWeb, login_password: login_password, api_token: api_token
|
||||
|
||||
config :music_library, :dns_cluster_query, System.get_env("DNS_CLUSTER_QUERY")
|
||||
|
||||
|
||||
@@ -7,11 +7,28 @@ defmodule MusicLibraryWeb.Auth do
|
||||
Plug.Crypto.secure_compare(login_password(), password)
|
||||
end
|
||||
|
||||
def require_api_token(conn, _opts) do
|
||||
with ["Bearer " <> token] <- get_req_header(conn, "authorization"),
|
||||
true <- Plug.Crypto.secure_compare(api_token(), token) do
|
||||
conn
|
||||
else
|
||||
_ ->
|
||||
conn
|
||||
|> send_resp(:unauthorized, "Unauthorized API access")
|
||||
|> halt()
|
||||
end
|
||||
end
|
||||
|
||||
defp login_password do
|
||||
Application.get_env(:music_library, MusicLibraryWeb)
|
||||
|> Keyword.fetch!(:login_password)
|
||||
end
|
||||
|
||||
defp api_token do
|
||||
Application.get_env(:music_library, MusicLibraryWeb)
|
||||
|> Keyword.fetch!(:api_token)
|
||||
end
|
||||
|
||||
def require_logged_in(conn, _opts) do
|
||||
if get_session(conn, :logged_in) do
|
||||
conn
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
defmodule MusicLibraryWeb.Router do
|
||||
use MusicLibraryWeb, :router
|
||||
|
||||
import MusicLibraryWeb.Auth, only: [require_logged_in: 2]
|
||||
import MusicLibraryWeb.Auth, only: [require_logged_in: 2, require_api_token: 2]
|
||||
|
||||
pipeline :browser do
|
||||
plug :accepts, ["html"]
|
||||
@@ -14,6 +14,7 @@ defmodule MusicLibraryWeb.Router do
|
||||
|
||||
pipeline :api do
|
||||
plug :accepts, ["json"]
|
||||
plug :require_api_token
|
||||
end
|
||||
|
||||
pipeline :logged_in do
|
||||
|
||||
@@ -335,7 +335,7 @@ msgstr ""
|
||||
msgid "Wishlist"
|
||||
msgstr ""
|
||||
|
||||
#: lib/music_library_web/auth.ex:20
|
||||
#: lib/music_library_web/auth.ex:37
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You must be logged in to access this page"
|
||||
msgstr ""
|
||||
|
||||
@@ -7,12 +7,26 @@ defmodule MusicLibraryWeb.CollectionControllerTest do
|
||||
%{record: record_fixture_with_artist("Steven Wilson")}
|
||||
end
|
||||
|
||||
defp api_token do
|
||||
Application.get_env(:music_library, MusicLibraryWeb)
|
||||
|> Keyword.fetch!(:api_token)
|
||||
end
|
||||
|
||||
describe "GET /api/collection/latest" do
|
||||
setup [:create_record]
|
||||
|
||||
test "it returns the latest record", %{conn: conn, record: record} do
|
||||
test "it requires authentication", %{conn: conn} do
|
||||
conn = get(conn, ~p"/api/collection/latest")
|
||||
|
||||
assert conn.status == 401
|
||||
end
|
||||
|
||||
test "it returns the latest record", %{conn: conn, record: record} do
|
||||
conn =
|
||||
conn
|
||||
|> put_req_header("authorization", "Bearer #{api_token()}")
|
||||
|> get(~p"/api/collection/latest")
|
||||
|
||||
assert json_response(conn, 200) == %{
|
||||
"artists" => ["Steven Wilson"],
|
||||
"title" => record.title,
|
||||
|
||||
Reference in New Issue
Block a user