From b4b7096e601cb24b0b047c4904bf6be43e0b805a Mon Sep 17 00:00:00 2001 From: Gordon Brown Date: Wed, 15 Mar 2017 13:15:49 -0600 Subject: [PATCH] Switch to native Elixir dependency for OAuth (#14) * Switch to OAuther from erlang-oauth * Clean up warnings * Cleanup per PR review. --- lib/ueberauth/strategy/twitter.ex | 19 ++++---- lib/ueberauth/strategy/twitter/internal.ex | 37 ++++++++++++++++ lib/ueberauth/strategy/twitter/oauth.ex | 50 ++++++++++------------ mix.exs | 14 +++--- mix.lock | 2 +- 5 files changed, 78 insertions(+), 44 deletions(-) create mode 100644 lib/ueberauth/strategy/twitter/internal.ex diff --git a/lib/ueberauth/strategy/twitter.ex b/lib/ueberauth/strategy/twitter.ex index b727c31..5f77aa1 100644 --- a/lib/ueberauth/strategy/twitter.ex +++ b/lib/ueberauth/strategy/twitter.ex @@ -99,25 +99,28 @@ defmodule Ueberauth.Strategy.Twitter do end defp fetch_user(conn, token) do - params = [include_entities: false, skip_status: true, include_email: true] + params = [{"include_entities", false}, {"skip_status", true}, {"include_email", true}] case Twitter.OAuth.get("/1.1/account/verify_credentials.json", params, token) do - {:ok, {{_, 401, _}, _, _}} -> + {:ok, %{status_code: 401, body: _, headers: _}} -> set_errors!(conn, [error("token", "unauthorized")]) - {:ok, {{_, status_code, _}, _, body}} when status_code in 200..399 -> - body = body |> List.to_string |> Poison.decode! + {:ok, %{status_code: status_code, body: body, headers: _}} when status_code in 200..399 -> + body = Poison.decode!(body) conn |> put_private(:twitter_token, token) |> put_private(:twitter_user, body) - {:ok, {_, _, body}} -> - body = body |> List.to_string |> Poison.decode! - + {:ok, %{status_code: _, body: body, headers: _}} -> + body = Poison.decode!(body) error = List.first(body["errors"]) set_errors!(conn, [error("token", error["message"])]) end end defp option(conn, key) do - Dict.get(options(conn), key, Dict.get(default_options, key)) + default = Keyword.get(default_options(), key) + + conn + |> options + |> Keyword.get(key, default) end end diff --git a/lib/ueberauth/strategy/twitter/internal.ex b/lib/ueberauth/strategy/twitter/internal.ex new file mode 100644 index 0000000..98d55ff --- /dev/null +++ b/lib/ueberauth/strategy/twitter/internal.ex @@ -0,0 +1,37 @@ +defmodule Ueberauth.Strategy.Twitter.OAuth.Internal do + @moduledoc """ + A layer to handle OAuth signing, etc. + """ + + def get(url, extraparams, {consumer_key, consumer_secret, _}, token \\ "", token_secret \\ "") do + creds = OAuther.credentials( + consumer_key: consumer_key, + consumer_secret: consumer_secret, + token: token, + token_secret: token_secret + ) + {header, params} = + "get" + |> OAuther.sign(url, extraparams, creds) + |> OAuther.header + + HTTPoison.get(url, [header], params: params) + end + + def params_decode(resp) do + resp + |> String.split("&", trim: true) + |> Enum.map(&String.split(&1, "=")) + |> Enum.map(&List.to_tuple/1) + |> Enum.into(%{}) + # |> Enum.reduce(%{}, fn({name, val}, acc) -> Map.put_new(acc, name, val) end) + end + + def token(params) do + params["oauth_token"] + end + + def token_secret(params) do + params["oauth_token_secret"] + end +end diff --git a/lib/ueberauth/strategy/twitter/oauth.ex b/lib/ueberauth/strategy/twitter/oauth.ex index 94d6c33..b2d3a79 100644 --- a/lib/ueberauth/strategy/twitter/oauth.ex +++ b/lib/ueberauth/strategy/twitter/oauth.ex @@ -10,6 +10,8 @@ defmodule Ueberauth.Strategy.Twitter.OAuth do redirect_uri: System.get_env("TWITTER_REDIRECT_URI") """ + alias Ueberauth.Strategy.Twitter.OAuth.Internal + @defaults [access_token: "/oauth/access_token", authorize_url: "/oauth/authorize", request_token: "/oauth/request_token", @@ -19,9 +21,8 @@ defmodule Ueberauth.Strategy.Twitter.OAuth do opts |> client |> to_url(:access_token) - |> String.to_char_list - |> :oauth.get([oauth_verifier: verifier], consumer(client), token, token_secret) - |> decode_access_response + |> Internal.get([{"oauth_verifier", verifier}], consumer(client()), token, token_secret) + |> decode_response end def access_token!(access_token, verifier, opts \\ []) do @@ -34,7 +35,7 @@ defmodule Ueberauth.Strategy.Twitter.OAuth do def authorize_url!({token, _token_secret}, opts \\ []) do opts |> client - |> to_url(:authorize_url, %{"oauth_token" => List.to_string(token)}) + |> to_url(:authorize_url, %{"oauth_token" => token}) end def client(opts \\ []) do @@ -48,21 +49,19 @@ defmodule Ueberauth.Strategy.Twitter.OAuth do def get(url, access_token), do: get(url, [], access_token) def get(url, params, {token, token_secret}) do - client + client() |> to_url(url) - |> String.to_char_list - |> :oauth.get(params, consumer(client), token, token_secret) + |> Internal.get(params, consumer(client()), token, token_secret) end def request_token(params \\ [], opts \\ []) do client = client(opts) - params = Keyword.put_new(params, :oauth_callback, client.redirect_uri) + params = [{"oauth_callback", client.redirect_uri} | params] client |> to_url(:request_token) - |> String.to_char_list - |> :oauth.get(params, consumer(client)) - |> decode_request_response + |> Internal.get(params, consumer(client)) + |> decode_response end def request_token!(params \\ [], opts \\ []) do @@ -74,27 +73,22 @@ defmodule Ueberauth.Strategy.Twitter.OAuth do defp consumer(client), do: {client.consumer_key, client.consumer_secret, :hmac_sha1} - defp decode_access_response({:ok, {{_, 200, _}, _, _} = resp}) do - params = :oauth.params_decode(resp) - token = :oauth.token(params) - token_secret = :oauth.token_secret(params) + defp decode_response({:ok, %{status_code: 200, body: body, headers: _}}) do + params = Internal.params_decode(body) + token = Internal.token(params) + token_secret = Internal.token_secret(params) {:ok, {token, token_secret}} end - defp decode_access_response({:ok, {{_, status_code, status_description}, _, _}}), do: {:error, "#{status_code} - #{status_description}"} - defp decode_access_response({:error, {error, [_, {:inet, [:inet], error_reason}]}}), do: {:error, "#{error}: #{error_reason}"} - defp decode_access_response(error), do: {:error, error} - - defp decode_request_response({:ok, {{_, 200, _}, _, _} = resp}) do - params = :oauth.params_decode(resp) - token = :oauth.token(params) - token_secret = :oauth.token_secret(params) - - {:ok, {token, token_secret}} + defp decode_response({:ok, %{status_code: status_code, body: _, headers: _}}) do + {:error, "#{status_code}"} + end + defp decode_response({:error, %{reason: reason}}) do + {:error, "#{reason}"} + end + defp decode_response(error) do + {:error, error} end - defp decode_request_response({:ok, {{_, status_code, status_description}, _, _}}), do: {:error, "#{status_code} - #{status_description}"} - defp decode_request_response({:error, {error, [_, {:inet, [:inet], error_reason}]}}), do: {:error, "#{error}: #{error_reason}"} - defp decode_request_response(error), do: {:error, error} defp endpoint("/" <> _path = endpoint, client), do: client.site <> endpoint defp endpoint(endpoint, _client), do: endpoint diff --git a/mix.exs b/mix.exs index 8746d80..8329ba2 100644 --- a/mix.exs +++ b/mix.exs @@ -8,25 +8,25 @@ defmodule UeberauthTwitter.Mixfile do [app: :ueberauth_twitter, version: @version, name: "Ueberauth Twitter Strategy", - package: package, + package: package(), elixir: "~> 1.1", build_embedded: Mix.env == :prod, start_permanent: Mix.env == :prod, source_url: @url, homepage_url: @url, - description: description, - deps: deps, - docs: docs] + description: description(), + deps: deps(), + docs: docs()] end def application do - [applications: [:logger, :httpoison, :oauth, :ueberauth]] + [applications: [:logger, :httpoison, :oauther, :ueberauth]] end defp deps do [ {:httpoison, "~> 0.7"}, - {:oauth, github: "tim/erlang-oauth"}, + {:oauther, "~> 1.1"}, {:poison, "~> 1.3 or ~> 2.0"}, {:ueberauth, "~> 0.2"}, @@ -38,7 +38,7 @@ defmodule UeberauthTwitter.Mixfile do end defp docs do - [extras: docs_extras, main: "extra-readme"] + [extras: docs_extras(), main: "extra-readme"] end defp docs_extras do diff --git a/mix.lock b/mix.lock index 7664cd4..403e80a 100644 --- a/mix.lock +++ b/mix.lock @@ -10,7 +10,7 @@ "mimetype_parser": {:hex, :mimetype_parser, "0.1.0"}, "oauth": {:git, "https://github.com/tim/erlang-oauth.git", "cd31addc828179983564fd57738f1680a4a4d1ff", []}, "oauth2": {:hex, :oauth2, "0.5.0"}, - "oauther": {:hex, :oauther, "1.0.2"}, + "oauther": {:hex, :oauther, "1.1.0", "c9a56e200507ce64e069f5273143db0cddd7904cd5d1fe46920388a48f22441b", [:mix], []}, "plug": {:hex, :plug, "1.0.3", "8bbcbdaa4cb15170b9a15cb12153e8a6d9e176ce78e4c1990ea0b505b0ca24a0", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, optional: true]}]}, "poison": {:hex, :poison, "1.5.0", "f2f4f460623a6f154683abae34352525e1d918380267cdbd949a07ba57503248", [:mix], []}, "ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5", "2e73e068cd6393526f9fa6d399353d7c9477d6886ba005f323b592d389fb47be", [:make], []},