First
[anni] / test / pleroma / web / auth / auth_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.Auth.AuthControllerTest do
6   use Pleroma.Web.ConnCase
7
8   import Pleroma.Factory
9
10   describe "do_oauth_check" do
11     test "serves with proper OAuth token (fulfilling requested scopes)" do
12       %{conn: good_token_conn, user: user} = oauth_access(["read"])
13
14       assert %{"user_id" => user.id} ==
15                good_token_conn
16                |> get("/test/authenticated_api/do_oauth_check")
17                |> json_response(200)
18
19       # Unintended usage (:api) — use with :authenticated_api instead
20       assert %{"user_id" => user.id} ==
21                good_token_conn
22                |> get("/test/api/do_oauth_check")
23                |> json_response(200)
24     end
25
26     test "fails on no token / missing scope(s)" do
27       %{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
28
29       bad_token_conn
30       |> get("/test/authenticated_api/do_oauth_check")
31       |> json_response(403)
32
33       bad_token_conn
34       |> assign(:token, nil)
35       |> get("/test/api/do_oauth_check")
36       |> json_response(403)
37     end
38   end
39
40   describe "fallback_oauth_check" do
41     test "serves with proper OAuth token (fulfilling requested scopes)" do
42       %{conn: good_token_conn, user: user} = oauth_access(["read"])
43
44       assert %{"user_id" => user.id} ==
45                good_token_conn
46                |> get("/test/api/fallback_oauth_check")
47                |> json_response(200)
48
49       # Unintended usage (:authenticated_api) — use with :api instead
50       assert %{"user_id" => user.id} ==
51                good_token_conn
52                |> get("/test/authenticated_api/fallback_oauth_check")
53                |> json_response(200)
54     end
55
56     test "for :api on public instance, drops :user and renders on no token / missing scope(s)" do
57       clear_config([:instance, :public], true)
58
59       %{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
60
61       assert %{"user_id" => nil} ==
62                bad_token_conn
63                |> get("/test/api/fallback_oauth_check")
64                |> json_response(200)
65
66       assert %{"user_id" => nil} ==
67                bad_token_conn
68                |> assign(:token, nil)
69                |> get("/test/api/fallback_oauth_check")
70                |> json_response(200)
71     end
72
73     test "for :api on private instance, fails on no token / missing scope(s)" do
74       clear_config([:instance, :public], false)
75
76       %{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
77
78       bad_token_conn
79       |> get("/test/api/fallback_oauth_check")
80       |> json_response(403)
81
82       bad_token_conn
83       |> assign(:token, nil)
84       |> get("/test/api/fallback_oauth_check")
85       |> json_response(403)
86     end
87   end
88
89   describe "skip_oauth_check" do
90     test "for :authenticated_api, serves if :user is set (regardless of token / token scopes)" do
91       user = insert(:user)
92
93       assert %{"user_id" => user.id} ==
94                build_conn()
95                |> assign(:user, user)
96                |> get("/test/authenticated_api/skip_oauth_check")
97                |> json_response(200)
98
99       %{conn: bad_token_conn, user: user} = oauth_access(["irrelevant_scope"])
100
101       assert %{"user_id" => user.id} ==
102                bad_token_conn
103                |> get("/test/authenticated_api/skip_oauth_check")
104                |> json_response(200)
105     end
106
107     test "serves via :api on public instance if :user is not set" do
108       clear_config([:instance, :public], true)
109
110       assert %{"user_id" => nil} ==
111                build_conn()
112                |> get("/test/api/skip_oauth_check")
113                |> json_response(200)
114
115       build_conn()
116       |> get("/test/authenticated_api/skip_oauth_check")
117       |> json_response(403)
118     end
119
120     test "fails on private instance if :user is not set" do
121       clear_config([:instance, :public], false)
122
123       build_conn()
124       |> get("/test/api/skip_oauth_check")
125       |> json_response(403)
126
127       build_conn()
128       |> get("/test/authenticated_api/skip_oauth_check")
129       |> json_response(403)
130     end
131   end
132
133   describe "fallback_oauth_skip_publicity_check" do
134     test "serves with proper OAuth token (fulfilling requested scopes)" do
135       %{conn: good_token_conn, user: user} = oauth_access(["read"])
136
137       assert %{"user_id" => user.id} ==
138                good_token_conn
139                |> get("/test/api/fallback_oauth_skip_publicity_check")
140                |> json_response(200)
141
142       # Unintended usage (:authenticated_api)
143       assert %{"user_id" => user.id} ==
144                good_token_conn
145                |> get("/test/authenticated_api/fallback_oauth_skip_publicity_check")
146                |> json_response(200)
147     end
148
149     test "for :api on private / public instance, drops :user and renders on token issue" do
150       %{conn: bad_token_conn} = oauth_access(["irrelevant_scope"])
151
152       for is_public <- [true, false] do
153         clear_config([:instance, :public], is_public)
154
155         assert %{"user_id" => nil} ==
156                  bad_token_conn
157                  |> get("/test/api/fallback_oauth_skip_publicity_check")
158                  |> json_response(200)
159
160         assert %{"user_id" => nil} ==
161                  bad_token_conn
162                  |> assign(:token, nil)
163                  |> get("/test/api/fallback_oauth_skip_publicity_check")
164                  |> json_response(200)
165       end
166     end
167   end
168
169   describe "skip_oauth_skip_publicity_check" do
170     test "for :authenticated_api, serves if :user is set (regardless of token / token scopes)" do
171       user = insert(:user)
172
173       assert %{"user_id" => user.id} ==
174                build_conn()
175                |> assign(:user, user)
176                |> get("/test/authenticated_api/skip_oauth_skip_publicity_check")
177                |> json_response(200)
178
179       %{conn: bad_token_conn, user: user} = oauth_access(["irrelevant_scope"])
180
181       assert %{"user_id" => user.id} ==
182                bad_token_conn
183                |> get("/test/authenticated_api/skip_oauth_skip_publicity_check")
184                |> json_response(200)
185     end
186
187     test "for :api, serves on private and public instances regardless of whether :user is set" do
188       user = insert(:user)
189
190       for is_public <- [true, false] do
191         clear_config([:instance, :public], is_public)
192
193         assert %{"user_id" => nil} ==
194                  build_conn()
195                  |> get("/test/api/skip_oauth_skip_publicity_check")
196                  |> json_response(200)
197
198         assert %{"user_id" => user.id} ==
199                  build_conn()
200                  |> assign(:user, user)
201                  |> get("/test/api/skip_oauth_skip_publicity_check")
202                  |> json_response(200)
203       end
204     end
205   end
206
207   describe "missing_oauth_check_definition" do
208     def test_missing_oauth_check_definition_failure(endpoint, expected_error) do
209       %{conn: conn} = oauth_access(["read", "write", "follow", "push", "admin"])
210
211       assert %{"error" => expected_error} ==
212                conn
213                |> get(endpoint)
214                |> json_response(403)
215     end
216
217     test "fails if served via :authenticated_api" do
218       test_missing_oauth_check_definition_failure(
219         "/test/authenticated_api/missing_oauth_check_definition",
220         "Security violation: OAuth scopes check was neither handled nor explicitly skipped."
221       )
222     end
223
224     test "fails if served via :api and the instance is private" do
225       clear_config([:instance, :public], false)
226
227       test_missing_oauth_check_definition_failure(
228         "/test/api/missing_oauth_check_definition",
229         "This resource requires authentication."
230       )
231     end
232
233     test "succeeds with dropped :user if served via :api on public instance" do
234       %{conn: conn} = oauth_access(["read", "write", "follow", "push", "admin"])
235
236       assert %{"user_id" => nil} ==
237                conn
238                |> get("/test/api/missing_oauth_check_definition")
239                |> json_response(200)
240     end
241   end
242 end