aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma/web/plugs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma/web/plugs')
-rw-r--r--lib/pleroma/web/plugs/admin_secret_authentication_plug.ex22
-rw-r--r--lib/pleroma/web/plugs/authentication_plug.ex63
-rw-r--r--lib/pleroma/web/plugs/basic_auth_decoder_plug.ex6
-rw-r--r--lib/pleroma/web/plugs/ensure_user_key_plug.ex18
-rw-r--r--lib/pleroma/web/plugs/ensure_user_token_assigns_plug.ex36
-rw-r--r--lib/pleroma/web/plugs/legacy_authentication_plug.ex41
-rw-r--r--lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex51
-rw-r--r--lib/pleroma/web/plugs/o_auth_plug.ex93
-rw-r--r--lib/pleroma/web/plugs/o_auth_scopes_plug.ex12
-rw-r--r--lib/pleroma/web/plugs/session_authentication_plug.ex21
-rw-r--r--lib/pleroma/web/plugs/set_user_session_id_plug.ex9
-rw-r--r--lib/pleroma/web/plugs/user_enabled_plug.ex9
-rw-r--r--lib/pleroma/web/plugs/user_fetcher_plug.ex6
13 files changed, 166 insertions, 221 deletions
diff --git a/lib/pleroma/web/plugs/admin_secret_authentication_plug.ex b/lib/pleroma/web/plugs/admin_secret_authentication_plug.ex
index d7d4e4092..ff851a874 100644
--- a/lib/pleroma/web/plugs/admin_secret_authentication_plug.ex
+++ b/lib/pleroma/web/plugs/admin_secret_authentication_plug.ex
@@ -5,21 +5,14 @@
defmodule Pleroma.Web.Plugs.AdminSecretAuthenticationPlug do
import Plug.Conn
+ alias Pleroma.Helpers.AuthHelper
alias Pleroma.User
- alias Pleroma.Web.Plugs.OAuthScopesPlug
alias Pleroma.Web.Plugs.RateLimiter
def init(options) do
options
end
- def secret_token do
- case Pleroma.Config.get(:admin_token) do
- blank when blank in [nil, ""] -> nil
- token -> token
- end
- end
-
def call(%{assigns: %{user: %User{}}} = conn, _), do: conn
def call(conn, _) do
@@ -30,7 +23,7 @@ defmodule Pleroma.Web.Plugs.AdminSecretAuthenticationPlug do
end
end
- def authenticate(%{params: %{"admin_token" => admin_token}} = conn) do
+ defp authenticate(%{params: %{"admin_token" => admin_token}} = conn) do
if admin_token == secret_token() do
assign_admin_user(conn)
else
@@ -38,7 +31,7 @@ defmodule Pleroma.Web.Plugs.AdminSecretAuthenticationPlug do
end
end
- def authenticate(conn) do
+ defp authenticate(conn) do
token = secret_token()
case get_req_header(conn, "x-admin-token") do
@@ -48,10 +41,17 @@ defmodule Pleroma.Web.Plugs.AdminSecretAuthenticationPlug do
end
end
+ defp secret_token do
+ case Pleroma.Config.get(:admin_token) do
+ blank when blank in [nil, ""] -> nil
+ token -> token
+ end
+ end
+
defp assign_admin_user(conn) do
conn
|> assign(:user, %User{is_admin: true})
- |> OAuthScopesPlug.skip_plug()
+ |> AuthHelper.skip_oauth()
end
defp handle_bad_token(conn) do
diff --git a/lib/pleroma/web/plugs/authentication_plug.ex b/lib/pleroma/web/plugs/authentication_plug.ex
index e2a8b1b69..a7b8a9bfe 100644
--- a/lib/pleroma/web/plugs/authentication_plug.ex
+++ b/lib/pleroma/web/plugs/authentication_plug.ex
@@ -3,6 +3,9 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.AuthenticationPlug do
+ @moduledoc "Password authentication plug."
+
+ alias Pleroma.Helpers.AuthHelper
alias Pleroma.User
import Plug.Conn
@@ -11,6 +14,30 @@ defmodule Pleroma.Web.Plugs.AuthenticationPlug do
def init(options), do: options
+ def call(%{assigns: %{user: %User{}}} = conn, _), do: conn
+
+ def call(
+ %{
+ assigns: %{
+ auth_user: %{password_hash: password_hash} = auth_user,
+ auth_credentials: %{password: password}
+ }
+ } = conn,
+ _
+ ) do
+ if checkpw(password, password_hash) do
+ {:ok, auth_user} = maybe_update_password(auth_user, password)
+
+ conn
+ |> assign(:user, auth_user)
+ |> AuthHelper.skip_oauth()
+ else
+ conn
+ end
+ end
+
+ def call(conn, _), do: conn
+
def checkpw(password, "$6" <> _ = password_hash) do
:crypt.crypt(password, password_hash) == password_hash
end
@@ -40,40 +67,6 @@ defmodule Pleroma.Web.Plugs.AuthenticationPlug do
def maybe_update_password(user, _), do: {:ok, user}
defp do_update_password(user, password) do
- user
- |> User.password_update_changeset(%{
- "password" => password,
- "password_confirmation" => password
- })
- |> Pleroma.Repo.update()
+ User.reset_password(user, %{password: password, password_confirmation: password})
end
-
- def call(%{assigns: %{user: %User{}}} = conn, _), do: conn
-
- def call(
- %{
- assigns: %{
- auth_user: %{password_hash: password_hash} = auth_user,
- auth_credentials: %{password: password}
- }
- } = conn,
- _
- ) do
- if checkpw(password, password_hash) do
- {:ok, auth_user} = maybe_update_password(auth_user, password)
-
- conn
- |> assign(:user, auth_user)
- |> Pleroma.Web.Plugs.OAuthScopesPlug.skip_plug()
- else
- conn
- end
- end
-
- def call(%{assigns: %{auth_credentials: %{password: _}}} = conn, _) do
- Pbkdf2.no_user_verify()
- conn
- end
-
- def call(conn, _), do: conn
end
diff --git a/lib/pleroma/web/plugs/basic_auth_decoder_plug.ex b/lib/pleroma/web/plugs/basic_auth_decoder_plug.ex
index 4dadfb000..97529aedb 100644
--- a/lib/pleroma/web/plugs/basic_auth_decoder_plug.ex
+++ b/lib/pleroma/web/plugs/basic_auth_decoder_plug.ex
@@ -3,6 +3,12 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.BasicAuthDecoderPlug do
+ @moduledoc """
+ Decodes HTTP Basic Auth information and assigns `:auth_credentials`.
+
+ NOTE: no checks are performed at this step, auth_credentials/username could be easily faked.
+ """
+
import Plug.Conn
def init(options) do
diff --git a/lib/pleroma/web/plugs/ensure_user_key_plug.ex b/lib/pleroma/web/plugs/ensure_user_key_plug.ex
deleted file mode 100644
index 70d3091f0..000000000
--- a/lib/pleroma/web/plugs/ensure_user_key_plug.ex
+++ /dev/null
@@ -1,18 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.Plugs.EnsureUserKeyPlug do
- import Plug.Conn
-
- def init(opts) do
- opts
- end
-
- def call(%{assigns: %{user: _}} = conn, _), do: conn
-
- def call(conn, _) do
- conn
- |> assign(:user, nil)
- end
-end
diff --git a/lib/pleroma/web/plugs/ensure_user_token_assigns_plug.ex b/lib/pleroma/web/plugs/ensure_user_token_assigns_plug.ex
new file mode 100644
index 000000000..4253458b2
--- /dev/null
+++ b/lib/pleroma/web/plugs/ensure_user_token_assigns_plug.ex
@@ -0,0 +1,36 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.Plugs.EnsureUserTokenAssignsPlug do
+ import Plug.Conn
+
+ alias Pleroma.Helpers.AuthHelper
+ alias Pleroma.User
+ alias Pleroma.Web.OAuth.Token
+
+ @moduledoc "Ensures presence and consistency of :user and :token assigns."
+
+ def init(opts) do
+ opts
+ end
+
+ def call(%{assigns: %{user: %User{id: user_id}} = assigns} = conn, _) do
+ with %Token{user_id: ^user_id} <- assigns[:token] do
+ conn
+ else
+ %Token{} ->
+ # A safety net for abnormal (unexpected) scenario: :token belongs to another user
+ AuthHelper.drop_auth_info(conn)
+
+ _ ->
+ assign(conn, :token, nil)
+ end
+ end
+
+ def call(conn, _) do
+ conn
+ |> assign(:user, nil)
+ |> assign(:token, nil)
+ end
+end
diff --git a/lib/pleroma/web/plugs/legacy_authentication_plug.ex b/lib/pleroma/web/plugs/legacy_authentication_plug.ex
deleted file mode 100644
index 2a54d0b59..000000000
--- a/lib/pleroma/web/plugs/legacy_authentication_plug.ex
+++ /dev/null
@@ -1,41 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.Plugs.LegacyAuthenticationPlug do
- import Plug.Conn
-
- alias Pleroma.User
-
- def init(options) do
- options
- end
-
- def call(%{assigns: %{user: %User{}}} = conn, _), do: conn
-
- def call(
- %{
- assigns: %{
- auth_user: %{password_hash: "$6$" <> _ = password_hash} = auth_user,
- auth_credentials: %{password: password}
- }
- } = conn,
- _
- ) do
- with ^password_hash <- :crypt.crypt(password, password_hash),
- {:ok, user} <-
- User.reset_password(auth_user, %{password: password, password_confirmation: password}) do
- conn
- |> assign(:auth_user, user)
- |> assign(:user, user)
- |> Pleroma.Web.Plugs.OAuthScopesPlug.skip_plug()
- else
- _ ->
- conn
- end
- end
-
- def call(conn, _) do
- conn
- end
-end
diff --git a/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex b/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex
index f44d4dee5..a0a0c5a9b 100644
--- a/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex
+++ b/lib/pleroma/web/plugs/mapped_signature_to_identity_plug.ex
@@ -3,6 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlug do
+ alias Pleroma.Helpers.AuthHelper
alias Pleroma.Signature
alias Pleroma.User
alias Pleroma.Web.ActivityPub.Utils
@@ -12,34 +13,16 @@ defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlug do
def init(options), do: options
- defp key_id_from_conn(conn) do
- with %{"keyId" => key_id} <- HTTPSignatures.signature_for_conn(conn),
- {:ok, ap_id} <- Signature.key_id_to_actor_id(key_id) do
- ap_id
- else
- _ ->
- nil
- end
- end
-
- defp user_from_key_id(conn) do
- with key_actor_id when is_binary(key_actor_id) <- key_id_from_conn(conn),
- {:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(key_actor_id) do
- user
- else
- _ ->
- nil
- end
- end
-
- def call(%{assigns: %{user: _}} = conn, _opts), do: conn
+ def call(%{assigns: %{user: %User{}}} = conn, _opts), do: conn
# if this has payload make sure it is signed by the same actor that made it
def call(%{assigns: %{valid_signature: true}, params: %{"actor" => actor}} = conn, _opts) do
with actor_id <- Utils.get_ap_id(actor),
{:user, %User{} = user} <- {:user, user_from_key_id(conn)},
{:user_match, true} <- {:user_match, user.ap_id == actor_id} do
- assign(conn, :user, user)
+ conn
+ |> assign(:user, user)
+ |> AuthHelper.skip_oauth()
else
{:user_match, false} ->
Logger.debug("Failed to map identity from signature (payload actor mismatch)")
@@ -57,7 +40,9 @@ defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlug do
# no payload, probably a signed fetch
def call(%{assigns: %{valid_signature: true}} = conn, _opts) do
with %User{} = user <- user_from_key_id(conn) do
- assign(conn, :user, user)
+ conn
+ |> assign(:user, user)
+ |> AuthHelper.skip_oauth()
else
_ ->
Logger.debug("Failed to map identity from signature (no payload actor mismatch)")
@@ -68,4 +53,24 @@ defmodule Pleroma.Web.Plugs.MappedSignatureToIdentityPlug do
# no signature at all
def call(conn, _opts), do: conn
+
+ defp key_id_from_conn(conn) do
+ with %{"keyId" => key_id} <- HTTPSignatures.signature_for_conn(conn),
+ {:ok, ap_id} <- Signature.key_id_to_actor_id(key_id) do
+ ap_id
+ else
+ _ ->
+ nil
+ end
+ end
+
+ defp user_from_key_id(conn) do
+ with key_actor_id when is_binary(key_actor_id) <- key_id_from_conn(conn),
+ {:ok, %User{} = user} <- User.get_or_fetch_by_ap_id(key_actor_id) do
+ user
+ else
+ _ ->
+ nil
+ end
+ end
end
diff --git a/lib/pleroma/web/plugs/o_auth_plug.ex b/lib/pleroma/web/plugs/o_auth_plug.ex
index c7b58d90f..eb287318b 100644
--- a/lib/pleroma/web/plugs/o_auth_plug.ex
+++ b/lib/pleroma/web/plugs/o_auth_plug.ex
@@ -3,9 +3,12 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.OAuthPlug do
+ @moduledoc "Performs OAuth authentication by token from params / headers / cookies."
+
import Plug.Conn
import Ecto.Query
+ alias Pleroma.Helpers.AuthHelper
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.OAuth.App
@@ -17,45 +20,26 @@ defmodule Pleroma.Web.Plugs.OAuthPlug do
def call(%{assigns: %{user: %User{}}} = conn, _), do: conn
- def call(%{params: %{"access_token" => access_token}} = conn, _) do
- with {:ok, user, token_record} <- fetch_user_and_token(access_token) do
- conn
- |> assign(:token, token_record)
- |> assign(:user, user)
- else
- _ ->
- # token found, but maybe only with app
- with {:ok, app, token_record} <- fetch_app_and_token(access_token) do
- conn
- |> assign(:token, token_record)
- |> assign(:app, app)
- else
- _ -> conn
- end
- end
- end
-
def call(conn, _) do
- case fetch_token_str(conn) do
- {:ok, token} ->
- with {:ok, user, token_record} <- fetch_user_and_token(token) do
- conn
- |> assign(:token, token_record)
- |> assign(:user, user)
- else
- _ ->
- # token found, but maybe only with app
- with {:ok, app, token_record} <- fetch_app_and_token(token) do
- conn
- |> assign(:token, token_record)
- |> assign(:app, app)
- else
- _ -> conn
- end
- end
-
- _ ->
+ with {:ok, token_str} <- fetch_token_str(conn) do
+ with {:ok, user, user_token} <- fetch_user_and_token(token_str),
+ false <- Token.is_expired?(user_token) do
conn
+ |> assign(:token, user_token)
+ |> assign(:user, user)
+ else
+ _ ->
+ with {:ok, app, app_token} <- fetch_app_and_token(token_str),
+ false <- Token.is_expired?(app_token) do
+ conn
+ |> assign(:token, app_token)
+ |> assign(:app, app)
+ else
+ _ -> conn
+ end
+ end
+ else
+ _ -> conn
end
end
@@ -70,7 +54,6 @@ defmodule Pleroma.Web.Plugs.OAuthPlug do
preload: [user: user]
)
- # credo:disable-for-next-line Credo.Check.Readability.MaxLineLength
with %Token{user: user} = token_record <- Repo.one(query) do
{:ok, user, token_record}
end
@@ -86,29 +69,23 @@ defmodule Pleroma.Web.Plugs.OAuthPlug do
end
end
- # Gets token from session by :oauth_token key
+ # Gets token string from conn (in params / headers / session)
#
- @spec fetch_token_from_session(Plug.Conn.t()) :: :no_token_found | {:ok, String.t()}
- defp fetch_token_from_session(conn) do
- case get_session(conn, :oauth_token) do
- nil -> :no_token_found
- token -> {:ok, token}
- end
+ @spec fetch_token_str(Plug.Conn.t() | list(String.t())) :: :no_token_found | {:ok, String.t()}
+ defp fetch_token_str(%Plug.Conn{params: %{"access_token" => access_token}} = _conn) do
+ {:ok, access_token}
end
- # Gets token from headers
- #
- @spec fetch_token_str(Plug.Conn.t()) :: :no_token_found | {:ok, String.t()}
defp fetch_token_str(%Plug.Conn{} = conn) do
headers = get_req_header(conn, "authorization")
- with :no_token_found <- fetch_token_str(headers),
- do: fetch_token_from_session(conn)
+ with {:ok, token} <- fetch_token_str(headers) do
+ {:ok, token}
+ else
+ _ -> fetch_token_from_session(conn)
+ end
end
- @spec fetch_token_str(Keyword.t()) :: :no_token_found | {:ok, String.t()}
- defp fetch_token_str([]), do: :no_token_found
-
defp fetch_token_str([token | tail]) do
trimmed_token = String.trim(token)
@@ -117,4 +94,14 @@ defmodule Pleroma.Web.Plugs.OAuthPlug do
_ -> fetch_token_str(tail)
end
end
+
+ defp fetch_token_str([]), do: :no_token_found
+
+ @spec fetch_token_from_session(Plug.Conn.t()) :: :no_token_found | {:ok, String.t()}
+ defp fetch_token_from_session(conn) do
+ case AuthHelper.get_session_token(conn) do
+ nil -> :no_token_found
+ token -> {:ok, token}
+ end
+ end
end
diff --git a/lib/pleroma/web/plugs/o_auth_scopes_plug.ex b/lib/pleroma/web/plugs/o_auth_scopes_plug.ex
index cfc30837c..e6d398b14 100644
--- a/lib/pleroma/web/plugs/o_auth_scopes_plug.ex
+++ b/lib/pleroma/web/plugs/o_auth_scopes_plug.ex
@@ -7,6 +7,7 @@ defmodule Pleroma.Web.Plugs.OAuthScopesPlug do
import Pleroma.Web.Gettext
alias Pleroma.Config
+ alias Pleroma.Helpers.AuthHelper
use Pleroma.Web, :plug
@@ -28,7 +29,7 @@ defmodule Pleroma.Web.Plugs.OAuthScopesPlug do
conn
options[:fallback] == :proceed_unauthenticated ->
- drop_auth_info(conn)
+ AuthHelper.drop_auth_info(conn)
true ->
missing_scopes = scopes -- matched_scopes
@@ -44,15 +45,6 @@ defmodule Pleroma.Web.Plugs.OAuthScopesPlug do
end
end
- @doc "Drops authentication info from connection"
- def drop_auth_info(conn) do
- # To simplify debugging, setting a private variable on `conn` if auth info is dropped
- conn
- |> put_private(:authentication_ignored, true)
- |> assign(:user, nil)
- |> assign(:token, nil)
- end
-
@doc "Keeps those of `scopes` which are descendants of `supported_scopes`"
def filter_descendants(scopes, supported_scopes) do
Enum.filter(
diff --git a/lib/pleroma/web/plugs/session_authentication_plug.ex b/lib/pleroma/web/plugs/session_authentication_plug.ex
deleted file mode 100644
index 6e176d553..000000000
--- a/lib/pleroma/web/plugs/session_authentication_plug.ex
+++ /dev/null
@@ -1,21 +0,0 @@
-# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
-# SPDX-License-Identifier: AGPL-3.0-only
-
-defmodule Pleroma.Web.Plugs.SessionAuthenticationPlug do
- import Plug.Conn
-
- def init(options) do
- options
- end
-
- def call(conn, _) do
- with saved_user_id <- get_session(conn, :user_id),
- %{auth_user: %{id: ^saved_user_id}} <- conn.assigns do
- conn
- |> assign(:user, conn.assigns.auth_user)
- else
- _ -> conn
- end
- end
-end
diff --git a/lib/pleroma/web/plugs/set_user_session_id_plug.ex b/lib/pleroma/web/plugs/set_user_session_id_plug.ex
index e520159e4..9f4a6b6ac 100644
--- a/lib/pleroma/web/plugs/set_user_session_id_plug.ex
+++ b/lib/pleroma/web/plugs/set_user_session_id_plug.ex
@@ -3,16 +3,15 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.SetUserSessionIdPlug do
- import Plug.Conn
- alias Pleroma.User
+ alias Pleroma.Helpers.AuthHelper
+ alias Pleroma.Web.OAuth.Token
def init(opts) do
opts
end
- def call(%{assigns: %{user: %User{id: id}}} = conn, _) do
- conn
- |> put_session(:user_id, id)
+ def call(%{assigns: %{token: %Token{} = oauth_token}} = conn, _) do
+ AuthHelper.put_session_token(conn, oauth_token.token)
end
def call(conn, _), do: conn
diff --git a/lib/pleroma/web/plugs/user_enabled_plug.ex b/lib/pleroma/web/plugs/user_enabled_plug.ex
index fa28ee48b..4f1b163bd 100644
--- a/lib/pleroma/web/plugs/user_enabled_plug.ex
+++ b/lib/pleroma/web/plugs/user_enabled_plug.ex
@@ -3,7 +3,7 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.UserEnabledPlug do
- import Plug.Conn
+ alias Pleroma.Helpers.AuthHelper
alias Pleroma.User
def init(options) do
@@ -11,9 +11,10 @@ defmodule Pleroma.Web.Plugs.UserEnabledPlug do
end
def call(%{assigns: %{user: %User{} = user}} = conn, _) do
- case User.account_status(user) do
- :active -> conn
- _ -> assign(conn, :user, nil)
+ if User.account_status(user) == :active do
+ conn
+ else
+ AuthHelper.drop_auth_info(conn)
end
end
diff --git a/lib/pleroma/web/plugs/user_fetcher_plug.ex b/lib/pleroma/web/plugs/user_fetcher_plug.ex
index 4039600da..89e16b49f 100644
--- a/lib/pleroma/web/plugs/user_fetcher_plug.ex
+++ b/lib/pleroma/web/plugs/user_fetcher_plug.ex
@@ -3,6 +3,12 @@
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.Plugs.UserFetcherPlug do
+ @moduledoc """
+ Assigns `:auth_user` basing on `:auth_credentials`.
+
+ NOTE: no checks are performed at this step, auth_credentials/username could be easily faked.
+ """
+
alias Pleroma.User
import Plug.Conn