diff options
Diffstat (limited to 'test/web/oauth')
| -rw-r--r-- | test/web/oauth/app_test.exs | 2 | ||||
| -rw-r--r-- | test/web/oauth/authorization_test.exs | 2 | ||||
| -rw-r--r-- | test/web/oauth/ldap_authorization_test.exs | 16 | ||||
| -rw-r--r-- | test/web/oauth/mfa_controller_test.exs | 306 | ||||
| -rw-r--r-- | test/web/oauth/oauth_controller_test.exs | 239 | ||||
| -rw-r--r-- | test/web/oauth/token/utils_test.exs | 2 | ||||
| -rw-r--r-- | test/web/oauth/token_test.exs | 2 | 
7 files changed, 505 insertions, 64 deletions
diff --git a/test/web/oauth/app_test.exs b/test/web/oauth/app_test.exs index 195b8c17f..899af648e 100644 --- a/test/web/oauth/app_test.exs +++ b/test/web/oauth/app_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.OAuth.AppTest do diff --git a/test/web/oauth/authorization_test.exs b/test/web/oauth/authorization_test.exs index 2e82a7b79..d74b26cf8 100644 --- a/test/web/oauth/authorization_test.exs +++ b/test/web/oauth/authorization_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.OAuth.AuthorizationTest do diff --git a/test/web/oauth/ldap_authorization_test.exs b/test/web/oauth/ldap_authorization_test.exs index 1cbe133b7..011642c08 100644 --- a/test/web/oauth/ldap_authorization_test.exs +++ b/test/web/oauth/ldap_authorization_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do @@ -12,18 +12,14 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do    @skip if !Code.ensure_loaded?(:eldap), do: :skip -  clear_config_all([:ldap, :enabled]) do -    Pleroma.Config.put([:ldap, :enabled], true) -  end +  setup_all do: clear_config([:ldap, :enabled], true) -  clear_config_all(Pleroma.Web.Auth.Authenticator) do -    Pleroma.Config.put(Pleroma.Web.Auth.Authenticator, Pleroma.Web.Auth.LDAPAuthenticator) -  end +  setup_all do: clear_config(Pleroma.Web.Auth.Authenticator, Pleroma.Web.Auth.LDAPAuthenticator)    @tag @skip    test "authorizes the existing user using LDAP credentials" do      password = "testpassword" -    user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password)) +    user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password))      app = insert(:oauth_app, scopes: ["read", "write"])      host = Pleroma.Config.get([:ldap, :host]) |> to_charlist @@ -108,7 +104,7 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do    @tag @skip    test "falls back to the default authorization when LDAP is unavailable" do      password = "testpassword" -    user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password)) +    user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password))      app = insert(:oauth_app, scopes: ["read", "write"])      host = Pleroma.Config.get([:ldap, :host]) |> to_charlist @@ -152,7 +148,7 @@ defmodule Pleroma.Web.OAuth.LDAPAuthorizationTest do    @tag @skip    test "disallow authorization for wrong LDAP credentials" do      password = "testpassword" -    user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password)) +    user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password))      app = insert(:oauth_app, scopes: ["read", "write"])      host = Pleroma.Config.get([:ldap, :host]) |> to_charlist diff --git a/test/web/oauth/mfa_controller_test.exs b/test/web/oauth/mfa_controller_test.exs new file mode 100644 index 000000000..3c341facd --- /dev/null +++ b/test/web/oauth/mfa_controller_test.exs @@ -0,0 +1,306 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2018 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.OAuth.MFAControllerTest do +  use Pleroma.Web.ConnCase +  import Pleroma.Factory + +  alias Pleroma.MFA +  alias Pleroma.MFA.BackupCodes +  alias Pleroma.MFA.TOTP +  alias Pleroma.Repo +  alias Pleroma.Web.OAuth.Authorization +  alias Pleroma.Web.OAuth.OAuthController + +  setup %{conn: conn} do +    otp_secret = TOTP.generate_secret() + +    user = +      insert(:user, +        multi_factor_authentication_settings: %MFA.Settings{ +          enabled: true, +          backup_codes: [Pbkdf2.hash_pwd_salt("test-code")], +          totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true} +        } +      ) + +    app = insert(:oauth_app) +    {:ok, conn: conn, user: user, app: app} +  end + +  describe "show" do +    setup %{conn: conn, user: user, app: app} do +      mfa_token = +        insert(:mfa_token, +          user: user, +          authorization: build(:oauth_authorization, app: app, scopes: ["write"]) +        ) + +      {:ok, conn: conn, mfa_token: mfa_token} +    end + +    test "GET /oauth/mfa renders mfa forms", %{conn: conn, mfa_token: mfa_token} do +      conn = +        get( +          conn, +          "/oauth/mfa", +          %{ +            "mfa_token" => mfa_token.token, +            "state" => "a_state", +            "redirect_uri" => "http://localhost:8080/callback" +          } +        ) + +      assert response = html_response(conn, 200) +      assert response =~ "Two-factor authentication" +      assert response =~ mfa_token.token +      assert response =~ "http://localhost:8080/callback" +    end + +    test "GET /oauth/mfa renders mfa recovery forms", %{conn: conn, mfa_token: mfa_token} do +      conn = +        get( +          conn, +          "/oauth/mfa", +          %{ +            "mfa_token" => mfa_token.token, +            "state" => "a_state", +            "redirect_uri" => "http://localhost:8080/callback", +            "challenge_type" => "recovery" +          } +        ) + +      assert response = html_response(conn, 200) +      assert response =~ "Two-factor recovery" +      assert response =~ mfa_token.token +      assert response =~ "http://localhost:8080/callback" +    end +  end + +  describe "verify" do +    setup %{conn: conn, user: user, app: app} do +      mfa_token = +        insert(:mfa_token, +          user: user, +          authorization: build(:oauth_authorization, app: app, scopes: ["write"]) +        ) + +      {:ok, conn: conn, user: user, mfa_token: mfa_token, app: app} +    end + +    test "POST /oauth/mfa/verify, verify totp code", %{ +      conn: conn, +      user: user, +      mfa_token: mfa_token, +      app: app +    } do +      otp_token = TOTP.generate_token(user.multi_factor_authentication_settings.totp.secret) + +      conn = +        conn +        |> post("/oauth/mfa/verify", %{ +          "mfa" => %{ +            "mfa_token" => mfa_token.token, +            "challenge_type" => "totp", +            "code" => otp_token, +            "state" => "a_state", +            "redirect_uri" => OAuthController.default_redirect_uri(app) +          } +        }) + +      target = redirected_to(conn) +      target_url = %URI{URI.parse(target) | query: nil} |> URI.to_string() +      query = URI.parse(target).query |> URI.query_decoder() |> Map.new() +      assert %{"state" => "a_state", "code" => code} = query +      assert target_url == OAuthController.default_redirect_uri(app) +      auth = Repo.get_by(Authorization, token: code) +      assert auth.scopes == ["write"] +    end + +    test "POST /oauth/mfa/verify, verify recovery code", %{ +      conn: conn, +      mfa_token: mfa_token, +      app: app +    } do +      conn = +        conn +        |> post("/oauth/mfa/verify", %{ +          "mfa" => %{ +            "mfa_token" => mfa_token.token, +            "challenge_type" => "recovery", +            "code" => "test-code", +            "state" => "a_state", +            "redirect_uri" => OAuthController.default_redirect_uri(app) +          } +        }) + +      target = redirected_to(conn) +      target_url = %URI{URI.parse(target) | query: nil} |> URI.to_string() +      query = URI.parse(target).query |> URI.query_decoder() |> Map.new() +      assert %{"state" => "a_state", "code" => code} = query +      assert target_url == OAuthController.default_redirect_uri(app) +      auth = Repo.get_by(Authorization, token: code) +      assert auth.scopes == ["write"] +    end +  end + +  describe "challenge/totp" do +    test "returns access token with valid code", %{conn: conn, user: user, app: app} do +      otp_token = TOTP.generate_token(user.multi_factor_authentication_settings.totp.secret) + +      mfa_token = +        insert(:mfa_token, +          user: user, +          authorization: build(:oauth_authorization, app: app, scopes: ["write"]) +        ) + +      response = +        conn +        |> post("/oauth/mfa/challenge", %{ +          "mfa_token" => mfa_token.token, +          "challenge_type" => "totp", +          "code" => otp_token, +          "client_id" => app.client_id, +          "client_secret" => app.client_secret +        }) +        |> json_response(:ok) + +      ap_id = user.ap_id + +      assert match?( +               %{ +                 "access_token" => _, +                 "expires_in" => 600, +                 "me" => ^ap_id, +                 "refresh_token" => _, +                 "scope" => "write", +                 "token_type" => "Bearer" +               }, +               response +             ) +    end + +    test "returns errors when mfa token invalid", %{conn: conn, user: user, app: app} do +      otp_token = TOTP.generate_token(user.multi_factor_authentication_settings.totp.secret) + +      response = +        conn +        |> post("/oauth/mfa/challenge", %{ +          "mfa_token" => "XXX", +          "challenge_type" => "totp", +          "code" => otp_token, +          "client_id" => app.client_id, +          "client_secret" => app.client_secret +        }) +        |> json_response(400) + +      assert response == %{"error" => "Invalid code"} +    end + +    test "returns error when otp code is invalid", %{conn: conn, user: user, app: app} do +      mfa_token = insert(:mfa_token, user: user) + +      response = +        conn +        |> post("/oauth/mfa/challenge", %{ +          "mfa_token" => mfa_token.token, +          "challenge_type" => "totp", +          "code" => "XXX", +          "client_id" => app.client_id, +          "client_secret" => app.client_secret +        }) +        |> json_response(400) + +      assert response == %{"error" => "Invalid code"} +    end + +    test "returns error when client credentails is wrong ", %{conn: conn, user: user} do +      otp_token = TOTP.generate_token(user.multi_factor_authentication_settings.totp.secret) +      mfa_token = insert(:mfa_token, user: user) + +      response = +        conn +        |> post("/oauth/mfa/challenge", %{ +          "mfa_token" => mfa_token.token, +          "challenge_type" => "totp", +          "code" => otp_token, +          "client_id" => "xxx", +          "client_secret" => "xxx" +        }) +        |> json_response(400) + +      assert response == %{"error" => "Invalid code"} +    end +  end + +  describe "challenge/recovery" do +    setup %{conn: conn} do +      app = insert(:oauth_app) +      {:ok, conn: conn, app: app} +    end + +    test "returns access token with valid code", %{conn: conn, app: app} do +      otp_secret = TOTP.generate_secret() + +      [code | _] = backup_codes = BackupCodes.generate() + +      hashed_codes = +        backup_codes +        |> Enum.map(&Pbkdf2.hash_pwd_salt(&1)) + +      user = +        insert(:user, +          multi_factor_authentication_settings: %MFA.Settings{ +            enabled: true, +            backup_codes: hashed_codes, +            totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true} +          } +        ) + +      mfa_token = +        insert(:mfa_token, +          user: user, +          authorization: build(:oauth_authorization, app: app, scopes: ["write"]) +        ) + +      response = +        conn +        |> post("/oauth/mfa/challenge", %{ +          "mfa_token" => mfa_token.token, +          "challenge_type" => "recovery", +          "code" => code, +          "client_id" => app.client_id, +          "client_secret" => app.client_secret +        }) +        |> json_response(:ok) + +      ap_id = user.ap_id + +      assert match?( +               %{ +                 "access_token" => _, +                 "expires_in" => 600, +                 "me" => ^ap_id, +                 "refresh_token" => _, +                 "scope" => "write", +                 "token_type" => "Bearer" +               }, +               response +             ) + +      error_response = +        conn +        |> post("/oauth/mfa/challenge", %{ +          "mfa_token" => mfa_token.token, +          "challenge_type" => "recovery", +          "code" => code, +          "client_id" => app.client_id, +          "client_secret" => app.client_secret +        }) +        |> json_response(400) + +      assert error_response == %{"error" => "Invalid code"} +    end +  end +end diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs index 41aaf6189..d389e4ce0 100644 --- a/test/web/oauth/oauth_controller_test.exs +++ b/test/web/oauth/oauth_controller_test.exs @@ -1,11 +1,13 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.OAuth.OAuthControllerTest do    use Pleroma.Web.ConnCase    import Pleroma.Factory +  alias Pleroma.MFA +  alias Pleroma.MFA.TOTP    alias Pleroma.Repo    alias Pleroma.User    alias Pleroma.Web.OAuth.Authorization @@ -17,7 +19,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do      key: "_test",      signing_salt: "cooldude"    ] -  clear_config_all([:instance, :account_activation_required]) +  setup do: clear_config([:instance, :account_activation_required])    describe "in OAuth consumer mode, " do      setup do @@ -30,12 +32,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do        ]      end -    clear_config([:auth, :oauth_consumer_strategies]) do -      Pleroma.Config.put( -        [:auth, :oauth_consumer_strategies], -        ~w(twitter facebook) -      ) -    end +    setup do: clear_config([:auth, :oauth_consumer_strategies], ~w(twitter facebook))      test "GET /oauth/authorize renders auth forms, including OAuth consumer form", %{        app: app, @@ -314,7 +311,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do             app: app,             conn: conn           } do -      user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt("testpassword")) +      user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt("testpassword"))        registration = insert(:registration, user: nil)        redirect_uri = OAuthController.default_redirect_uri(app) @@ -345,7 +342,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do             app: app,             conn: conn           } do -      user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt("testpassword")) +      user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt("testpassword"))        registration = insert(:registration, user: nil)        unlisted_redirect_uri = "http://cross-site-request.com" @@ -450,7 +447,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do      test "renders authentication page if user is already authenticated but `force_login` is tru-ish",           %{app: app, conn: conn} do -      token = insert(:oauth_token, app_id: app.id) +      token = insert(:oauth_token, app: app)        conn =          conn @@ -469,12 +466,35 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do        assert html_response(conn, 200) =~ ~s(type="submit")      end +    test "renders authentication page if user is already authenticated but user request with another client", +         %{ +           app: app, +           conn: conn +         } do +      token = insert(:oauth_token, app: app) + +      conn = +        conn +        |> put_session(:oauth_token, token.token) +        |> get( +          "/oauth/authorize", +          %{ +            "response_type" => "code", +            "client_id" => "another_client_id", +            "redirect_uri" => OAuthController.default_redirect_uri(app), +            "scope" => "read" +          } +        ) + +      assert html_response(conn, 200) =~ ~s(type="submit") +    end +      test "with existing authentication and non-OOB `redirect_uri`, redirects to app with `token` and `state` params",           %{             app: app,             conn: conn           } do -      token = insert(:oauth_token, app_id: app.id) +      token = insert(:oauth_token, app: app)        conn =          conn @@ -500,7 +520,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do             conn: conn           } do        unlisted_redirect_uri = "http://cross-site-request.com" -      token = insert(:oauth_token, app_id: app.id) +      token = insert(:oauth_token, app: app)        conn =          conn @@ -524,7 +544,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do             app: app,             conn: conn           } do -      token = insert(:oauth_token, app_id: app.id) +      token = insert(:oauth_token, app: app)        conn =          conn @@ -544,11 +564,61 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do    end    describe "POST /oauth/authorize" do -    test "redirects with oauth authorization" do -      user = insert(:user) -      app = insert(:oauth_app, scopes: ["read", "write", "follow"]) +    test "redirects with oauth authorization, " <> +           "granting requested app-supported scopes to both admin- and non-admin users" do +      app_scopes = ["read", "write", "admin", "secret_scope"] +      app = insert(:oauth_app, scopes: app_scopes)        redirect_uri = OAuthController.default_redirect_uri(app) +      non_admin = insert(:user, is_admin: false) +      admin = insert(:user, is_admin: true) +      scopes_subset = ["read:subscope", "write", "admin"] + +      # In case scope param is missing, expecting _all_ app-supported scopes to be granted +      for user <- [non_admin, admin], +          {requested_scopes, expected_scopes} <- +            %{scopes_subset => scopes_subset, nil: app_scopes} do +        conn = +          post( +            build_conn(), +            "/oauth/authorize", +            %{ +              "authorization" => %{ +                "name" => user.nickname, +                "password" => "test", +                "client_id" => app.client_id, +                "redirect_uri" => redirect_uri, +                "scope" => requested_scopes, +                "state" => "statepassed" +              } +            } +          ) + +        target = redirected_to(conn) +        assert target =~ redirect_uri + +        query = URI.parse(target).query |> URI.query_decoder() |> Map.new() + +        assert %{"state" => "statepassed", "code" => code} = query +        auth = Repo.get_by(Authorization, token: code) +        assert auth +        assert auth.scopes == expected_scopes +      end +    end + +    test "redirect to on two-factor auth page" do +      otp_secret = TOTP.generate_secret() + +      user = +        insert(:user, +          multi_factor_authentication_settings: %MFA.Settings{ +            enabled: true, +            totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true} +          } +        ) + +      app = insert(:oauth_app, scopes: ["read", "write", "follow"]) +        conn =          build_conn()          |> post("/oauth/authorize", %{ @@ -556,21 +626,19 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do              "name" => user.nickname,              "password" => "test",              "client_id" => app.client_id, -            "redirect_uri" => redirect_uri, -            "scope" => "read:subscope write", +            "redirect_uri" => app.redirect_uris, +            "scope" => "read write",              "state" => "statepassed"            }          }) -      target = redirected_to(conn) -      assert target =~ redirect_uri +      result = html_response(conn, 200) -      query = URI.parse(target).query |> URI.query_decoder() |> Map.new() - -      assert %{"state" => "statepassed", "code" => code} = query -      auth = Repo.get_by(Authorization, token: code) -      assert auth -      assert auth.scopes == ["read:subscope", "write"] +      mfa_token = Repo.get_by(MFA.Token, user_id: user.id) +      assert result =~ app.redirect_uris +      assert result =~ "statepassed" +      assert result =~ mfa_token.token +      assert result =~ "Two-factor authentication"      end      test "returns 401 for wrong credentials", %{conn: conn} do @@ -600,13 +668,13 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do        assert result =~ "Invalid Username/Password"      end -    test "returns 401 for missing scopes", %{conn: conn} do -      user = insert(:user) -      app = insert(:oauth_app) +    test "returns 401 for missing scopes" do +      user = insert(:user, is_admin: false) +      app = insert(:oauth_app, scopes: ["read", "write", "admin"])        redirect_uri = OAuthController.default_redirect_uri(app)        result = -        conn +        build_conn()          |> post("/oauth/authorize", %{            "authorization" => %{              "name" => user.nickname, @@ -682,7 +750,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do      test "issues a token for `password` grant_type with valid credentials, with full permissions by default" do        password = "testpassword" -      user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password)) +      user = insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password))        app = insert(:oauth_app, scopes: ["read", "write"]) @@ -704,6 +772,46 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do        assert token.scopes == app.scopes      end +    test "issues a mfa token for `password` grant_type, when MFA enabled" do +      password = "testpassword" +      otp_secret = TOTP.generate_secret() + +      user = +        insert(:user, +          password_hash: Pbkdf2.hash_pwd_salt(password), +          multi_factor_authentication_settings: %MFA.Settings{ +            enabled: true, +            totp: %MFA.Settings.TOTP{secret: otp_secret, confirmed: true} +          } +        ) + +      app = insert(:oauth_app, scopes: ["read", "write"]) + +      response = +        build_conn() +        |> post("/oauth/token", %{ +          "grant_type" => "password", +          "username" => user.nickname, +          "password" => password, +          "client_id" => app.client_id, +          "client_secret" => app.client_secret +        }) +        |> json_response(403) + +      assert match?( +               %{ +                 "supported_challenge_types" => "totp", +                 "mfa_token" => _, +                 "error" => "mfa_required" +               }, +               response +             ) + +      token = Repo.get_by(MFA.Token, token: response["mfa_token"]) +      assert token.user_id == user.id +      assert token.authorization_id +    end +      test "issues a token for request with HTTP basic auth client credentials" do        user = insert(:user)        app = insert(:oauth_app, scopes: ["scope1", "scope2", "scope3"]) @@ -779,11 +887,11 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do        password = "testpassword"        {:ok, user} = -        insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password)) -        |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true)) -        |> Repo.update() +        insert(:user, password_hash: Pbkdf2.hash_pwd_salt(password)) +        |> User.confirmation_changeset(need_confirmation: true) +        |> User.update_and_set_cache() -      refute Pleroma.User.auth_active?(user) +      refute Pleroma.User.account_status(user) == :active        app = insert(:oauth_app) @@ -807,13 +915,13 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do        user =          insert(:user, -          password_hash: Comeonin.Pbkdf2.hashpwsalt(password), -          info: %{deactivated: true} +          password_hash: Pbkdf2.hash_pwd_salt(password), +          deactivated: true          )        app = insert(:oauth_app) -      conn = +      resp =          build_conn()          |> post("/oauth/token", %{            "grant_type" => "password", @@ -822,10 +930,12 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do            "client_id" => app.client_id,            "client_secret" => app.client_secret          }) +        |> json_response(403) -      assert resp = json_response(conn, 403) -      assert %{"error" => _} = resp -      refute Map.has_key?(resp, "access_token") +      assert resp == %{ +               "error" => "Your account is currently disabled", +               "identifier" => "account_is_disabled" +             }      end      test "rejects token exchange for user with password_reset_pending set to true" do @@ -833,13 +943,13 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do        user =          insert(:user, -          password_hash: Comeonin.Pbkdf2.hashpwsalt(password), -          info: %{password_reset_pending: true} +          password_hash: Pbkdf2.hash_pwd_salt(password), +          password_reset_pending: true          )        app = insert(:oauth_app, scopes: ["read", "write"]) -      conn = +      resp =          build_conn()          |> post("/oauth/token", %{            "grant_type" => "password", @@ -848,12 +958,41 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do            "client_id" => app.client_id,            "client_secret" => app.client_secret          }) +        |> json_response(403) -      assert resp = json_response(conn, 403) +      assert resp == %{ +               "error" => "Password reset is required", +               "identifier" => "password_reset_required" +             } +    end -      assert resp["error"] == "Password reset is required" -      assert resp["identifier"] == "password_reset_required" -      refute Map.has_key?(resp, "access_token") +    test "rejects token exchange for user with confirmation_pending set to true" do +      Pleroma.Config.put([:instance, :account_activation_required], true) +      password = "testpassword" + +      user = +        insert(:user, +          password_hash: Pbkdf2.hash_pwd_salt(password), +          confirmation_pending: true +        ) + +      app = insert(:oauth_app, scopes: ["read", "write"]) + +      resp = +        build_conn() +        |> post("/oauth/token", %{ +          "grant_type" => "password", +          "username" => user.nickname, +          "password" => password, +          "client_id" => app.client_id, +          "client_secret" => app.client_secret +        }) +        |> json_response(403) + +      assert resp == %{ +               "error" => "Your login is missing a confirmed e-mail address", +               "identifier" => "missing_confirmed_email" +             }      end      test "rejects an invalid authorization code" do @@ -876,7 +1015,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do    end    describe "POST /oauth/token - refresh token" do -    clear_config([:oauth2, :issue_new_refresh_token]) +    setup do: clear_config([:oauth2, :issue_new_refresh_token])      test "issues a new access token with keep fresh token" do        Pleroma.Config.put([:oauth2, :issue_new_refresh_token], true) diff --git a/test/web/oauth/token/utils_test.exs b/test/web/oauth/token/utils_test.exs index dc1f9a986..a610d92f8 100644 --- a/test/web/oauth/token/utils_test.exs +++ b/test/web/oauth/token/utils_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.OAuth.Token.UtilsTest do diff --git a/test/web/oauth/token_test.exs b/test/web/oauth/token_test.exs index 5359940f8..40d71eb59 100644 --- a/test/web/oauth/token_test.exs +++ b/test/web/oauth/token_test.exs @@ -1,5 +1,5 @@  # Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/> +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>  # SPDX-License-Identifier: AGPL-3.0-only  defmodule Pleroma.Web.OAuth.TokenTest do  | 
