Switch to native Elixir dependency for OAuth (#14)

* Switch to OAuther from erlang-oauth

* Clean up warnings

* Cleanup per PR review.
This commit is contained in:
Gordon Brown 2017-03-15 13:15:49 -06:00 committed by Sean Callan
parent 2d2d94803d
commit b4b7096e60
5 changed files with 78 additions and 44 deletions

View File

@ -99,25 +99,28 @@ defmodule Ueberauth.Strategy.Twitter do
end end
defp fetch_user(conn, token) do 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 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")]) set_errors!(conn, [error("token", "unauthorized")])
{:ok, {{_, status_code, _}, _, body}} when status_code in 200..399 -> {:ok, %{status_code: status_code, body: body, headers: _}} when status_code in 200..399 ->
body = body |> List.to_string |> Poison.decode! body = Poison.decode!(body)
conn conn
|> put_private(:twitter_token, token) |> put_private(:twitter_token, token)
|> put_private(:twitter_user, body) |> put_private(:twitter_user, body)
{:ok, {_, _, body}} -> {:ok, %{status_code: _, body: body, headers: _}} ->
body = body |> List.to_string |> Poison.decode! body = Poison.decode!(body)
error = List.first(body["errors"]) error = List.first(body["errors"])
set_errors!(conn, [error("token", error["message"])]) set_errors!(conn, [error("token", error["message"])])
end end
end end
defp option(conn, key) do 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
end end

View File

@ -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

View File

@ -10,6 +10,8 @@ defmodule Ueberauth.Strategy.Twitter.OAuth do
redirect_uri: System.get_env("TWITTER_REDIRECT_URI") redirect_uri: System.get_env("TWITTER_REDIRECT_URI")
""" """
alias Ueberauth.Strategy.Twitter.OAuth.Internal
@defaults [access_token: "/oauth/access_token", @defaults [access_token: "/oauth/access_token",
authorize_url: "/oauth/authorize", authorize_url: "/oauth/authorize",
request_token: "/oauth/request_token", request_token: "/oauth/request_token",
@ -19,9 +21,8 @@ defmodule Ueberauth.Strategy.Twitter.OAuth do
opts opts
|> client |> client
|> to_url(:access_token) |> to_url(:access_token)
|> String.to_char_list |> Internal.get([{"oauth_verifier", verifier}], consumer(client()), token, token_secret)
|> :oauth.get([oauth_verifier: verifier], consumer(client), token, token_secret) |> decode_response
|> decode_access_response
end end
def access_token!(access_token, verifier, opts \\ []) do 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 def authorize_url!({token, _token_secret}, opts \\ []) do
opts opts
|> client |> client
|> to_url(:authorize_url, %{"oauth_token" => List.to_string(token)}) |> to_url(:authorize_url, %{"oauth_token" => token})
end end
def client(opts \\ []) do 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, access_token), do: get(url, [], access_token)
def get(url, params, {token, token_secret}) do def get(url, params, {token, token_secret}) do
client client()
|> to_url(url) |> to_url(url)
|> String.to_char_list |> Internal.get(params, consumer(client()), token, token_secret)
|> :oauth.get(params, consumer(client), token, token_secret)
end end
def request_token(params \\ [], opts \\ []) do def request_token(params \\ [], opts \\ []) do
client = client(opts) client = client(opts)
params = Keyword.put_new(params, :oauth_callback, client.redirect_uri) params = [{"oauth_callback", client.redirect_uri} | params]
client client
|> to_url(:request_token) |> to_url(:request_token)
|> String.to_char_list |> Internal.get(params, consumer(client))
|> :oauth.get(params, consumer(client)) |> decode_response
|> decode_request_response
end end
def request_token!(params \\ [], opts \\ []) do 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 consumer(client), do: {client.consumer_key, client.consumer_secret, :hmac_sha1}
defp decode_access_response({:ok, {{_, 200, _}, _, _} = resp}) do defp decode_response({:ok, %{status_code: 200, body: body, headers: _}}) do
params = :oauth.params_decode(resp) params = Internal.params_decode(body)
token = :oauth.token(params) token = Internal.token(params)
token_secret = :oauth.token_secret(params) token_secret = Internal.token_secret(params)
{:ok, {token, token_secret}} {:ok, {token, token_secret}}
end end
defp decode_access_response({:ok, {{_, status_code, status_description}, _, _}}), do: {:error, "#{status_code} - #{status_description}"} defp decode_response({:ok, %{status_code: status_code, body: _, headers: _}}) do
defp decode_access_response({:error, {error, [_, {:inet, [:inet], error_reason}]}}), do: {:error, "#{error}: #{error_reason}"} {:error, "#{status_code}"}
defp decode_access_response(error), do: {:error, error} end
defp decode_response({:error, %{reason: reason}}) do
defp decode_request_response({:ok, {{_, 200, _}, _, _} = resp}) do {:error, "#{reason}"}
params = :oauth.params_decode(resp) end
token = :oauth.token(params) defp decode_response(error) do
token_secret = :oauth.token_secret(params) {:error, error}
{:ok, {token, token_secret}}
end 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("/" <> _path = endpoint, client), do: client.site <> endpoint
defp endpoint(endpoint, _client), do: endpoint defp endpoint(endpoint, _client), do: endpoint

14
mix.exs
View File

@ -8,25 +8,25 @@ defmodule UeberauthTwitter.Mixfile do
[app: :ueberauth_twitter, [app: :ueberauth_twitter,
version: @version, version: @version,
name: "Ueberauth Twitter Strategy", name: "Ueberauth Twitter Strategy",
package: package, package: package(),
elixir: "~> 1.1", elixir: "~> 1.1",
build_embedded: Mix.env == :prod, build_embedded: Mix.env == :prod,
start_permanent: Mix.env == :prod, start_permanent: Mix.env == :prod,
source_url: @url, source_url: @url,
homepage_url: @url, homepage_url: @url,
description: description, description: description(),
deps: deps, deps: deps(),
docs: docs] docs: docs()]
end end
def application do def application do
[applications: [:logger, :httpoison, :oauth, :ueberauth]] [applications: [:logger, :httpoison, :oauther, :ueberauth]]
end end
defp deps do defp deps do
[ [
{:httpoison, "~> 0.7"}, {:httpoison, "~> 0.7"},
{:oauth, github: "tim/erlang-oauth"}, {:oauther, "~> 1.1"},
{:poison, "~> 1.3 or ~> 2.0"}, {:poison, "~> 1.3 or ~> 2.0"},
{:ueberauth, "~> 0.2"}, {:ueberauth, "~> 0.2"},
@ -38,7 +38,7 @@ defmodule UeberauthTwitter.Mixfile do
end end
defp docs do defp docs do
[extras: docs_extras, main: "extra-readme"] [extras: docs_extras(), main: "extra-readme"]
end end
defp docs_extras do defp docs_extras do

View File

@ -10,7 +10,7 @@
"mimetype_parser": {:hex, :mimetype_parser, "0.1.0"}, "mimetype_parser": {:hex, :mimetype_parser, "0.1.0"},
"oauth": {:git, "https://github.com/tim/erlang-oauth.git", "cd31addc828179983564fd57738f1680a4a4d1ff", []}, "oauth": {:git, "https://github.com/tim/erlang-oauth.git", "cd31addc828179983564fd57738f1680a4a4d1ff", []},
"oauth2": {:hex, :oauth2, "0.5.0"}, "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]}]}, "plug": {:hex, :plug, "1.0.3", "8bbcbdaa4cb15170b9a15cb12153e8a6d9e176ce78e4c1990ea0b505b0ca24a0", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, optional: true]}]},
"poison": {:hex, :poison, "1.5.0", "f2f4f460623a6f154683abae34352525e1d918380267cdbd949a07ba57503248", [:mix], []}, "poison": {:hex, :poison, "1.5.0", "f2f4f460623a6f154683abae34352525e1d918380267cdbd949a07ba57503248", [:mix], []},
"ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5", "2e73e068cd6393526f9fa6d399353d7c9477d6886ba005f323b592d389fb47be", [:make], []}, "ssl_verify_hostname": {:hex, :ssl_verify_hostname, "1.0.5", "2e73e068cd6393526f9fa6d399353d7c9477d6886ba005f323b592d389fb47be", [:make], []},