Fix oauth2 (for real) (#179)
[akkoma] / lib / pleroma / web / mastodon_api / controllers / auth_controller.ex
index 9cc3984d0cd33fafaf9ccbd0229a5a0e082a4331..f415e5931ee0a189f098e9bbd592f4938b5d80fd 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.MastodonAPI.AuthController do
@@ -7,10 +7,12 @@ defmodule Pleroma.Web.MastodonAPI.AuthController do
 
   import Pleroma.Web.ControllerHelper, only: [json_response: 3]
 
+  alias Pleroma.Helpers.UriHelper
   alias Pleroma.User
   alias Pleroma.Web.OAuth.App
   alias Pleroma.Web.OAuth.Authorization
   alias Pleroma.Web.OAuth.Token
+  alias Pleroma.Web.OAuth.Token.Strategy.Revoke, as: RevokeToken
   alias Pleroma.Web.TwitterAPI.TwitterAPI
 
   action_fallback(Pleroma.Web.MastodonAPI.FallbackController)
@@ -20,26 +22,36 @@ defmodule Pleroma.Web.MastodonAPI.AuthController do
   @local_mastodon_name "Mastodon-Local"
 
   @doc "GET /web/login"
-  def login(%{assigns: %{user: %User{}}} = conn, _params) do
-    redirect(conn, to: local_mastodon_root_path(conn))
-  end
-
-  # Local Mastodon FE login init action
-  def login(conn, %{"code" => auth_token}) do
-    with {:ok, app} <- get_or_make_app(),
+  # Local Mastodon FE login callback action
+  def login(conn, %{"code" => auth_token} = params) do
+    with {:ok, app} <- local_mastofe_app(),
          {:ok, auth} <- Authorization.get_by_token(app, auth_token),
-         {:ok, token} <- Token.exchange_token(app, auth) do
+         {:ok, oauth_token} <- Token.exchange_token(app, auth) do
+      redirect_to =
+        conn
+        |> local_mastodon_post_login_path()
+        |> UriHelper.modify_uri_params(%{"access_token" => oauth_token.token})
+
       conn
-      |> put_session(:oauth_token, token.token)
-      |> redirect(to: local_mastodon_root_path(conn))
+      |> redirect(to: redirect_to)
+    else
+      _ -> redirect_to_oauth_form(conn, params)
+    end
+  end
+
+  def login(conn, params) do
+    with %{assigns: %{user: %User{}, token: %Token{app_id: app_id, token: token}}} <- conn,
+         {:ok, %{id: ^app_id}} <- local_mastofe_app() do
+      redirect(conn, to: local_mastodon_post_login_path(conn) <> "?access_token=#{token}")
+    else
+      _ -> redirect_to_oauth_form(conn, params)
     end
   end
 
-  # Local Mastodon FE callback action
-  def login(conn, _) do
-    with {:ok, app} <- get_or_make_app() do
+  defp redirect_to_oauth_form(conn, _params) do
+    with {:ok, app} <- local_mastofe_app() do
       path =
-        o_auth_path(conn, :authorize,
+        Routes.o_auth_path(conn, :authorize,
           response_type: "code",
           client_id: app.client_id,
           redirect_uri: ".",
@@ -52,9 +64,15 @@ defmodule Pleroma.Web.MastodonAPI.AuthController do
 
   @doc "DELETE /auth/sign_out"
   def logout(conn, _) do
-    conn
-    |> clear_session
-    |> redirect(to: "/")
+    conn =
+      with %{assigns: %{token: %Token{} = oauth_token}} <- conn,
+           {:ok, %Token{token: _session_token}} <- RevokeToken.revoke(oauth_token) do
+        conn
+      else
+        _ -> conn
+      end
+
+    redirect(conn, to: "/")
   end
 
   @doc "POST /auth/password"
@@ -66,10 +84,10 @@ defmodule Pleroma.Web.MastodonAPI.AuthController do
     json_response(conn, :no_content, "")
   end
 
-  defp local_mastodon_root_path(conn) do
+  defp local_mastodon_post_login_path(conn) do
     case get_session(conn, :return_to) do
       nil ->
-        masto_fe_path(conn, :index, ["getting-started"])
+        Routes.masto_fe_path(conn, :index, ["getting-started"])
 
       return_to ->
         delete_session(conn, :return_to)
@@ -77,9 +95,11 @@ defmodule Pleroma.Web.MastodonAPI.AuthController do
     end
   end
 
-  @spec get_or_make_app() :: {:ok, App.t()} | {:error, Ecto.Changeset.t()}
-  defp get_or_make_app do
-    %{client_name: @local_mastodon_name, redirect_uris: "."}
-    |> App.get_or_make(["read", "write", "follow", "push", "admin"])
+  @spec local_mastofe_app() :: {:ok, App.t()} | {:error, Ecto.Changeset.t()}
+  def local_mastofe_app do
+    App.get_or_make(
+      %{client_name: @local_mastodon_name, redirect_uris: "."},
+      ["read", "write", "follow", "push", "admin"]
+    )
   end
 end