[#923] Support for multiple OAuth consumer strategies.
authorIvan Tashkinov <ivant.business@gmail.com>
Wed, 20 Mar 2019 17:25:48 +0000 (20:25 +0300)
committerIvan Tashkinov <ivant.business@gmail.com>
Wed, 20 Mar 2019 17:25:48 +0000 (20:25 +0300)
config/config.exs
lib/pleroma/web/oauth/oauth_controller.ex
lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex
lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
mix.exs
mix.lock

index 03baf894dc439504b831318643f4fa309ce3a445..7d8de5af6f729987825434021efb13b29afb7187 100644 (file)
@@ -381,20 +381,26 @@ config :pleroma, :ldap,
   base: System.get_env("LDAP_BASE") || "dc=example,dc=com",
   uid: System.get_env("LDAP_UID") || "cn"
 
-config :pleroma, :auth, oauth_consumer_enabled: System.get_env("OAUTH_CONSUMER_ENABLED") == "true"
+oauth_consumer_strategies = String.split(System.get_env("OAUTH_CONSUMER_STRATEGIES" || ""))
+
+ueberauth_providers =
+  for strategy <- oauth_consumer_strategies do
+    strategy_module_name =
+      System.get_env("UEBERAUTH_#{String.upcase(strategy)}_STRATEGY_MODULE") ||
+        "Elixir.Ueberauth.Strategy.#{String.capitalize(strategy)}"
+
+    strategy_module = String.to_atom(strategy_module_name)
+    {String.to_atom(strategy), {strategy_module, [callback_params: ["state"]]}}
+  end
 
 config :ueberauth,
        Ueberauth,
        base_path: "/oauth",
-       providers: [
-         twitter:
-           {Ueberauth.Strategy.Twitter,
-            [callback_params: ~w[client_id redirect_uri scope scopes]]}
-       ]
-
-config :ueberauth, Ueberauth.Strategy.Twitter.OAuth,
-  consumer_key: System.get_env("TWITTER_CONSUMER_KEY"),
-  consumer_secret: System.get_env("TWITTER_CONSUMER_SECRET")
+       providers: ueberauth_providers
+
+config :pleroma, :auth,
+  oauth_consumer_strategies: oauth_consumer_strategies,
+  oauth_consumer_enabled: oauth_consumer_strategies != []
 
 # Import environment specific config. This must remain at the bottom
 # of this file so it overrides the configuration defined above.
index a2c62ae68a05d9fe44892ad6d317e03d84982dc8..b300c96dfb9772fa266cb55da547584e95e1644b 100644 (file)
@@ -187,25 +187,25 @@ defmodule Pleroma.Web.OAuth.OAuthController do
     |> redirect(to: "/")
   end
 
-  def callback(%{assigns: %{ueberauth_failure: failure}} = conn, %{"redirect_uri" => redirect_uri}) do
+  def callback(%{assigns: %{ueberauth_failure: failure}} = conn, params) do
+    params = callback_params(params)
     messages = for e <- Map.get(failure, :errors, []), do: e.message
     message = Enum.join(messages, "; ")
 
     conn
     |> put_flash(:error, "Failed to authenticate: #{message}.")
-    |> redirect(external: redirect_uri(conn, redirect_uri))
+    |> redirect(external: redirect_uri(conn, params["redirect_uri"]))
   end
 
-  def callback(
-        conn,
-        %{"client_id" => client_id, "redirect_uri" => redirect_uri} = params
-      ) do
+  def callback(conn, params) do
+    params = callback_params(params)
+
     with {:ok, registration} <- Authenticator.get_registration(conn, params) do
       user = Repo.preload(registration, :user).user
 
       auth_params = %{
-        "client_id" => client_id,
-        "redirect_uri" => redirect_uri,
+        "client_id" => params["client_id"],
+        "redirect_uri" => params["redirect_uri"],
         "scopes" => oauth_scopes(params, nil)
       }
 
@@ -230,10 +230,21 @@ defmodule Pleroma.Web.OAuth.OAuthController do
       _ ->
         conn
         |> put_flash(:error, "Failed to set up user account.")
-        |> redirect(external: redirect_uri(conn, redirect_uri))
+        |> redirect(external: redirect_uri(conn, params["redirect_uri"]))
     end
   end
 
+  defp callback_params(%{"state" => state} = params) do
+    [client_id, redirect_uri, scope, state] = String.split(state, "|")
+
+    Map.merge(params, %{
+      "client_id" => client_id,
+      "redirect_uri" => redirect_uri,
+      "scope" => scope,
+      "state" => state
+    })
+  end
+
   def registration_details(conn, params) do
     render(conn, "register.html", %{
       client_id: params["client_id"],
index e7251bce81fb7d54cc5d9277c5afef8770a3a9d3..a64859a494acd6dbe68bcb0953b2c3135a805c81 100644 (file)
@@ -1,14 +1,10 @@
-<h2>External OAuth Authorization</h2>
-<%= form_for @conn, o_auth_path(@conn, :request, :twitter), [method: "get"], fn f -> %>
-  <div class="scopes-input">
-  <%= label f, :scope, "Permissions" %>
-  <div class="scopes">
-    <%= text_input f, :scope, value: Enum.join(@available_scopes, " ") %>
-  </div>
-  </div>
+<br>
+<br>
+<h2>Sign in with external provider</h2>
 
-  <%= hidden_input f, :client_id, value: @client_id %>
-  <%= hidden_input f, :redirect_uri, value: @redirect_uri %>
-  <%= hidden_input f, :state, value: @state%>
-  <%= submit "Sign in with Twitter" %>
+<%= for strategy <- Pleroma.Config.get([:auth, :oauth_consumer_strategies], []) do %>
+  <%= form_for @conn, o_auth_path(@conn, :request, strategy), [method: "get"], fn f -> %>
+    <%= hidden_input f, :state, value: Enum.join([@client_id, @redirect_uri, Enum.join(@available_scopes, " "), @state], "|") %>
+    <%= submit "Sign in with #{String.capitalize(strategy)}" %>
+  <% end %>
 <% end %>
index 2fa7837fc439a322a53c7f813768e851b1024295..b2381869a7ecddc6dab8633016021e9f650b985e 100644 (file)
@@ -37,6 +37,5 @@
 <% end %>
 
 <%= if Pleroma.Config.get([:auth, :oauth_consumer_enabled]) do %>
-  <br>
   <%= render @view_module, "consumer.html", assigns %>
 <% end %>
diff --git a/mix.exs b/mix.exs
index 25711bc26b6bf482d49cc45524c12845d2e3af12..f7ab008acbfdb4e75678e3b1cc6326da24280f44 100644 (file)
--- a/mix.exs
+++ b/mix.exs
@@ -44,7 +44,7 @@ defmodule Pleroma.Mixfile do
   def application do
     [
       mod: {Pleroma.Application, []},
-      extra_applications: [:logger, :runtime_tools, :comeonin, :ueberauth_twitter],
+      extra_applications: [:logger, :runtime_tools, :comeonin],
       included_applications: [:ex_syslogger]
     ]
   end
@@ -57,6 +57,12 @@ defmodule Pleroma.Mixfile do
   #
   # Type `mix help deps` for examples and options.
   defp deps do
+    oauth_strategies = String.split(System.get_env("OAUTH_CONSUMER_STRATEGIES") || "")
+
+    oauth_deps =
+      for s <- oauth_strategies,
+          do: {String.to_atom("ueberauth_#{s}"), ">= 0.0.0"}
+
     [
       {:phoenix, "~> 1.4.1"},
       {:plug_cowboy, "~> 2.0"},
@@ -94,14 +100,11 @@ defmodule Pleroma.Mixfile do
       {:floki, "~> 0.20.0"},
       {:ex_syslogger, github: "slashmili/ex_syslogger", tag: "1.4.0"},
       {:timex, "~> 3.5"},
-      {:oauth, github: "tim/erlang-oauth"},
-      # {:oauth2, "~> 0.8", override: true},
       {:ueberauth, "~> 0.4"},
-      {:ueberauth_twitter, "~> 0.2"},
       {:auto_linker,
        git: "https://git.pleroma.social/pleroma/auto_linker.git",
        ref: "94193ca5f97c1f9fdf3d1469653e2d46fac34bcd"}
-    ]
+    ] ++ oauth_deps
   end
 
   # Aliases are shortcuts or tasks specific to the current project.
index 92660b70a352ceb5899f5e3063e9f3971e3032f0..6a6cee1a9d57848cd8a3a65180b77a510782a565 100644 (file)
--- a/mix.lock
+++ b/mix.lock
@@ -67,6 +67,7 @@
   "trailing_format_plug": {:hex, :trailing_format_plug, "0.0.7", "64b877f912cf7273bed03379936df39894149e35137ac9509117e59866e10e45", [:mix], [{:plug, "> 0.12.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
   "tzdata": {:hex, :tzdata, "0.5.17", "50793e3d85af49736701da1a040c415c97dc1caf6464112fd9bd18f425d3053b", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
   "ueberauth": {:hex, :ueberauth, "0.5.0", "4570ec94d7f784dc4c4aa94c83391dbd9b9bd7b66baa30e95a666c5ec1b168b1", [:mix], [{:plug, "~> 1.2", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
+  "ueberauth_facebook": {:hex, :ueberauth_facebook, "0.8.0", "9ec8571f804dd5c06f4e305d70606b39fc0ac8a8f43ed56ebb76012a97d14729", [:mix], [{:oauth2, "~> 0.9", [hex: :oauth2, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.4", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm"},
   "ueberauth_twitter": {:hex, :ueberauth_twitter, "0.2.4", "770ac273cc696cde986582e7a36df0923deb39fa3deff0152fbf150343809f81", [:mix], [{:httpoison, "~> 0.7", [hex: :httpoison, repo: "hexpm", optional: false]}, {:oauther, "~> 1.1", [hex: :oauther, repo: "hexpm", optional: false]}, {:poison, "~> 1.3 or ~> 2.0", [hex: :poison, repo: "hexpm", optional: false]}, {:ueberauth, "~> 0.2", [hex: :ueberauth, repo: "hexpm", optional: false]}], "hexpm"},
   "unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
   "unsafe": {:hex, :unsafe, "1.0.0", "7c21742cd05380c7875546b023481d3a26f52df8e5dfedcb9f958f322baae305", [:mix], [], "hexpm"},