Fix oauth2 (for real) (#179)
[akkoma] / test / pleroma / web / o_auth / o_auth_controller_test.exs
index 9c7c57d48b84fbfe8677e3496c3f57b52c783acf..9f984b26fad02a21af581c362443bea9e0a84ea5 100644 (file)
@@ -7,7 +7,6 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
 
   import Pleroma.Factory
 
 
   import Pleroma.Factory
 
-  alias Pleroma.Helpers.AuthHelper
   alias Pleroma.MFA
   alias Pleroma.MFA.TOTP
   alias Pleroma.Repo
   alias Pleroma.MFA
   alias Pleroma.MFA.TOTP
   alias Pleroma.Repo
@@ -456,7 +455,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
 
       conn =
         conn
 
       conn =
         conn
-        |> AuthHelper.put_session_token(token.token)
+        |> put_req_header("authorization", "Bearer #{token.token}")
         |> get(
           "/oauth/authorize",
           %{
         |> get(
           "/oauth/authorize",
           %{
@@ -471,22 +470,57 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
       assert html_response(conn, 200) =~ ~s(type="submit")
     end
 
       assert html_response(conn, 200) =~ ~s(type="submit")
     end
 
-    test "renders authentication page if user is already authenticated but user request with another client",
+    test "reuses authentication if the user is authenticated with another client",
          %{
          %{
-           app: app,
            conn: conn
          } do
            conn: conn
          } do
-      token = insert(:oauth_token, app: app)
+      user = insert(:user)
+
+      app = insert(:oauth_app, redirect_uris: "https://redirect.url")
+      other_app = insert(:oauth_app, redirect_uris: "https://redirect.url")
+
+      token = insert(:oauth_token, user: user, app: app)
+      reusable_token = insert(:oauth_token, app: other_app, user: user)
 
       conn =
         conn
 
       conn =
         conn
-        |> AuthHelper.put_session_token(token.token)
+        |> put_req_header("authorization", "Bearer #{token.token}")
         |> get(
           "/oauth/authorize",
           %{
             "response_type" => "code",
         |> get(
           "/oauth/authorize",
           %{
             "response_type" => "code",
-            "client_id" => "another_client_id",
-            "redirect_uri" => OAuthController.default_redirect_uri(app),
+            "client_id" => other_app.client_id,
+            "redirect_uri" => OAuthController.default_redirect_uri(other_app),
+            "scope" => "read"
+          }
+        )
+
+      assert URI.decode(redirected_to(conn)) ==
+               "https://redirect.url?access_token=#{reusable_token.token}"
+    end
+
+    test "does not reuse other people's tokens",
+         %{
+           conn: conn
+         } do
+      user = insert(:user)
+      other_user = insert(:user)
+
+      app = insert(:oauth_app, redirect_uris: "https://redirect.url")
+      other_app = insert(:oauth_app, redirect_uris: "https://redirect.url")
+
+      token = insert(:oauth_token, user: user, app: app)
+      _not_reusable_token = insert(:oauth_token, app: other_app, user: other_user)
+
+      conn =
+        conn
+        |> put_req_header("authorization", "Bearer #{token.token}")
+        |> get(
+          "/oauth/authorize",
+          %{
+            "response_type" => "code",
+            "client_id" => other_app.client_id,
+            "redirect_uri" => OAuthController.default_redirect_uri(other_app),
             "scope" => "read"
           }
         )
             "scope" => "read"
           }
         )
@@ -494,6 +528,75 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
       assert html_response(conn, 200) =~ ~s(type="submit")
     end
 
       assert html_response(conn, 200) =~ ~s(type="submit")
     end
 
+    test "does not reuse expired tokens",
+         %{
+           conn: conn
+         } do
+      user = insert(:user)
+
+      app = insert(:oauth_app, redirect_uris: "https://redirect.url")
+
+      other_app = insert(:oauth_app, redirect_uris: "https://redirect.url")
+
+      token = insert(:oauth_token, user: user, app: app)
+
+      _not_reusable_token =
+        insert(:oauth_token,
+          app: other_app,
+          user: user,
+          valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), -60 * 100)
+        )
+
+      conn =
+        conn
+        |> put_req_header("authorization", "Bearer #{token.token}")
+        |> get(
+          "/oauth/authorize",
+          %{
+            "response_type" => "code",
+            "client_id" => other_app.client_id,
+            "redirect_uri" => OAuthController.default_redirect_uri(other_app),
+            "scope" => "read"
+          }
+        )
+
+      assert html_response(conn, 200) =~ ~s(type="submit")
+    end
+
+    test "does not reuse tokens with the wrong scopes",
+         %{
+           conn: conn
+         } do
+      user = insert(:user)
+
+      app = insert(:oauth_app, redirect_uris: "https://redirect.url")
+
+      other_app = insert(:oauth_app, redirect_uris: "https://redirect.url")
+
+      token = insert(:oauth_token, user: user, app: app, scopes: ["read"])
+
+      _not_reusable_token =
+        insert(:oauth_token,
+          app: other_app,
+          user: user
+        )
+
+      conn =
+        conn
+        |> put_req_header("authorization", "Bearer #{token.token}")
+        |> get(
+          "/oauth/authorize",
+          %{
+            "response_type" => "code",
+            "client_id" => other_app.client_id,
+            "redirect_uri" => OAuthController.default_redirect_uri(other_app),
+            "scope" => "read write"
+          }
+        )
+
+      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,
     test "with existing authentication and non-OOB `redirect_uri`, redirects to app with `token` and `state` params",
          %{
            app: app,
@@ -503,7 +606,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
 
       conn =
         conn
 
       conn =
         conn
-        |> AuthHelper.put_session_token(token.token)
+        |> put_req_header("authorization", "Bearer #{token.token}")
         |> get(
           "/oauth/authorize",
           %{
         |> get(
           "/oauth/authorize",
           %{
@@ -529,7 +632,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
 
       conn =
         conn
 
       conn =
         conn
-        |> AuthHelper.put_session_token(token.token)
+        |> put_req_header("authorization", "Bearer #{token.token}")
         |> get(
           "/oauth/authorize",
           %{
         |> get(
           "/oauth/authorize",
           %{
@@ -553,7 +656,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
 
       conn =
         conn
 
       conn =
         conn
-        |> AuthHelper.put_session_token(token.token)
+        |> put_req_header("authorization", "Bearer #{token.token}")
         |> get(
           "/oauth/authorize",
           %{
         |> get(
           "/oauth/authorize",
           %{
@@ -611,41 +714,6 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
       end
     end
 
       end
     end
 
-    test "authorize from cookie" do
-      user = insert(:user)
-      app = insert(:oauth_app)
-      oauth_token = insert(:oauth_token, user: user, app: app)
-      redirect_uri = OAuthController.default_redirect_uri(app)
-
-      conn =
-        build_conn()
-        |> Plug.Session.call(Plug.Session.init(@session_opts))
-        |> fetch_session()
-        |> AuthHelper.put_session_token(oauth_token.token)
-        |> post(
-          "/oauth/authorize",
-          %{
-            "authorization" => %{
-              "name" => user.nickname,
-              "client_id" => app.client_id,
-              "redirect_uri" => redirect_uri,
-              "scope" => app.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 == app.scopes
-    end
-
     test "redirect to on two-factor auth page" do
       otp_secret = TOTP.generate_secret()
 
     test "redirect to on two-factor auth page" do
       otp_secret = TOTP.generate_secret()
 
@@ -805,10 +873,12 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
           "client_secret" => app.client_secret
         })
 
           "client_secret" => app.client_secret
         })
 
-      assert %{"access_token" => token} = json_response(conn, 200)
+      assert %{"id" => id, "access_token" => access_token} = json_response(conn, 200)
 
 
-      token = Repo.get_by(Token, token: token)
+      token = Repo.get_by(Token, token: access_token)
       assert token
       assert token
+      assert token.id == id
+      assert token.token == access_token
       assert token.scopes == app.scopes
     end
 
       assert token.scopes == app.scopes
     end
 
@@ -923,7 +993,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
     end
 
     test "rejects token exchange for valid credentials belonging to unconfirmed user and confirmation is required" do
     end
 
     test "rejects token exchange for valid credentials belonging to unconfirmed user and confirmation is required" do
-      Pleroma.Config.put([:instance, :account_activation_required], true)
+      clear_config([:instance, :account_activation_required], true)
       password = "testpassword"
 
       {:ok, user} =
       password = "testpassword"
 
       {:ok, user} =
@@ -1007,7 +1077,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
     end
 
     test "rejects token exchange for user with confirmation_pending set to true" do
     end
 
     test "rejects token exchange for user with confirmation_pending set to true" do
-      Pleroma.Config.put([:instance, :account_activation_required], true)
+      clear_config([:instance, :account_activation_required], true)
       password = "testpassword"
 
       user =
       password = "testpassword"
 
       user =
@@ -1086,7 +1156,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
     setup do: clear_config([:oauth2, :issue_new_refresh_token])
 
     test "issues a new access token with keep fresh token" do
     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)
+      clear_config([:oauth2, :issue_new_refresh_token], true)
       user = insert(:user)
       app = insert(:oauth_app, scopes: ["read", "write"])
 
       user = insert(:user)
       app = insert(:oauth_app, scopes: ["read", "write"])
 
@@ -1125,7 +1195,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
     end
 
     test "issues a new access token with new fresh token" do
     end
 
     test "issues a new access token with new fresh token" do
-      Pleroma.Config.put([:oauth2, :issue_new_refresh_token], false)
+      clear_config([:oauth2, :issue_new_refresh_token], false)
       user = insert(:user)
       app = insert(:oauth_app, scopes: ["read", "write"])
 
       user = insert(:user)
       app = insert(:oauth_app, scopes: ["read", "write"])
 
@@ -1216,6 +1286,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
 
       response =
         build_conn()
 
       response =
         build_conn()
+        |> put_req_header("authorization", "Bearer #{access_token.token}")
         |> post("/oauth/token", %{
           "grant_type" => "refresh_token",
           "refresh_token" => access_token.refresh_token,
         |> post("/oauth/token", %{
           "grant_type" => "refresh_token",
           "refresh_token" => access_token.refresh_token,
@@ -1265,12 +1336,11 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
         build_conn()
         |> Plug.Session.call(Plug.Session.init(@session_opts))
         |> fetch_session()
         build_conn()
         |> Plug.Session.call(Plug.Session.init(@session_opts))
         |> fetch_session()
-        |> AuthHelper.put_session_token(oauth_token.token)
+        |> put_req_header("authorization", "Bearer #{oauth_token.token}")
         |> post("/oauth/revoke", %{"token" => oauth_token.token})
 
       assert json_response(conn, 200)
 
         |> post("/oauth/revoke", %{"token" => oauth_token.token})
 
       assert json_response(conn, 200)
 
-      refute AuthHelper.get_session_token(conn)
       assert Token.get_by_token(oauth_token.token) == {:error, :not_found}
     end
 
       assert Token.get_by_token(oauth_token.token) == {:error, :not_found}
     end
 
@@ -1284,12 +1354,11 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do
         build_conn()
         |> Plug.Session.call(Plug.Session.init(@session_opts))
         |> fetch_session()
         build_conn()
         |> Plug.Session.call(Plug.Session.init(@session_opts))
         |> fetch_session()
-        |> AuthHelper.put_session_token(oauth_token.token)
+        |> put_req_header("authorization", "Bearer #{oauth_token.token}")
         |> post("/oauth/revoke", %{"token" => other_app_oauth_token.token})
 
       assert json_response(conn, 200)
 
         |> post("/oauth/revoke", %{"token" => other_app_oauth_token.token})
 
       assert json_response(conn, 200)
 
-      assert AuthHelper.get_session_token(conn) == oauth_token.token
       assert Token.get_by_token(other_app_oauth_token.token) == {:error, :not_found}
     end
 
       assert Token.get_by_token(other_app_oauth_token.token) == {:error, :not_found}
     end