[#2409] Tested all auth setup configs in AuthTestControllerTest. Adjusted :skip_plug definitions for some endpoints.
This commit is contained in:
parent
89f38d94c7
commit
00e62161f6
|
@ -0,0 +1,93 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
# A test controller reachable only in :test env.
|
||||||
|
defmodule Pleroma.Tests.AuthTestController do
|
||||||
|
@moduledoc false
|
||||||
|
|
||||||
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
|
||||||
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
|
alias Pleroma.User
|
||||||
|
|
||||||
|
# Serves only with proper OAuth token (:api and :authenticated_api)
|
||||||
|
# Skipping EnsurePublicOrAuthenticatedPlug has no effect in this case
|
||||||
|
#
|
||||||
|
# Suggested use case: all :authenticated_api endpoints (makes no sense for :api endpoints)
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["read"]} when action == :do_oauth_check)
|
||||||
|
|
||||||
|
# Via :api, keeps :user if token has requested scopes (if :user is dropped, serves if public)
|
||||||
|
# Via :authenticated_api, serves if token is present and has requested scopes
|
||||||
|
#
|
||||||
|
# Suggested use case: vast majority of :api endpoints (no sense for :authenticated_api ones)
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["read"], fallback: :proceed_unauthenticated}
|
||||||
|
when action == :fallback_oauth_check
|
||||||
|
)
|
||||||
|
|
||||||
|
# Keeps :user if present, executes regardless of token / token scopes
|
||||||
|
# Fails with no :user for :authenticated_api / no user for :api on private instance
|
||||||
|
# Note: EnsurePublicOrAuthenticatedPlug is not skipped (private instance fails on no :user)
|
||||||
|
# Note: Basic Auth processing results in :skip_plug call for OAuthScopesPlug
|
||||||
|
#
|
||||||
|
# Suggested use: suppressing OAuth checks for other auth mechanisms (like Basic Auth)
|
||||||
|
# For controller-level use, see :skip_oauth_skip_publicity_check instead
|
||||||
|
plug(
|
||||||
|
:skip_plug,
|
||||||
|
OAuthScopesPlug when action == :skip_oauth_check
|
||||||
|
)
|
||||||
|
|
||||||
|
# (Shouldn't be executed since the plug is skipped)
|
||||||
|
plug(OAuthScopesPlug, %{scopes: ["admin"]} when action == :skip_oauth_check)
|
||||||
|
|
||||||
|
# Via :api, keeps :user if token has requested scopes, and continues with nil :user otherwise
|
||||||
|
# Via :authenticated_api, serves if token is present and has requested scopes
|
||||||
|
#
|
||||||
|
# Suggested use: as :fallback_oauth_check but open with nil :user for :api on private instances
|
||||||
|
plug(
|
||||||
|
:skip_plug,
|
||||||
|
EnsurePublicOrAuthenticatedPlug when action == :fallback_oauth_skip_publicity_check
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(
|
||||||
|
OAuthScopesPlug,
|
||||||
|
%{scopes: ["read"], fallback: :proceed_unauthenticated}
|
||||||
|
when action == :fallback_oauth_skip_publicity_check
|
||||||
|
)
|
||||||
|
|
||||||
|
# Via :api, keeps :user if present, serves regardless of token presence / scopes / :user presence
|
||||||
|
# Via :authenticated_api, serves if :user is set (regardless of token presence and its scopes)
|
||||||
|
#
|
||||||
|
# Suggested use: making an :api endpoint always accessible (e.g. email confirmation endpoint)
|
||||||
|
plug(
|
||||||
|
:skip_plug,
|
||||||
|
[OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug]
|
||||||
|
when action == :skip_oauth_skip_publicity_check
|
||||||
|
)
|
||||||
|
|
||||||
|
# Via :authenticated_api, always fails with 403 (endpoint is insecure)
|
||||||
|
# Via :api, drops :user if present and serves if public (private instance rejects on no user)
|
||||||
|
#
|
||||||
|
# Suggested use: none; please define OAuth rules for all :api / :authenticated_api endpoints
|
||||||
|
plug(:skip_plug, [] when action == :missing_oauth_check_definition)
|
||||||
|
|
||||||
|
def do_oauth_check(conn, _params), do: conn_state(conn)
|
||||||
|
|
||||||
|
def fallback_oauth_check(conn, _params), do: conn_state(conn)
|
||||||
|
|
||||||
|
def skip_oauth_check(conn, _params), do: conn_state(conn)
|
||||||
|
|
||||||
|
def fallback_oauth_skip_publicity_check(conn, _params), do: conn_state(conn)
|
||||||
|
|
||||||
|
def skip_oauth_skip_publicity_check(conn, _params), do: conn_state(conn)
|
||||||
|
|
||||||
|
def missing_oauth_check_definition(conn, _params), do: conn_state(conn)
|
||||||
|
|
||||||
|
defp conn_state(%{assigns: %{user: %User{} = user}} = conn),
|
||||||
|
do: json(conn, %{user_id: user.id})
|
||||||
|
|
||||||
|
defp conn_state(conn), do: json(conn, %{user_id: nil})
|
||||||
|
end
|
|
@ -1,31 +0,0 @@
|
||||||
# Pleroma: A lightweight social networking server
|
|
||||||
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
|
||||||
# SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
|
|
||||||
# A test controller reachable only in :test env.
|
|
||||||
# Serves to test OAuth scopes check skipping / enforcement.
|
|
||||||
defmodule Pleroma.Tests.OAuthTestController do
|
|
||||||
@moduledoc false
|
|
||||||
|
|
||||||
use Pleroma.Web, :controller
|
|
||||||
|
|
||||||
alias Pleroma.Plugs.OAuthScopesPlug
|
|
||||||
|
|
||||||
plug(:skip_plug, OAuthScopesPlug when action == :skipped_oauth)
|
|
||||||
|
|
||||||
plug(OAuthScopesPlug, %{scopes: ["read"]} when action != :missed_oauth)
|
|
||||||
|
|
||||||
def skipped_oauth(conn, _params) do
|
|
||||||
noop(conn)
|
|
||||||
end
|
|
||||||
|
|
||||||
def performed_oauth(conn, _params) do
|
|
||||||
noop(conn)
|
|
||||||
end
|
|
||||||
|
|
||||||
def missed_oauth(conn, _params) do
|
|
||||||
noop(conn)
|
|
||||||
end
|
|
||||||
|
|
||||||
defp noop(conn), do: json(conn, %{})
|
|
||||||
end
|
|
|
@ -5,12 +5,15 @@
|
||||||
defmodule Pleroma.Web.MastoFEController do
|
defmodule Pleroma.Web.MastoFEController do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
|
||||||
alias Pleroma.Plugs.OAuthScopesPlug
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
|
||||||
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action == :put_settings)
|
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action == :put_settings)
|
||||||
|
|
||||||
# Note: :index action handles attempt of unauthenticated access to private instance with redirect
|
# Note: :index action handles attempt of unauthenticated access to private instance with redirect
|
||||||
|
plug(:skip_plug, EnsurePublicOrAuthenticatedPlug when action == :index)
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
OAuthScopesPlug,
|
OAuthScopesPlug,
|
||||||
%{scopes: ["read"], fallback: :proceed_unauthenticated}
|
%{scopes: ["read"], fallback: :proceed_unauthenticated}
|
||||||
|
@ -19,7 +22,7 @@ defmodule Pleroma.Web.MastoFEController do
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
:skip_plug,
|
:skip_plug,
|
||||||
Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action in [:index, :manifest]
|
[OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :manifest
|
||||||
)
|
)
|
||||||
|
|
||||||
@doc "GET /web/*path"
|
@doc "GET /web/*path"
|
||||||
|
|
|
@ -14,6 +14,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
||||||
skip_relationships?: 1
|
skip_relationships?: 1
|
||||||
]
|
]
|
||||||
|
|
||||||
|
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
|
||||||
alias Pleroma.Plugs.OAuthScopesPlug
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Plugs.RateLimiter
|
alias Pleroma.Plugs.RateLimiter
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
@ -26,18 +27,14 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
||||||
alias Pleroma.Web.OAuth.Token
|
alias Pleroma.Web.OAuth.Token
|
||||||
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
alias Pleroma.Web.TwitterAPI.TwitterAPI
|
||||||
|
|
||||||
plug(:skip_plug, OAuthScopesPlug when action in [:create, :identity_proofs])
|
plug(:skip_plug, [OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :create)
|
||||||
|
|
||||||
plug(
|
plug(:skip_plug, EnsurePublicOrAuthenticatedPlug when action in [:show, :statuses])
|
||||||
:skip_plug,
|
|
||||||
Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
|
|
||||||
when action in [:create, :show, :statuses]
|
|
||||||
)
|
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
OAuthScopesPlug,
|
OAuthScopesPlug,
|
||||||
%{fallback: :proceed_unauthenticated, scopes: ["read:accounts"]}
|
%{fallback: :proceed_unauthenticated, scopes: ["read:accounts"]}
|
||||||
when action in [:show, :followers, :following, :endorsements]
|
when action in [:show, :followers, :following]
|
||||||
)
|
)
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
|
@ -49,7 +46,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do
|
||||||
plug(
|
plug(
|
||||||
OAuthScopesPlug,
|
OAuthScopesPlug,
|
||||||
%{scopes: ["read:accounts"]}
|
%{scopes: ["read:accounts"]}
|
||||||
when action in [:endorsements, :verify_credentials]
|
when action in [:verify_credentials, :endorsements, :identity_proofs]
|
||||||
)
|
)
|
||||||
|
|
||||||
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action == :update_credentials)
|
plug(OAuthScopesPlug, %{scopes: ["write:accounts"]} when action == :update_credentials)
|
||||||
|
|
|
@ -24,6 +24,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
|
||||||
alias Pleroma.Web.MastodonAPI.AccountView
|
alias Pleroma.Web.MastodonAPI.AccountView
|
||||||
alias Pleroma.Web.MastodonAPI.ScheduledActivityView
|
alias Pleroma.Web.MastodonAPI.ScheduledActivityView
|
||||||
|
|
||||||
|
plug(:skip_plug, Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action in [:index, :show])
|
||||||
|
|
||||||
@unauthenticated_access %{fallback: :proceed_unauthenticated, scopes: []}
|
@unauthenticated_access %{fallback: :proceed_unauthenticated, scopes: []}
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
|
@ -77,8 +79,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusController do
|
||||||
%{scopes: ["write:bookmarks"]} when action in [:bookmark, :unbookmark]
|
%{scopes: ["write:bookmarks"]} when action in [:bookmark, :unbookmark]
|
||||||
)
|
)
|
||||||
|
|
||||||
plug(:skip_plug, Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action in [:index, :show])
|
|
||||||
|
|
||||||
@rate_limited_status_actions ~w(reblog unreblog favourite unfavourite create delete)a
|
@rate_limited_status_actions ~w(reblog unreblog favourite unfavourite create delete)a
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
|
|
|
@ -15,6 +15,8 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.ActivityPub.ActivityPub
|
alias Pleroma.Web.ActivityPub.ActivityPub
|
||||||
|
|
||||||
|
plug(:skip_plug, EnsurePublicOrAuthenticatedPlug when action in [:public, :hashtag])
|
||||||
|
|
||||||
# TODO: Replace with a macro when there is a Phoenix release with the following commit in it:
|
# TODO: Replace with a macro when there is a Phoenix release with the following commit in it:
|
||||||
# https://github.com/phoenixframework/phoenix/commit/2e8c63c01fec4dde5467dbbbf9705ff9e780735e
|
# https://github.com/phoenixframework/phoenix/commit/2e8c63c01fec4dde5467dbbbf9705ff9e780735e
|
||||||
|
|
||||||
|
@ -33,8 +35,6 @@ defmodule Pleroma.Web.MastodonAPI.TimelineController do
|
||||||
when action in [:public, :hashtag]
|
when action in [:public, :hashtag]
|
||||||
)
|
)
|
||||||
|
|
||||||
plug(:skip_plug, EnsurePublicOrAuthenticatedPlug when action in [:public, :hashtag])
|
|
||||||
|
|
||||||
plug(:put_view, Pleroma.Web.MastodonAPI.StatusView)
|
plug(:put_view, Pleroma.Web.MastodonAPI.StatusView)
|
||||||
|
|
||||||
# GET /api/v1/timelines/home
|
# GET /api/v1/timelines/home
|
||||||
|
|
|
@ -25,9 +25,10 @@ defmodule Pleroma.Web.OAuth.OAuthController do
|
||||||
|
|
||||||
plug(:fetch_session)
|
plug(:fetch_session)
|
||||||
plug(:fetch_flash)
|
plug(:fetch_flash)
|
||||||
plug(RateLimiter, [name: :authentication] when action == :create_authorization)
|
|
||||||
|
|
||||||
plug(:skip_plug, Pleroma.Plugs.OAuthScopesPlug)
|
plug(:skip_plug, [Pleroma.Plugs.OAuthScopesPlug, Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug])
|
||||||
|
|
||||||
|
plug(RateLimiter, [name: :authentication] when action == :create_authorization)
|
||||||
|
|
||||||
action_fallback(Pleroma.Web.OAuth.FallbackController)
|
action_fallback(Pleroma.Web.OAuth.FallbackController)
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
|
||||||
only: [json_response: 3, add_link_headers: 2, assign_account_by_id: 2, skip_relationships?: 1]
|
only: [json_response: 3, add_link_headers: 2, assign_account_by_id: 2, skip_relationships?: 1]
|
||||||
|
|
||||||
alias Ecto.Changeset
|
alias Ecto.Changeset
|
||||||
|
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
|
||||||
alias Pleroma.Plugs.OAuthScopesPlug
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.Plugs.RateLimiter
|
alias Pleroma.Plugs.RateLimiter
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
@ -17,11 +18,9 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do
|
||||||
|
|
||||||
require Pleroma.Constants
|
require Pleroma.Constants
|
||||||
|
|
||||||
plug(:skip_plug, OAuthScopesPlug when action == :confirmation_resend)
|
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
:skip_plug,
|
:skip_plug,
|
||||||
Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug when action == :confirmation_resend
|
[OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :confirmation_resend
|
||||||
)
|
)
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
|
|
|
@ -655,11 +655,28 @@ defmodule Pleroma.Web.Router do
|
||||||
|
|
||||||
# Test-only routes needed to test action dispatching and plug chain execution
|
# Test-only routes needed to test action dispatching and plug chain execution
|
||||||
if Pleroma.Config.get(:env) == :test do
|
if Pleroma.Config.get(:env) == :test do
|
||||||
|
@test_actions [
|
||||||
|
:do_oauth_check,
|
||||||
|
:fallback_oauth_check,
|
||||||
|
:skip_oauth_check,
|
||||||
|
:fallback_oauth_skip_publicity_check,
|
||||||
|
:skip_oauth_skip_publicity_check,
|
||||||
|
:missing_oauth_check_definition
|
||||||
|
]
|
||||||
|
|
||||||
|
scope "/test/api", Pleroma.Tests do
|
||||||
|
pipe_through(:api)
|
||||||
|
|
||||||
|
for action <- @test_actions do
|
||||||
|
get("/#{action}", AuthTestController, action)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
scope "/test/authenticated_api", Pleroma.Tests do
|
scope "/test/authenticated_api", Pleroma.Tests do
|
||||||
pipe_through(:authenticated_api)
|
pipe_through(:authenticated_api)
|
||||||
|
|
||||||
for action <- [:skipped_oauth, :performed_oauth, :missed_oauth] do
|
for action <- @test_actions do
|
||||||
get("/#{action}", OAuthTestController, action)
|
get("/#{action}", AuthTestController, action)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,6 +6,7 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|
||||||
use Pleroma.Web, :controller
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
alias Pleroma.Notification
|
alias Pleroma.Notification
|
||||||
|
alias Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug
|
||||||
alias Pleroma.Plugs.OAuthScopesPlug
|
alias Pleroma.Plugs.OAuthScopesPlug
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
alias Pleroma.Web.OAuth.Token
|
alias Pleroma.Web.OAuth.Token
|
||||||
|
@ -18,7 +19,12 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
|
||||||
%{scopes: ["write:notifications"]} when action == :mark_notifications_as_read
|
%{scopes: ["write:notifications"]} when action == :mark_notifications_as_read
|
||||||
)
|
)
|
||||||
|
|
||||||
plug(:skip_plug, OAuthScopesPlug when action in [:confirm_email, :oauth_tokens, :revoke_token])
|
plug(
|
||||||
|
:skip_plug,
|
||||||
|
[OAuthScopesPlug, EnsurePublicOrAuthenticatedPlug] when action == :confirm_email
|
||||||
|
)
|
||||||
|
|
||||||
|
plug(:skip_plug, OAuthScopesPlug when action in [:oauth_tokens, :revoke_token])
|
||||||
|
|
||||||
action_fallback(:errors)
|
action_fallback(:errors)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,242 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Tests.AuthTestControllerTest do
|
||||||
|
use Pleroma.Web.ConnCase
|
||||||
|
|
||||||
|
import Pleroma.Factory
|
||||||
|
|
||||||
|
describe "do_oauth_check" do
|
||||||
|
test "serves with proper OAuth token (fulfilling requested scopes)" do
|
||||||
|
%{conn: good_token_conn, user: user} = oauth_access(["read"])
|
||||||
|
|
||||||
|
assert %{"user_id" => user.id} ==
|
||||||
|
good_token_conn
|
||||||
|
|> get("/test/authenticated_api/do_oauth_check")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
# Unintended usage (:api) — use with :authenticated_api instead
|
||||||
|
assert %{"user_id" => user.id} ==
|
||||||
|
good_token_conn
|
||||||
|
|> get("/test/api/do_oauth_check")
|
||||||
|
|> json_response(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails on no token / missing scope(s)" do
|
||||||
|
%{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
|
||||||
|
|
||||||
|
bad_token_conn
|
||||||
|
|> get("/test/authenticated_api/do_oauth_check")
|
||||||
|
|> json_response(403)
|
||||||
|
|
||||||
|
bad_token_conn
|
||||||
|
|> assign(:token, nil)
|
||||||
|
|> get("/test/api/do_oauth_check")
|
||||||
|
|> json_response(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "fallback_oauth_check" do
|
||||||
|
test "serves with proper OAuth token (fulfilling requested scopes)" do
|
||||||
|
%{conn: good_token_conn, user: user} = oauth_access(["read"])
|
||||||
|
|
||||||
|
assert %{"user_id" => user.id} ==
|
||||||
|
good_token_conn
|
||||||
|
|> get("/test/api/fallback_oauth_check")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
# Unintended usage (:authenticated_api) — use with :api instead
|
||||||
|
assert %{"user_id" => user.id} ==
|
||||||
|
good_token_conn
|
||||||
|
|> get("/test/authenticated_api/fallback_oauth_check")
|
||||||
|
|> json_response(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "for :api on public instance, drops :user and renders on no token / missing scope(s)" do
|
||||||
|
clear_config([:instance, :public], true)
|
||||||
|
|
||||||
|
%{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
|
||||||
|
|
||||||
|
assert %{"user_id" => nil} ==
|
||||||
|
bad_token_conn
|
||||||
|
|> get("/test/api/fallback_oauth_check")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
assert %{"user_id" => nil} ==
|
||||||
|
bad_token_conn
|
||||||
|
|> assign(:token, nil)
|
||||||
|
|> get("/test/api/fallback_oauth_check")
|
||||||
|
|> json_response(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "for :api on private instance, fails on no token / missing scope(s)" do
|
||||||
|
clear_config([:instance, :public], false)
|
||||||
|
|
||||||
|
%{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
|
||||||
|
|
||||||
|
bad_token_conn
|
||||||
|
|> get("/test/api/fallback_oauth_check")
|
||||||
|
|> json_response(403)
|
||||||
|
|
||||||
|
bad_token_conn
|
||||||
|
|> assign(:token, nil)
|
||||||
|
|> get("/test/api/fallback_oauth_check")
|
||||||
|
|> json_response(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "skip_oauth_check" do
|
||||||
|
test "for :authenticated_api, serves if :user is set (regardless of token / token scopes)" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
assert %{"user_id" => user.id} ==
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/test/authenticated_api/skip_oauth_check")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
%{conn: bad_token_conn, user: user} = oauth_access(["irrelevant_scope"])
|
||||||
|
|
||||||
|
assert %{"user_id" => user.id} ==
|
||||||
|
bad_token_conn
|
||||||
|
|> get("/test/authenticated_api/skip_oauth_check")
|
||||||
|
|> json_response(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "serves via :api on public instance if :user is not set" do
|
||||||
|
clear_config([:instance, :public], true)
|
||||||
|
|
||||||
|
assert %{"user_id" => nil} ==
|
||||||
|
build_conn()
|
||||||
|
|> get("/test/api/skip_oauth_check")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
build_conn()
|
||||||
|
|> get("/test/authenticated_api/skip_oauth_check")
|
||||||
|
|> json_response(403)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails on private instance if :user is not set" do
|
||||||
|
clear_config([:instance, :public], false)
|
||||||
|
|
||||||
|
build_conn()
|
||||||
|
|> get("/test/api/skip_oauth_check")
|
||||||
|
|> json_response(403)
|
||||||
|
|
||||||
|
build_conn()
|
||||||
|
|> get("/test/authenticated_api/skip_oauth_check")
|
||||||
|
|> json_response(403)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "fallback_oauth_skip_publicity_check" do
|
||||||
|
test "serves with proper OAuth token (fulfilling requested scopes)" do
|
||||||
|
%{conn: good_token_conn, user: user} = oauth_access(["read"])
|
||||||
|
|
||||||
|
assert %{"user_id" => user.id} ==
|
||||||
|
good_token_conn
|
||||||
|
|> get("/test/api/fallback_oauth_skip_publicity_check")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
# Unintended usage (:authenticated_api)
|
||||||
|
assert %{"user_id" => user.id} ==
|
||||||
|
good_token_conn
|
||||||
|
|> get("/test/authenticated_api/fallback_oauth_skip_publicity_check")
|
||||||
|
|> json_response(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "for :api on private / public instance, drops :user and renders on token issue" do
|
||||||
|
%{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
|
||||||
|
|
||||||
|
for is_public <- [true, false] do
|
||||||
|
clear_config([:instance, :public], is_public)
|
||||||
|
|
||||||
|
assert %{"user_id" => nil} ==
|
||||||
|
bad_token_conn
|
||||||
|
|> get("/test/api/fallback_oauth_skip_publicity_check")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
assert %{"user_id" => nil} ==
|
||||||
|
bad_token_conn
|
||||||
|
|> assign(:token, nil)
|
||||||
|
|> get("/test/api/fallback_oauth_skip_publicity_check")
|
||||||
|
|> json_response(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "skip_oauth_skip_publicity_check" do
|
||||||
|
test "for :authenticated_api, serves if :user is set (regardless of token / token scopes)" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
assert %{"user_id" => user.id} ==
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/test/authenticated_api/skip_oauth_skip_publicity_check")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
%{conn: bad_token_conn, user: user} = oauth_access(["irrelevant_scope"])
|
||||||
|
|
||||||
|
assert %{"user_id" => user.id} ==
|
||||||
|
bad_token_conn
|
||||||
|
|> get("/test/authenticated_api/skip_oauth_skip_publicity_check")
|
||||||
|
|> json_response(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "for :api, serves on private and public instances regardless of whether :user is set" do
|
||||||
|
user = insert(:user)
|
||||||
|
|
||||||
|
for is_public <- [true, false] do
|
||||||
|
clear_config([:instance, :public], is_public)
|
||||||
|
|
||||||
|
assert %{"user_id" => nil} ==
|
||||||
|
build_conn()
|
||||||
|
|> get("/test/api/skip_oauth_skip_publicity_check")
|
||||||
|
|> json_response(200)
|
||||||
|
|
||||||
|
assert %{"user_id" => user.id} ==
|
||||||
|
build_conn()
|
||||||
|
|> assign(:user, user)
|
||||||
|
|> get("/test/api/skip_oauth_skip_publicity_check")
|
||||||
|
|> json_response(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "missing_oauth_check_definition" do
|
||||||
|
def test_missing_oauth_check_definition_failure(endpoint, expected_error) do
|
||||||
|
%{conn: conn} = oauth_access(["read", "write", "follow", "push", "admin"])
|
||||||
|
|
||||||
|
assert %{"error" => expected_error} ==
|
||||||
|
conn
|
||||||
|
|> get(endpoint)
|
||||||
|
|> json_response(403)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails if served via :authenticated_api" do
|
||||||
|
test_missing_oauth_check_definition_failure(
|
||||||
|
"/test/authenticated_api/missing_oauth_check_definition",
|
||||||
|
"Security violation: OAuth scopes check was neither handled nor explicitly skipped."
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "fails if served via :api and the instance is private" do
|
||||||
|
clear_config([:instance, :public], false)
|
||||||
|
|
||||||
|
test_missing_oauth_check_definition_failure(
|
||||||
|
"/test/api/missing_oauth_check_definition",
|
||||||
|
"This resource requires authentication."
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "succeeds with dropped :user if served via :api on public instance" do
|
||||||
|
%{conn: conn} = oauth_access(["read", "write", "follow", "push", "admin"])
|
||||||
|
|
||||||
|
assert %{"user_id" => nil} ==
|
||||||
|
conn
|
||||||
|
|> get("/test/api/missing_oauth_check_definition")
|
||||||
|
|> json_response(200)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,49 +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.Tests.OAuthTestControllerTest do
|
|
||||||
use Pleroma.Web.ConnCase
|
|
||||||
|
|
||||||
import Pleroma.Factory
|
|
||||||
|
|
||||||
setup %{conn: conn} do
|
|
||||||
user = insert(:user)
|
|
||||||
conn = assign(conn, :user, user)
|
|
||||||
%{conn: conn, user: user}
|
|
||||||
end
|
|
||||||
|
|
||||||
test "missed_oauth", %{conn: conn} do
|
|
||||||
res =
|
|
||||||
conn
|
|
||||||
|> get("/test/authenticated_api/missed_oauth")
|
|
||||||
|> json_response(403)
|
|
||||||
|
|
||||||
assert res ==
|
|
||||||
%{
|
|
||||||
"error" =>
|
|
||||||
"Security violation: OAuth scopes check was neither handled nor explicitly skipped."
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
test "skipped_oauth", %{conn: conn} do
|
|
||||||
conn
|
|
||||||
|> assign(:token, nil)
|
|
||||||
|> get("/test/authenticated_api/skipped_oauth")
|
|
||||||
|> json_response(200)
|
|
||||||
end
|
|
||||||
|
|
||||||
test "performed_oauth", %{user: user} do
|
|
||||||
%{conn: good_token_conn} = oauth_access(["read"], user: user)
|
|
||||||
|
|
||||||
good_token_conn
|
|
||||||
|> get("/test/authenticated_api/performed_oauth")
|
|
||||||
|> json_response(200)
|
|
||||||
|
|
||||||
%{conn: bad_token_conn} = oauth_access(["follow"], user: user)
|
|
||||||
|
|
||||||
bad_token_conn
|
|
||||||
|> get("/test/authenticated_api/performed_oauth")
|
|
||||||
|> json_response(403)
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -7,35 +7,28 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
|
||||||
|
|
||||||
describe "empty_array/2 (stubs)" do
|
describe "empty_array/2 (stubs)" do
|
||||||
test "GET /api/v1/accounts/:id/identity_proofs" do
|
test "GET /api/v1/accounts/:id/identity_proofs" do
|
||||||
%{user: user, conn: conn} = oauth_access(["n/a"])
|
%{user: user, conn: conn} = oauth_access(["read:accounts"])
|
||||||
|
|
||||||
res =
|
assert [] ==
|
||||||
conn
|
conn
|
||||||
|> assign(:user, user)
|
|
||||||
|> get("/api/v1/accounts/#{user.id}/identity_proofs")
|
|> get("/api/v1/accounts/#{user.id}/identity_proofs")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert res == []
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "GET /api/v1/endorsements" do
|
test "GET /api/v1/endorsements" do
|
||||||
%{conn: conn} = oauth_access(["read:accounts"])
|
%{conn: conn} = oauth_access(["read:accounts"])
|
||||||
|
|
||||||
res =
|
assert [] ==
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/endorsements")
|
|> get("/api/v1/endorsements")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert res == []
|
|
||||||
end
|
end
|
||||||
|
|
||||||
test "GET /api/v1/trends", %{conn: conn} do
|
test "GET /api/v1/trends", %{conn: conn} do
|
||||||
res =
|
assert [] ==
|
||||||
conn
|
conn
|
||||||
|> get("/api/v1/trends")
|
|> get("/api/v1/trends")
|
||||||
|> json_response(200)
|
|> json_response(200)
|
||||||
|
|
||||||
assert res == []
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue