summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/config.exs15
-rw-r--r--config/dev.exs1
-rw-r--r--lib/pleroma/user.ex46
-rw-r--r--lib/pleroma/web/auth/authenticator.ex9
-rw-r--r--lib/pleroma/web/auth/ldap_authenticator.ex10
-rw-r--r--lib/pleroma/web/auth/pleroma_authenticator.ex52
-rw-r--r--lib/pleroma/web/endpoint.ex17
-rw-r--r--lib/pleroma/web/oauth/oauth_controller.ex86
-rw-r--r--lib/pleroma/web/router.ex12
-rw-r--r--lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex14
-rw-r--r--lib/pleroma/web/templates/o_auth/o_auth/show.html.eex7
-rw-r--r--mix.exs9
-rw-r--r--mix.lock11
-rw-r--r--priv/repo/migrations/20190315101315_add_auth_provider_and_auth_provider_uid_to_users.exs12
14 files changed, 263 insertions, 38 deletions
diff --git a/config/config.exs b/config/config.exs
index ccdd35777..6839b489b 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -381,6 +381,21 @@ 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: false
+
+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")
+
# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"
diff --git a/config/dev.exs b/config/dev.exs
index f77bb9976..a7eb4b644 100644
--- a/config/dev.exs
+++ b/config/dev.exs
@@ -12,7 +12,6 @@ config :pleroma, Pleroma.Web.Endpoint,
protocol_options: [max_request_line_length: 8192, max_header_value_length: 8192]
],
protocol: "http",
- secure_cookie_flag: false,
debug_errors: true,
code_reloader: true,
check_origin: false,
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index 692ae836c..7f8b282e0 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -41,6 +41,8 @@ defmodule Pleroma.User do
field(:email, :string)
field(:name, :string)
field(:nickname, :string)
+ field(:auth_provider, :string)
+ field(:auth_provider_uid, :string)
field(:password_hash, :string)
field(:password, :string, virtual: true)
field(:password_confirmation, :string, virtual: true)
@@ -207,6 +209,36 @@ defmodule Pleroma.User do
update_and_set_cache(password_update_changeset(user, data))
end
+ # TODO: FIXME (WIP):
+ def oauth_register_changeset(struct, params \\ %{}) do
+ info_change = User.Info.confirmation_changeset(%User.Info{}, :confirmed)
+
+ changeset =
+ struct
+ |> cast(params, [:email, :nickname, :name, :bio, :auth_provider, :auth_provider_uid])
+ |> validate_required([:auth_provider, :auth_provider_uid])
+ |> unique_constraint(:email)
+ |> unique_constraint(:nickname)
+ |> validate_exclusion(:nickname, Pleroma.Config.get([Pleroma.User, :restricted_nicknames]))
+ |> validate_format(:email, @email_regex)
+ |> validate_length(:bio, max: 1000)
+ |> put_change(:info, info_change)
+
+ if changeset.valid? do
+ nickname = changeset.changes[:nickname]
+ ap_id = (nickname && User.ap_id(%User{nickname: nickname})) || nil
+ followers = User.ap_followers(%User{nickname: ap_id})
+
+ changeset
+ |> put_change(:ap_id, ap_id)
+ |> unique_constraint(:ap_id)
+ |> put_change(:following, [followers])
+ |> put_change(:follower_address, followers)
+ else
+ changeset
+ end
+ end
+
def register_changeset(struct, params \\ %{}, opts \\ []) do
confirmation_status =
if opts[:confirmed] || !Pleroma.Config.get([:instance, :account_activation_required]) do
@@ -506,13 +538,19 @@ defmodule Pleroma.User do
end
end
+ def get_by_email(email), do: Repo.get_by(User, email: email)
+
def get_by_nickname_or_email(nickname_or_email) do
- case user = Repo.get_by(User, nickname: nickname_or_email) do
- %User{} -> user
- nil -> Repo.get_by(User, email: nickname_or_email)
- end
+ get_by_nickname(nickname_or_email) || get_by_email(nickname_or_email)
end
+ def get_by_auth_provider_uid(auth_provider, auth_provider_uid),
+ do:
+ Repo.get_by(User,
+ auth_provider: to_string(auth_provider),
+ auth_provider_uid: to_string(auth_provider_uid)
+ )
+
def get_cached_user_info(user) do
key = "user_info:#{user.id}"
Cachex.fetch!(:user_cache, key, fn _ -> user_info(user) end)
diff --git a/lib/pleroma/web/auth/authenticator.ex b/lib/pleroma/web/auth/authenticator.ex
index 82267c595..fa439d562 100644
--- a/lib/pleroma/web/auth/authenticator.ex
+++ b/lib/pleroma/web/auth/authenticator.ex
@@ -12,8 +12,13 @@ defmodule Pleroma.Web.Auth.Authenticator do
)
end
- @callback get_user(Plug.Conn.t()) :: {:ok, User.t()} | {:error, any()}
- def get_user(plug), do: implementation().get_user(plug)
+ @callback get_user(Plug.Conn.t(), Map.t()) :: {:ok, User.t()} | {:error, any()}
+ def get_user(plug, params), do: implementation().get_user(plug, params)
+
+ @callback get_or_create_user_by_oauth(Plug.Conn.t(), Map.t()) ::
+ {:ok, User.t()} | {:error, any()}
+ def get_or_create_user_by_oauth(plug, params),
+ do: implementation().get_or_create_user_by_oauth(plug, params)
@callback handle_error(Plug.Conn.t(), any()) :: any()
def handle_error(plug, error), do: implementation().handle_error(plug, error)
diff --git a/lib/pleroma/web/auth/ldap_authenticator.ex b/lib/pleroma/web/auth/ldap_authenticator.ex
index 88217aab8..6c65cff27 100644
--- a/lib/pleroma/web/auth/ldap_authenticator.ex
+++ b/lib/pleroma/web/auth/ldap_authenticator.ex
@@ -12,10 +12,10 @@ defmodule Pleroma.Web.Auth.LDAPAuthenticator do
@connection_timeout 10_000
@search_timeout 10_000
- def get_user(%Plug.Conn{} = conn) do
+ def get_user(%Plug.Conn{} = conn, params) do
if Pleroma.Config.get([:ldap, :enabled]) do
{name, password} =
- case conn.params do
+ case params do
%{"authorization" => %{"name" => name, "password" => password}} ->
{name, password}
@@ -29,17 +29,19 @@ defmodule Pleroma.Web.Auth.LDAPAuthenticator do
{:error, {:ldap_connection_error, _}} ->
# When LDAP is unavailable, try default authenticator
- Pleroma.Web.Auth.PleromaAuthenticator.get_user(conn)
+ Pleroma.Web.Auth.PleromaAuthenticator.get_user(conn, params)
error ->
error
end
else
# Fall back to default authenticator
- Pleroma.Web.Auth.PleromaAuthenticator.get_user(conn)
+ Pleroma.Web.Auth.PleromaAuthenticator.get_user(conn, params)
end
end
+ def get_or_create_user_by_oauth(conn, params), do: get_user(conn, params)
+
def handle_error(%Plug.Conn{} = _conn, error) do
error
end
diff --git a/lib/pleroma/web/auth/pleroma_authenticator.ex b/lib/pleroma/web/auth/pleroma_authenticator.ex
index 94a19ad49..2e2bcfb70 100644
--- a/lib/pleroma/web/auth/pleroma_authenticator.ex
+++ b/lib/pleroma/web/auth/pleroma_authenticator.ex
@@ -8,9 +8,9 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do
@behaviour Pleroma.Web.Auth.Authenticator
- def get_user(%Plug.Conn{} = conn) do
+ def get_user(%Plug.Conn{} = _conn, params) do
{name, password} =
- case conn.params do
+ case params do
%{"authorization" => %{"name" => name, "password" => password}} ->
{name, password}
@@ -27,6 +27,54 @@ defmodule Pleroma.Web.Auth.PleromaAuthenticator do
end
end
+ def get_or_create_user_by_oauth(
+ %Plug.Conn{assigns: %{ueberauth_auth: %{provider: provider, uid: uid} = auth}},
+ _params
+ ) do
+ user = User.get_by_auth_provider_uid(provider, uid)
+
+ if user do
+ {:ok, user}
+ else
+ info = auth.info
+ email = info.email
+ nickname = info.nickname
+
+ # TODO: FIXME: connect to existing (non-oauth) account (need a UI flow for that) / generate a random nickname?
+ email =
+ if email && User.get_by_email(email) do
+ nil
+ else
+ email
+ end
+
+ nickname =
+ if nickname && User.get_by_nickname(nickname) do
+ nil
+ else
+ nickname
+ end
+
+ new_user =
+ User.oauth_register_changeset(
+ %User{},
+ %{
+ auth_provider: to_string(provider),
+ auth_provider_uid: to_string(uid),
+ name: info.name,
+ bio: info.description,
+ email: email,
+ nickname: nickname
+ }
+ )
+
+ Pleroma.Repo.insert(new_user)
+ end
+ end
+
+ def get_or_create_user_by_oauth(%Plug.Conn{} = _conn, _params),
+ do: {:error, :missing_credentials}
+
def handle_error(%Plug.Conn{} = _conn, error) do
error
end
diff --git a/lib/pleroma/web/endpoint.ex b/lib/pleroma/web/endpoint.ex
index fa2d1cbe7..f92724d8b 100644
--- a/lib/pleroma/web/endpoint.ex
+++ b/lib/pleroma/web/endpoint.ex
@@ -51,11 +51,21 @@ defmodule Pleroma.Web.Endpoint do
plug(Plug.MethodOverride)
plug(Plug.Head)
+ secure_cookies = Pleroma.Config.get([__MODULE__, :secure_cookie_flag])
+
cookie_name =
- if Application.get_env(:pleroma, Pleroma.Web.Endpoint) |> Keyword.get(:secure_cookie_flag),
+ if secure_cookies,
do: "__Host-pleroma_key",
else: "pleroma_key"
+ same_site =
+ if Pleroma.Config.get([:auth, :oauth_consumer_enabled]) do
+ # Note: "SameSite=Strict" prevents sign in with external OAuth provider (no cookies during callback request)
+ "SameSite=Lax"
+ else
+ "SameSite=Strict"
+ end
+
# The session will be stored in the cookie and signed,
# this means its contents can be read but not tampered with.
# Set :encryption_salt if you would also like to encrypt it.
@@ -65,9 +75,8 @@ defmodule Pleroma.Web.Endpoint do
key: cookie_name,
signing_salt: {Pleroma.Config, :get, [[__MODULE__, :signing_salt], "CqaoopA2"]},
http_only: true,
- secure:
- Application.get_env(:pleroma, Pleroma.Web.Endpoint) |> Keyword.get(:secure_cookie_flag),
- extra: "SameSite=Strict"
+ secure: secure_cookies,
+ extra: same_site
)
plug(Pleroma.Web.Router)
diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex
index d151efe9e..588933d31 100644
--- a/lib/pleroma/web/oauth/oauth_controller.ex
+++ b/lib/pleroma/web/oauth/oauth_controller.ex
@@ -14,11 +14,59 @@ defmodule Pleroma.Web.OAuth.OAuthController do
import Pleroma.Web.ControllerHelper, only: [oauth_scopes: 2]
+ if Pleroma.Config.get([:auth, :oauth_consumer_enabled]), do: plug(Ueberauth)
+
plug(:fetch_session)
plug(:fetch_flash)
action_fallback(Pleroma.Web.OAuth.FallbackController)
+ def request(conn, params) do
+ message =
+ if params["provider"] do
+ "Unsupported OAuth provider: #{params["provider"]}."
+ else
+ "Bad OAuth request."
+ end
+
+ conn
+ |> put_flash(:error, message)
+ |> redirect(to: "/")
+ end
+
+ def callback(%{assigns: %{ueberauth_failure: failure}} = conn, %{"redirect_uri" => redirect_uri}) do
+ 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))
+ end
+
+ def callback(
+ conn,
+ %{"client_id" => client_id, "redirect_uri" => redirect_uri} = params
+ ) do
+ with {:ok, user} <- Authenticator.get_or_create_user_by_oauth(conn, params) do
+ do_create_authorization(
+ conn,
+ %{
+ "authorization" => %{
+ "client_id" => client_id,
+ "redirect_uri" => redirect_uri,
+ "scope" => oauth_scopes(params, nil)
+ }
+ },
+ user
+ )
+ else
+ _ ->
+ conn
+ |> put_flash(:error, "Failed to set up user account.")
+ |> redirect(external: redirect_uri(conn, redirect_uri))
+ end
+ end
+
def authorize(conn, params) do
app = Repo.get_by(App, client_id: params["client_id"])
available_scopes = (app && app.scopes) || []
@@ -35,14 +83,21 @@ defmodule Pleroma.Web.OAuth.OAuthController do
})
end
- def create_authorization(conn, %{
- "authorization" =>
- %{
- "client_id" => client_id,
- "redirect_uri" => redirect_uri
- } = auth_params
- }) do
- with {_, {:ok, %User{} = user}} <- {:get_user, Authenticator.get_user(conn)},
+ def create_authorization(conn, params), do: do_create_authorization(conn, params, nil)
+
+ defp do_create_authorization(
+ conn,
+ %{
+ "authorization" =>
+ %{
+ "client_id" => client_id,
+ "redirect_uri" => redirect_uri
+ } = auth_params
+ } = params,
+ user
+ ) do
+ with {_, {:ok, %User{} = user}} <-
+ {:get_user, (user && {:ok, user}) || Authenticator.get_user(conn, params)},
%App{} = app <- Repo.get_by(App, client_id: client_id),
true <- redirect_uri in String.split(app.redirect_uris),
scopes <- oauth_scopes(auth_params, []),
@@ -51,13 +106,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
{:missing_scopes, false} <- {:missing_scopes, scopes == []},
{:auth_active, true} <- {:auth_active, User.auth_active?(user)},
{:ok, auth} <- Authorization.create_authorization(app, user, scopes) do
- redirect_uri =
- if redirect_uri == "." do
- # Special case: Local MastodonFE
- mastodon_api_url(conn, :login)
- else
- redirect_uri
- end
+ redirect_uri = redirect_uri(conn, redirect_uri)
cond do
redirect_uri == "urn:ietf:wg:oauth:2.0:oob" ->
@@ -129,7 +178,7 @@ defmodule Pleroma.Web.OAuth.OAuthController do
conn,
%{"grant_type" => "password"} = params
) do
- with {_, {:ok, %User{} = user}} <- {:get_user, Authenticator.get_user(conn)},
+ with {_, {:ok, %User{} = user}} <- {:get_user, Authenticator.get_user(conn, params)},
%App{} = app <- get_app_from_request(conn, params),
{:auth_active, true} <- {:auth_active, User.auth_active?(user)},
scopes <- oauth_scopes(params, app.scopes),
@@ -215,4 +264,9 @@ defmodule Pleroma.Web.OAuth.OAuthController do
nil
end
end
+
+ # Special case: Local MastodonFE
+ defp redirect_uri(conn, "."), do: mastodon_api_url(conn, :login)
+
+ defp redirect_uri(_conn, redirect_uri), do: redirect_uri
end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index befd382ba..9b6784120 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -5,6 +5,11 @@
defmodule Pleroma.Web.Router do
use Pleroma.Web, :router
+ pipeline :browser do
+ plug(:accepts, ["html"])
+ plug(:fetch_session)
+ end
+
pipeline :api do
plug(:accepts, ["json"])
plug(:fetch_session)
@@ -203,6 +208,13 @@ defmodule Pleroma.Web.Router do
post("/authorize", OAuthController, :create_authorization)
post("/token", OAuthController, :token_exchange)
post("/revoke", OAuthController, :token_revoke)
+
+ scope [] do
+ pipe_through(:browser)
+
+ get("/:provider", OAuthController, :request)
+ get("/:provider/callback", OAuthController, :callback)
+ end
end
scope "/api/v1", Pleroma.Web.MastodonAPI do
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex
new file mode 100644
index 000000000..e7251bce8
--- /dev/null
+++ b/lib/pleroma/web/templates/o_auth/o_auth/consumer.html.eex
@@ -0,0 +1,14 @@
+<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>
+
+ <%= 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" %>
+<% end %>
diff --git a/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex b/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
index 161333847..2fa7837fc 100644
--- a/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
+++ b/lib/pleroma/web/templates/o_auth/o_auth/show.html.eex
@@ -4,7 +4,9 @@
<%= if get_flash(@conn, :error) do %>
<p class="alert alert-danger" role="alert"><%= get_flash(@conn, :error) %></p>
<% end %>
+
<h2>OAuth Authorization</h2>
+
<%= form_for @conn, o_auth_path(@conn, :authorize), [as: "authorization"], fn f -> %>
<div class="input">
<%= label f, :name, "Name or email" %>
@@ -33,3 +35,8 @@
<%= hidden_input f, :state, value: @state%>
<%= submit "Authorize" %>
<% 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 efdf15d3a..25711bc26 100644
--- 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],
+ extra_applications: [:logger, :runtime_tools, :comeonin, :ueberauth_twitter],
included_applications: [:ex_syslogger]
]
end
@@ -72,7 +72,8 @@ defmodule Pleroma.Mixfile do
{:phoenix_html, "~> 2.10"},
{:calendar, "~> 0.17.4"},
{:cachex, "~> 3.0.2"},
- {:httpoison, "~> 1.2.0"},
+ {:httpoison, "~> 1.2.0", override: true},
+ {:poison, "~> 3.0", override: true},
{:tesla, "~> 1.2"},
{:jason, "~> 1.0"},
{:mogrify, "~> 0.6.1"},
@@ -93,6 +94,10 @@ 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"}
diff --git a/mix.lock b/mix.lock
index f43a18564..92660b70a 100644
--- a/mix.lock
+++ b/mix.lock
@@ -4,7 +4,7 @@
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], [], "hexpm"},
"cachex": {:hex, :cachex, "3.0.2", "1351caa4e26e29f7d7ec1d29b53d6013f0447630bbf382b4fb5d5bad0209f203", [:mix], [{:eternal, "~> 1.2", [hex: :eternal, repo: "hexpm", optional: false]}, {:unsafe, "~> 1.0", [hex: :unsafe, repo: "hexpm", optional: false]}], "hexpm"},
"calendar": {:hex, :calendar, "0.17.4", "22c5e8d98a4db9494396e5727108dffb820ee0d18fed4b0aa8ab76e4f5bc32f1", [:mix], [{:tzdata, "~> 0.5.8 or ~> 0.1.201603", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
- "certifi": {:hex, :certifi, "2.4.2", "75424ff0f3baaccfd34b1214184b6ef616d89e420b258bb0a5ea7d7bc628f7f0", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
+ "certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm"},
"comeonin": {:hex, :comeonin, "4.1.1", "c7304fc29b45b897b34142a91122bc72757bc0c295e9e824999d5179ffc08416", [:mix], [{:argon2_elixir, "~> 1.2", [hex: :argon2_elixir, repo: "hexpm", optional: true]}, {:bcrypt_elixir, "~> 0.12.1 or ~> 1.0", [hex: :bcrypt_elixir, repo: "hexpm", optional: true]}, {:pbkdf2_elixir, "~> 0.12", [hex: :pbkdf2_elixir, repo: "hexpm", optional: true]}], "hexpm"},
"connection": {:hex, :connection, "1.0.4", "a1cae72211f0eef17705aaededacac3eb30e6625b04a6117c1b2db6ace7d5976", [:mix], [], "hexpm"},
@@ -26,7 +26,7 @@
"floki": {:hex, :floki, "0.20.4", "be42ac911fece24b4c72f3b5846774b6e61b83fe685c2fc9d62093277fb3bc86", [:mix], [{:html_entities, "~> 0.4.0", [hex: :html_entities, repo: "hexpm", optional: false]}, {:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},
"gen_smtp": {:hex, :gen_smtp, "0.13.0", "11f08504c4bdd831dc520b8f84a1dce5ce624474a797394e7aafd3c29f5dcd25", [:rebar3], [], "hexpm"},
"gettext": {:hex, :gettext, "0.15.0", "40a2b8ce33a80ced7727e36768499fc9286881c43ebafccae6bab731e2b2b8ce", [:mix], [], "hexpm"},
- "hackney": {:hex, :hackney, "1.14.3", "b5f6f5dcc4f1fba340762738759209e21914516df6be440d85772542d4a5e412", [:rebar3], [{:certifi, "2.4.2", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
+ "hackney": {:hex, :hackney, "1.15.1", "9f8f471c844b8ce395f7b6d8398139e26ddca9ebc171a8b91342ee15a19963f4", [:rebar3], [{:certifi, "2.5.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
"html_entities": {:hex, :html_entities, "0.4.0", "f2fee876858cf6aaa9db608820a3209e45a087c5177332799592142b50e89a6b", [:mix], [], "hexpm"},
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.3.0", "f005ad692b717691203f940c686208aa3d8ffd9dd4bb3699240096a51fa9564e", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm"},
"httpoison": {:hex, :httpoison, "1.2.0", "2702ed3da5fd7a8130fc34b11965c8cfa21ade2f232c00b42d96d4967c39a3a3", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
@@ -38,11 +38,14 @@
"meck": {:hex, :meck, "0.8.13", "ffedb39f99b0b99703b8601c6f17c7f76313ee12de6b646e671e3188401f7866", [:rebar3], [], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
- "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
+ "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
"mochiweb": {:hex, :mochiweb, "2.15.0", "e1daac474df07651e5d17cc1e642c4069c7850dc4508d3db7263a0651330aacc", [:rebar3], [], "hexpm"},
"mock": {:hex, :mock, "0.3.1", "994f00150f79a0ea50dc9d86134cd9ebd0d177ad60bd04d1e46336cdfdb98ff9", [:mix], [{:meck, "~> 0.8.8", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm"},
"mogrify": {:hex, :mogrify, "0.6.1", "de1b527514f2d95a7bbe9642eb556061afb337e220cf97adbf3a4e6438ed70af", [:mix], [], "hexpm"},
"nimble_parsec": {:hex, :nimble_parsec, "0.4.0", "ee261bb53214943679422be70f1658fff573c5d0b0a1ecd0f18738944f818efe", [:mix], [], "hexpm"},
+ "oauth": {:git, "https://github.com/tim/erlang-oauth.git", "bd19896e31125f99ff45bb5850b1c0e74b996743", []},
+ "oauth2": {:hex, :oauth2, "0.9.4", "632e8e8826a45e33ac2ea5ac66dcc019ba6bb5a0d2ba77e342d33e3b7b252c6e", [:mix], [{:hackney, "~> 1.7", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
+ "oauther": {:hex, :oauther, "1.1.1", "7d8b16167bb587ecbcddd3f8792beb9ec3e7b65c1f8ebd86b8dd25318d535752", [:mix], [], "hexpm"},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
"pbkdf2_elixir": {:hex, :pbkdf2_elixir, "0.12.3", "6706a148809a29c306062862c803406e88f048277f6e85b68faf73291e820b84", [:mix], [], "hexpm"},
"phoenix": {:hex, :phoenix, "1.4.1", "801f9d632808657f1f7c657c8bbe624caaf2ba91429123ebe3801598aea4c3d9", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 1.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm"},
@@ -63,6 +66,8 @@
"timex": {:hex, :timex, "3.5.0", "b0a23167da02d0fe4f1a4e104d1f929a00d348502b52432c05de875d0b9cffa5", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm"},
"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_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"},
"web_push_encryption": {:hex, :web_push_encryption, "0.2.1", "d42cecf73420d9dc0053ba3299cc8c8d6ff2be2487d67ca2a57265868e4d9a98", [:mix], [{:httpoison, "~> 1.0", [hex: :httpoison, repo: "hexpm", optional: false]}, {:jose, "~> 1.8", [hex: :jose, repo: "hexpm", optional: false]}, {:poison, "~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}], "hexpm"},
diff --git a/priv/repo/migrations/20190315101315_add_auth_provider_and_auth_provider_uid_to_users.exs b/priv/repo/migrations/20190315101315_add_auth_provider_and_auth_provider_uid_to_users.exs
new file mode 100644
index 000000000..90947f85a
--- /dev/null
+++ b/priv/repo/migrations/20190315101315_add_auth_provider_and_auth_provider_uid_to_users.exs
@@ -0,0 +1,12 @@
+defmodule Pleroma.Repo.Migrations.AddAuthProviderAndAuthProviderUidToUsers do
+ use Ecto.Migration
+
+ def change do
+ alter table(:users) do
+ add :auth_provider, :string
+ add :auth_provider_uid, :string
+ end
+
+ create unique_index(:users, [:auth_provider, :auth_provider_uid])
+ end
+end