diff --git a/lib/pleroma/web/oauth/token.ex b/lib/pleroma/web/oauth/token.ex
index ca9e718ac8a27b562c4de9936500f50bddc51b23..71fd1b87463d70b045f8ea8bdd1d062e35f90fb7 100644
--- a/lib/pleroma/web/oauth/token.ex
+++ b/lib/pleroma/web/oauth/token.ex
@@ -47,9 +47,27 @@ defmodule Pleroma.Web.OAuth.Token do
 
   def delete_user_tokens(%User{id: user_id}) do
     from(
-      t in Pleroma.Web.OAuth.Token,
+      t in Token,
       where: t.user_id == ^user_id
     )
     |> Repo.delete_all()
   end
+
+  def delete_user_token(%User{id: user_id}, token_id) do
+    from(
+      t in Token,
+      where: t.user_id == ^user_id,
+      where: t.id == ^token_id
+    )
+    |> Repo.delete_all()
+  end
+
+  def get_user_tokens(%User{id: user_id}) do
+    from(
+      t in Token,
+      where: t.user_id == ^user_id
+    )
+    |> Repo.all()
+    |> Repo.preload(:app)
+  end
 end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 664f93c1c798d7318f93aed7b233a61c2a02cd3c..9a6cf22328c641ee45748cf43f905176f1d8fc33 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -392,6 +392,9 @@ defmodule Pleroma.Web.Router do
     get("/qvitter/mutes", TwitterAPI.Controller, :raw_empty_array)
 
     get("/externalprofile/show", TwitterAPI.Controller, :external_profile)
+
+    get("/oauth_tokens", TwitterAPI.Controller, :oauth_tokens)
+    delete("/oauth_tokens/:id", TwitterAPI.Controller, :revoke_token)
   end
 
   pipeline :ap_relay do
diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
index 7e4ee317c24b67d2ba1cf80947c5e216ff3e2c23..b815379fdae614ec57972249cf22ab471c77100a 100644
--- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex
+++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex
@@ -8,6 +8,10 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
   import Pleroma.Web.ControllerHelper, only: [json_response: 3]
 
   alias Ecto.Changeset
+  alias Pleroma.Web.TwitterAPI.{TwitterAPI, UserView, ActivityView, NotificationView, TokenView}
+  alias Pleroma.Web.CommonAPI
+  alias Pleroma.{Repo, Activity, Object, User, Notification}
+  alias Pleroma.Web.OAuth.Token
   alias Pleroma.Web.ActivityPub.ActivityPub
   alias Pleroma.Web.ActivityPub.Utils
   alias Pleroma.Web.CommonAPI
@@ -545,6 +549,20 @@ defmodule Pleroma.Web.TwitterAPI.Controller do
     end
   end
 
+  def oauth_tokens(%{assigns: %{user: user}} = conn, _params) do
+    with oauth_tokens <- Token.get_user_tokens(user) do
+      conn
+      |> put_view(TokenView)
+      |> render("index.json", %{tokens: oauth_tokens})
+    end
+  end
+
+  def revoke_token(%{assigns: %{user: user}} = conn, %{"id" => id} = _params) do
+    Token.delete_user_token(user, id)
+
+    json_reply(conn, 201, "")
+  end
+
   def blocks(%{assigns: %{user: user}} = conn, _params) do
     with blocked_users <- User.blocked_users(user) do
       conn
diff --git a/lib/pleroma/web/twitter_api/views/token_view.ex b/lib/pleroma/web/twitter_api/views/token_view.ex
new file mode 100644
index 0000000000000000000000000000000000000000..3ff314913fdac2faf6f44f7b70e62cb189cfe5b3
--- /dev/null
+++ b/lib/pleroma/web/twitter_api/views/token_view.ex
@@ -0,0 +1,21 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.TwitterAPI.TokenView do
+  use Pleroma.Web, :view
+
+  def render("index.json", %{tokens: tokens}) do
+    tokens
+    |> render_many(Pleroma.Web.TwitterAPI.TokenView, "show.json")
+    |> Enum.filter(&Enum.any?/1)
+  end
+
+  def render("show.json", %{token: token_entry}) do
+    %{
+      id: token_entry.id,
+      valid_until: token_entry.valid_until,
+      app_name: token_entry.app.client_name
+    }
+  end
+end
diff --git a/test/support/factory.ex b/test/support/factory.ex
index 0c21093cef5c3f7c4a8082d29a7f2d49623ffa66..7a91549f5eb687c591035879edf2c7c173c10ba6 100644
--- a/test/support/factory.ex
+++ b/test/support/factory.ex
@@ -227,4 +227,17 @@ defmodule Pleroma.Factory do
       unreachable_since: nil
     }
   end
+
+  def oauth_token_factory do
+    user = insert(:user)
+    oauth_app = insert(:oauth_app)
+
+    %Pleroma.Web.OAuth.Token{
+      token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(),
+      refresh_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64(),
+      user_id: user.id,
+      app_id: oauth_app.id,
+      valid_until: NaiveDateTime.add(NaiveDateTime.utc_now(), 60 * 10)
+    }
+  end
 end
diff --git a/test/web/twitter_api/twitter_api_controller_test.exs b/test/web/twitter_api/twitter_api_controller_test.exs
index d6b1331bd1dce09ca64e8af80e2581a8d6593115..1571ab68e5a453360f7a80d96e3a3864d753a8df 100644
--- a/test/web/twitter_api/twitter_api_controller_test.exs
+++ b/test/web/twitter_api/twitter_api_controller_test.exs
@@ -13,6 +13,7 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
   alias Pleroma.Object
   alias Pleroma.Notification
   alias Pleroma.Web.ActivityPub.ActivityPub
+  alias Pleroma.Web.OAuth.Token
   alias Pleroma.Web.TwitterAPI.UserView
   alias Pleroma.Web.TwitterAPI.NotificationView
   alias Pleroma.Web.CommonAPI
@@ -1915,4 +1916,38 @@ defmodule Pleroma.Web.TwitterAPI.ControllerTest do
                ActivityRepresenter.to_map(activity, %{user: user, for: user})
     end
   end
+
+  describe "GET /api/oauth_tokens" do
+    setup do
+      token = insert(:oauth_token) |> Repo.preload(:user)
+
+      %{token: token}
+    end
+
+    test "renders list", %{token: token} do
+      response =
+        build_conn()
+        |> assign(:user, token.user)
+        |> get("/api/oauth_tokens")
+
+      keys =
+        json_response(response, 200)
+        |> hd()
+        |> Map.keys()
+
+      assert keys -- ["id", "app_name", "valid_until"] == []
+    end
+
+    test "revoke token", %{token: token} do
+      response =
+        build_conn()
+        |> assign(:user, token.user)
+        |> delete("/api/oauth_tokens/#{token.id}")
+
+      tokens = Token.get_user_tokens(token.user)
+
+      assert tokens == []
+      assert response.status == 201
+    end
+  end
 end