1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.PleromaAPI.TwoFactorAuthenticationControllerTest do
6 use Pleroma.Web.ConnCase
9 alias Pleroma.MFA.Settings
10 alias Pleroma.MFA.TOTP
12 describe "GET /api/pleroma/accounts/mfa/settings" do
13 test "returns user mfa settings for new user", %{conn: conn} do
14 token = insert(:oauth_token, scopes: ["read", "follow"])
15 token2 = insert(:oauth_token, scopes: ["write"])
18 |> put_req_header("authorization", "Bearer #{token.token}")
19 |> get("/api/pleroma/accounts/mfa")
20 |> json_response(:ok) == %{
21 "settings" => %{"enabled" => false, "totp" => false}
25 |> put_req_header("authorization", "Bearer #{token2.token}")
26 |> get("/api/pleroma/accounts/mfa")
27 |> json_response(403) == %{
28 "error" => "Insufficient permissions: read:security."
32 test "returns user mfa settings with enabled totp", %{conn: conn} do
35 multi_factor_authentication_settings: %Settings{
37 totp: %Settings.TOTP{secret: "XXX", delivery_type: "app", confirmed: true}
41 token = insert(:oauth_token, scopes: ["read", "follow"], user: user)
44 |> put_req_header("authorization", "Bearer #{token.token}")
45 |> get("/api/pleroma/accounts/mfa")
46 |> json_response(:ok) == %{
47 "settings" => %{"enabled" => true, "totp" => true}
52 describe "GET /api/pleroma/accounts/mfa/backup_codes" do
53 test "returns backup codes", %{conn: conn} do
56 multi_factor_authentication_settings: %Settings{
57 backup_codes: ["1", "2", "3"],
58 totp: %Settings.TOTP{secret: "secret"}
62 token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
63 token2 = insert(:oauth_token, scopes: ["read"])
67 |> put_req_header("authorization", "Bearer #{token.token}")
68 |> get("/api/pleroma/accounts/mfa/backup_codes")
71 assert [<<_::bytes-size(6)>>, <<_::bytes-size(6)>>] = response["codes"]
72 user = refresh_record(user)
73 mfa_settings = user.multi_factor_authentication_settings
74 assert mfa_settings.totp.secret == "secret"
75 refute mfa_settings.backup_codes == ["1", "2", "3"]
76 refute mfa_settings.backup_codes == []
79 |> put_req_header("authorization", "Bearer #{token2.token}")
80 |> get("/api/pleroma/accounts/mfa/backup_codes")
81 |> json_response(403) == %{
82 "error" => "Insufficient permissions: write:security."
87 describe "GET /api/pleroma/accounts/mfa/setup/totp" do
88 test "return errors when method is invalid", %{conn: conn} do
90 token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
94 |> put_req_header("authorization", "Bearer #{token.token}")
95 |> get("/api/pleroma/accounts/mfa/setup/torf")
98 assert response == %{"error" => "undefined method"}
101 test "returns key and provisioning_uri", %{conn: conn} do
104 multi_factor_authentication_settings: %Settings{backup_codes: ["1", "2", "3"]}
107 token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
108 token2 = insert(:oauth_token, scopes: ["read"])
112 |> put_req_header("authorization", "Bearer #{token.token}")
113 |> get("/api/pleroma/accounts/mfa/setup/totp")
114 |> json_response(:ok)
116 user = refresh_record(user)
117 mfa_settings = user.multi_factor_authentication_settings
118 secret = mfa_settings.totp.secret
119 refute mfa_settings.enabled
120 assert mfa_settings.backup_codes == ["1", "2", "3"]
122 assert response == %{
124 "provisioning_uri" => TOTP.provisioning_uri(secret, "#{user.email}")
128 |> put_req_header("authorization", "Bearer #{token2.token}")
129 |> get("/api/pleroma/accounts/mfa/setup/totp")
130 |> json_response(403) == %{
131 "error" => "Insufficient permissions: write:security."
136 describe "GET /api/pleroma/accounts/mfa/confirm/totp" do
137 test "returns success result", %{conn: conn} do
138 secret = TOTP.generate_secret()
139 code = TOTP.generate_token(secret)
143 multi_factor_authentication_settings: %Settings{
144 backup_codes: ["1", "2", "3"],
145 totp: %Settings.TOTP{secret: secret}
149 token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
150 token2 = insert(:oauth_token, scopes: ["read"])
153 |> put_req_header("authorization", "Bearer #{token.token}")
154 |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: code})
155 |> json_response(:ok)
157 settings = refresh_record(user).multi_factor_authentication_settings
158 assert settings.enabled
159 assert settings.totp.secret == secret
160 assert settings.totp.confirmed
161 assert settings.backup_codes == ["1", "2", "3"]
164 |> put_req_header("authorization", "Bearer #{token2.token}")
165 |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: code})
166 |> json_response(403) == %{
167 "error" => "Insufficient permissions: write:security."
171 test "returns error if password incorrect", %{conn: conn} do
172 secret = TOTP.generate_secret()
173 code = TOTP.generate_token(secret)
177 multi_factor_authentication_settings: %Settings{
178 backup_codes: ["1", "2", "3"],
179 totp: %Settings.TOTP{secret: secret}
183 token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
187 |> put_req_header("authorization", "Bearer #{token.token}")
188 |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "xxx", code: code})
189 |> json_response(422)
191 settings = refresh_record(user).multi_factor_authentication_settings
192 refute settings.enabled
193 refute settings.totp.confirmed
194 assert settings.backup_codes == ["1", "2", "3"]
195 assert response == %{"error" => "Invalid password."}
198 test "returns error if code incorrect", %{conn: conn} do
199 secret = TOTP.generate_secret()
203 multi_factor_authentication_settings: %Settings{
204 backup_codes: ["1", "2", "3"],
205 totp: %Settings.TOTP{secret: secret}
209 token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
210 token2 = insert(:oauth_token, scopes: ["read"])
214 |> put_req_header("authorization", "Bearer #{token.token}")
215 |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: "code"})
216 |> json_response(422)
218 settings = refresh_record(user).multi_factor_authentication_settings
219 refute settings.enabled
220 refute settings.totp.confirmed
221 assert settings.backup_codes == ["1", "2", "3"]
222 assert response == %{"error" => "invalid_token"}
225 |> put_req_header("authorization", "Bearer #{token2.token}")
226 |> post("/api/pleroma/accounts/mfa/confirm/totp", %{password: "test", code: "code"})
227 |> json_response(403) == %{
228 "error" => "Insufficient permissions: write:security."
233 describe "DELETE /api/pleroma/accounts/mfa/totp" do
234 test "returns success result", %{conn: conn} do
237 multi_factor_authentication_settings: %Settings{
238 backup_codes: ["1", "2", "3"],
239 totp: %Settings.TOTP{secret: "secret"}
243 token = insert(:oauth_token, scopes: ["write", "follow"], user: user)
244 token2 = insert(:oauth_token, scopes: ["read"])
247 |> put_req_header("authorization", "Bearer #{token.token}")
248 |> delete("/api/pleroma/accounts/mfa/totp", %{password: "test"})
249 |> json_response(:ok)
251 settings = refresh_record(user).multi_factor_authentication_settings
252 refute settings.enabled
253 assert settings.totp.secret == nil
254 refute settings.totp.confirmed
257 |> put_req_header("authorization", "Bearer #{token2.token}")
258 |> delete("/api/pleroma/accounts/mfa/totp", %{password: "test"})
259 |> json_response(403) == %{
260 "error" => "Insufficient permissions: write:security."