Support authentication via `x-admin-token` HTTP header
authorEgor Kislitsyn <egor@kislitsyn.com>
Tue, 19 Nov 2019 08:58:20 +0000 (15:58 +0700)
committerEgor Kislitsyn <egor@kislitsyn.com>
Tue, 19 Nov 2019 08:58:20 +0000 (15:58 +0700)
CHANGELOG.md
docs/configuration/cheatsheet.md
lib/pleroma/plugs/admin_secret_authentication_plug.ex
test/plugs/admin_secret_authentication_plug_test.exs

index 1d9b97f0b88c00c955c6338ab0f141c543ce7a5b..00fc00ca8ca10bce996ceba1d66559fd8c22907b 100644 (file)
@@ -30,6 +30,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
 - Admin API: Return `total` when querying for reports
 - Mastodon API: Return `pleroma.direct_conversation_id` when creating a direct message (`POST /api/v1/statuses`)
 - Admin API: Return link alongside with token on password reset
+- Admin API: Support authentication via `x-admin-token` HTTP header
 - Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`)
 - Mastodon API: `pleroma.thread_muted` to the Status entity
 - Mastodon API: Mark the direct conversation as read for the author when they send a new direct message
index d798bd692ae1a0b38113e883dd9de3f759895081..07d9a1d451765274f18633ff821fc31f4efab4c9 100644 (file)
@@ -656,7 +656,7 @@ Feel free to adjust the priv_dir and port number. Then you will have to create t
 
 ### :admin_token
 
-Allows to set a token that can be used to authenticate with the admin api without using an actual user by giving it as the 'admin_token' parameter. Example:
+Allows to set a token that can be used to authenticate with the admin api without using an actual user by giving it as the `admin_token` parameter or `x-admin-token` HTTP header. Example:
 
 ```elixir
 config :pleroma, :admin_token, "somerandomtoken"
@@ -664,8 +664,14 @@ config :pleroma, :admin_token, "somerandomtoken"
 
 You can then do
 
-```sh
-curl "http://localhost:4000/api/pleroma/admin/invite_token?admin_token=somerandomtoken"
+```shell
+curl "http://localhost:4000/api/pleroma/admin/users/invites?admin_token=somerandomtoken"
+```
+
+or
+
+```shell
+curl -H "X-Admin-Token: somerandomtoken" "http://localhost:4000/api/pleroma/admin/users/invites"
 ```
 
 ### :auth
index fdadd476e6c06320f9bfa708024764789482ccfd..49dea452d4fe9e092a4fd50f750bfc8a8da8e4e2 100644 (file)
@@ -16,14 +16,28 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlug do
 
   def call(%{assigns: %{user: %User{}}} = conn, _), do: conn
 
-  def call(%{params: %{"admin_token" => admin_token}} = conn, _) do
-    if secret_token() && admin_token == secret_token() do
+  def call(conn, _) do
+    if secret_token() do
+      authenticate(conn)
+    else
       conn
-      |> assign(:user, %User{is_admin: true})
+    end
+  end
+
+  def authenticate(%{params: %{"admin_token" => admin_token}} = conn) do
+    if admin_token == secret_token() do
+      assign(conn, :user, %User{is_admin: true})
     else
       conn
     end
   end
 
-  def call(conn, _), do: conn
+  def authenticate(conn) do
+    token = secret_token()
+
+    case get_req_header(conn, "x-admin-token") do
+      [^token] -> assign(conn, :user, %User{is_admin: true})
+      _ -> conn
+    end
+  end
 end
index c94a62c102e9bd82d1fe53801110ac8810d0ee2f..506b1f609d2d50afcd08c395930cb281bd019c15 100644 (file)
@@ -22,21 +22,39 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do
     assert conn == ret_conn
   end
 
-  test "with secret set and given in the 'admin_token' parameter, it assigns an admin user", %{
-    conn: conn
-  } do
-    Pleroma.Config.put(:admin_token, "password123")
+  describe "when secret set it assigns an admin user" do
+    test "with `admin_token` query parameter", %{conn: conn} do
+      Pleroma.Config.put(:admin_token, "password123")
 
-    conn =
-      %{conn | params: %{"admin_token" => "wrong_password"}}
-      |> AdminSecretAuthenticationPlug.call(%{})
+      conn =
+        %{conn | params: %{"admin_token" => "wrong_password"}}
+        |> AdminSecretAuthenticationPlug.call(%{})
 
-    refute conn.assigns[:user]
+      refute conn.assigns[:user]
 
-    conn =
-      %{conn | params: %{"admin_token" => "password123"}}
-      |> AdminSecretAuthenticationPlug.call(%{})
+      conn =
+        %{conn | params: %{"admin_token" => "password123"}}
+        |> AdminSecretAuthenticationPlug.call(%{})
+
+      assert conn.assigns[:user].is_admin
+    end
+
+    test "with `x-admin-token` HTTP header", %{conn: conn} do
+      Pleroma.Config.put(:admin_token, "☕️")
+
+      conn =
+        conn
+        |> put_req_header("x-admin-token", "🥛")
+        |> AdminSecretAuthenticationPlug.call(%{})
+
+      refute conn.assigns[:user]
+
+      conn =
+        conn
+        |> put_req_header("x-admin-token", "☕️")
+        |> AdminSecretAuthenticationPlug.call(%{})
 
-    assert conn.assigns[:user].is_admin
+      assert conn.assigns[:user].is_admin
+    end
   end
 end