[#1682] Fixed Basic Auth permissions issue by disabling OAuth scopes checks when password is provided. Refactored plugs skipping functionality.
This commit is contained in:
parent
da4923f2e5
commit
862d4886c9
8 changed files with 100 additions and 23 deletions
|
|
@ -4,8 +4,11 @@
|
|||
|
||||
defmodule Pleroma.Plugs.AuthenticationPlug do
|
||||
alias Comeonin.Pbkdf2
|
||||
import Plug.Conn
|
||||
alias Pleroma.Plugs.OAuthScopesPlug
|
||||
alias Pleroma.User
|
||||
|
||||
import Plug.Conn
|
||||
|
||||
require Logger
|
||||
|
||||
def init(options), do: options
|
||||
|
|
@ -37,6 +40,7 @@ defmodule Pleroma.Plugs.AuthenticationPlug do
|
|||
if Pbkdf2.checkpw(password, password_hash) do
|
||||
conn
|
||||
|> assign(:user, auth_user)
|
||||
|> OAuthScopesPlug.skip_plug()
|
||||
else
|
||||
conn
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
defmodule Pleroma.Plugs.LegacyAuthenticationPlug do
|
||||
import Plug.Conn
|
||||
|
||||
alias Pleroma.Plugs.OAuthScopesPlug
|
||||
alias Pleroma.User
|
||||
|
||||
def init(options) do
|
||||
|
|
@ -27,6 +29,7 @@ defmodule Pleroma.Plugs.LegacyAuthenticationPlug do
|
|||
conn
|
||||
|> assign(:auth_user, user)
|
||||
|> assign(:user, user)
|
||||
|> OAuthScopesPlug.skip_plug()
|
||||
else
|
||||
_ ->
|
||||
conn
|
||||
|
|
|
|||
|
|
@ -5,30 +5,32 @@
|
|||
defmodule Pleroma.Plugs.PlugHelper do
|
||||
@moduledoc "Pleroma Plug helper"
|
||||
|
||||
def append_to_called_plugs(conn, plug_module) do
|
||||
append_to_private_list(conn, :called_plugs, plug_module)
|
||||
end
|
||||
@called_plugs_list_id :called_plugs
|
||||
def called_plugs_list_id, do: @called_plugs_list_id
|
||||
|
||||
def append_to_skipped_plugs(conn, plug_module) do
|
||||
append_to_private_list(conn, :skipped_plugs, plug_module)
|
||||
end
|
||||
@skipped_plugs_list_id :skipped_plugs
|
||||
def skipped_plugs_list_id, do: @skipped_plugs_list_id
|
||||
|
||||
@doc "Returns `true` if specified plug was called."
|
||||
def plug_called?(conn, plug_module) do
|
||||
contained_in_private_list?(conn, :called_plugs, plug_module)
|
||||
contained_in_private_list?(conn, @called_plugs_list_id, plug_module)
|
||||
end
|
||||
|
||||
@doc "Returns `true` if specified plug was explicitly marked as skipped."
|
||||
def plug_skipped?(conn, plug_module) do
|
||||
contained_in_private_list?(conn, :skipped_plugs, plug_module)
|
||||
contained_in_private_list?(conn, @skipped_plugs_list_id, plug_module)
|
||||
end
|
||||
|
||||
@doc "Returns `true` if specified plug was either called or explicitly marked as skipped."
|
||||
def plug_called_or_skipped?(conn, plug_module) do
|
||||
plug_called?(conn, plug_module) || plug_skipped?(conn, plug_module)
|
||||
end
|
||||
|
||||
defp append_to_private_list(conn, private_variable, value) do
|
||||
list = conn.private[private_variable] || []
|
||||
# Appends plug to known list (skipped, called). Intended to be used from within plug code only.
|
||||
def append_to_private_list(conn, list_id, value) do
|
||||
list = conn.private[list_id] || []
|
||||
modified_list = Enum.uniq(list ++ [value])
|
||||
Plug.Conn.put_private(conn, private_variable, modified_list)
|
||||
Plug.Conn.put_private(conn, list_id, modified_list)
|
||||
end
|
||||
|
||||
defp contained_in_private_list?(conn, private_variable, value) do
|
||||
|
|
|
|||
|
|
@ -40,17 +40,22 @@ defmodule Pleroma.Web do
|
|||
# Marks a plug intentionally skipped and blocks its execution if it's present in plugs chain
|
||||
defp skip_plug(conn, plug_module) do
|
||||
try do
|
||||
plug_module.ensure_skippable()
|
||||
plug_module.skip_plug(conn)
|
||||
rescue
|
||||
UndefinedFunctionError ->
|
||||
raise "#{plug_module} is not skippable. Append `use Pleroma.Web, :plug` to its code."
|
||||
end
|
||||
|
||||
PlugHelper.append_to_skipped_plugs(conn, plug_module)
|
||||
end
|
||||
|
||||
# Here we can apply before-action hooks (e.g. verify whether auth checks were preformed)
|
||||
# Executed just before actual controller action, invokes before-action hooks (callbacks)
|
||||
defp action(conn, params) do
|
||||
with %Plug.Conn{halted: false} <- maybe_halt_on_missing_oauth_scopes_check(conn) do
|
||||
super(conn, params)
|
||||
end
|
||||
end
|
||||
|
||||
# Halts if authenticated API action neither performs nor explicitly skips OAuth scopes check
|
||||
defp maybe_halt_on_missing_oauth_scopes_check(conn) do
|
||||
if Pleroma.Plugs.AuthExpectedPlug.auth_expected?(conn) &&
|
||||
not PlugHelper.plug_called_or_skipped?(conn, Pleroma.Plugs.OAuthScopesPlug) do
|
||||
conn
|
||||
|
|
@ -60,7 +65,7 @@ defmodule Pleroma.Web do
|
|||
)
|
||||
|> halt()
|
||||
else
|
||||
super(conn, params)
|
||||
conn
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -129,7 +134,16 @@ defmodule Pleroma.Web do
|
|||
quote do
|
||||
alias Pleroma.Plugs.PlugHelper
|
||||
|
||||
def ensure_skippable, do: :noop
|
||||
@doc """
|
||||
Marks a plug intentionally skipped and blocks its execution if it's present in plugs chain.
|
||||
"""
|
||||
def skip_plug(conn) do
|
||||
PlugHelper.append_to_private_list(
|
||||
conn,
|
||||
PlugHelper.skipped_plugs_list_id(),
|
||||
__MODULE__
|
||||
)
|
||||
end
|
||||
|
||||
@impl Plug
|
||||
@doc "If marked as skipped, returns `conn`, and calls `perform/2` otherwise."
|
||||
|
|
@ -138,7 +152,7 @@ defmodule Pleroma.Web do
|
|||
conn
|
||||
else
|
||||
conn
|
||||
|> PlugHelper.append_to_called_plugs(__MODULE__)
|
||||
|> PlugHelper.append_to_private_list(PlugHelper.called_plugs_list_id(), __MODULE__)
|
||||
|> perform(options)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue