Skip to content

Commit

Permalink
use oauth2 to simplify code
Browse files Browse the repository at this point in the history
Need waiting for ueberauth/oauth2#132 to merge
  • Loading branch information
goofansu committed Apr 2, 2019
1 parent 6f5c15b commit 1e08d55
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 48 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ end
config :ueberauth, Ueberauth,
providers: [
weixin: {Ueberauth.Strategy.Weixin,
[appid: "YOUR_APPID",
secret: "YOUR_SECRET",
redirect_uri: "https://example.com/auth/weixin/callback",
uid_field: :unionid # default is :openid
]}
[uid_field: :unionid # default is :openid]}
]

config :ueberauth, Ueberauth.Strategy.Weixin.OAuth,
client_id: "YOUR_APPID",
client_secret: "YOUR_SECRET",
redirect_uri: "https://example.com/auth/weixin/callback"
```

## Ueberauth.Auth struct
Expand Down
43 changes: 10 additions & 33 deletions lib/ueberauth/strategy/weixin.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,24 @@ defmodule Ueberauth.Strategy.Weixin do
use Ueberauth.Strategy, uid_field: :openid

alias Ueberauth.Auth.{Credentials, Extra, Info}

@auth_url "https://open.weixin.qq.com/connect/qrconnect"
@token_url "https://api.weixin.qq.com/sns/oauth2/access_token"
alias Ueberauth.Strategy.Weixin.OAuth

def handle_request!(conn) do
appid = option(conn, :appid)
redirect_uri = option(conn, :redirect_uri)

url =
"#{@auth_url}?appid=#{appid}&redirect_uri=#{redirect_uri}&response_type=code&scope=snsapi_login#wechat_redirect"

url = OAuth.authorize_url!()
redirect!(conn, url)
end

def handle_callback!(%Plug.Conn{params: %{"code" => code}} = conn) do
appid = option(conn, :appid)
secret = option(conn, :secret)
client = OAuth.get_token!(code: code)

url =
"#{@token_url}?appid=#{appid}&secret=#{secret}&code=#{code}&grant_type=authorization_code"

case HTTPoison.get!(url).body |> Ueberauth.json_library().decode!() do
%{"access_token" => access_token, "openid" => openid} ->
fetch_user(conn, access_token, openid)
case OAuth.fetch_user(client) do
{:ok, user} ->
conn
|> put_private(:weixin_user, user)
|> put_private(:weixin_token, client.token)

%{"errcode" => errcode, "errmsg" => errmsg} ->
set_errors!(conn, [error(errcode, errmsg)])
{:error, error} ->
set_errors!(conn, [error(error.code, error.reason)])
end
end

Expand Down Expand Up @@ -63,20 +54,6 @@ defmodule Ueberauth.Strategy.Weixin do
}
end

defp fetch_user(conn, token, openid) do
url = "https://api.weixin.qq.com/sns/userinfo?access_token=#{token}&openid=#{openid}"

case HTTPoison.get!(url).body |> Ueberauth.json_library().decode!() do
%{"errcode" => errcode, "errmsg" => errmsg} ->
set_errors!(conn, [error(errcode, errmsg)])

body ->
conn
|> put_private(:weixin_token, token)
|> put_private(:weixin_user, body)
end
end

defp option(conn, key) do
default = Keyword.get(default_options(), key)

Expand Down
74 changes: 74 additions & 0 deletions lib/ueberauth/strategy/weixin/oauth.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
defmodule Ueberauth.Strategy.Weixin.OAuth do
@moduledoc false

use OAuth2.Strategy

def new do
:ueberauth
|> Application.fetch_env!(__MODULE__)
|> Keyword.merge(config())
|> OAuth2.Client.new()
|> put_serializer("text/plain", Jason)
end

defp config do
[
strategy: __MODULE__,
site: "https://api.weixin.qq.com",
authorize_url: "https://open.weixin.qq.com/connect/qrconnect",
token_url: "https://api.weixin.qq.com/sns/oauth2/access_token"
]
end

def authorize_url!(params \\ []) do
new()
|> OAuth2.Client.authorize_url!(params)
end

def get_token!(params \\ [], headers \\ []) do
new()
|> OAuth2.Client.get_token!(params, headers)
end

def fetch_user(%{token: token} = client) do
params = %{
access_token: token.access_token,
openid: token.other_params["openid"]
}

case OAuth2.Client.get!(client, "/sns/userinfo", [], params: params) do
%{body: %{"errcode" => errcode, "errmsg" => errmsg}} ->
{:error, %{code: errcode, reason: errmsg}}

%{body: body} ->
{:ok, body}
end
end

@impl true
def authorize_url(client, params) do
client
|> put_param(:response_type, "code")
|> put_param(:scope, "snsapi_login")
|> put_param(:appid, client.client_id)
|> put_param(:redirect_uri, client.redirect_uri)
|> merge_params(params)
end

@impl true
def get_token(client, params, headers) do
{code, params} = Keyword.pop(params, :code, client.params["code"])

unless code do
raise OAuth2.Error, reason: "Missing required key `code` for `#{inspect(__MODULE__)}`"
end

client
|> put_param(:grant_type, "authorization_code")
|> put_param(:code, code)
|> put_param(:appid, client.client_id)
|> put_param(:secret, client.client_secret)
|> merge_params(params)
|> put_headers(headers)
end
end
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ defmodule UeberauthWeixin.MixProject do
defp deps do
[
{:ueberauth, "~> 0.6"},
{:httpoison, "~> 1.0"},
{:jason, "~> 1.0"},
{:oauth2, "~> 1.0"},
{:ex_doc, "~> 0.19", only: :dev, runtime: false}
]
end
Expand Down
18 changes: 9 additions & 9 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
%{
"certifi": {:hex, :certifi, "2.5.1", "867ce347f7c7d78563450a18a6a28a8090331e77fa02380b4a21962a65d36ee5", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
"certifi": {:hex, :certifi, "2.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [:rebar3], [{:parse_trans, "3.2.0", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
"earmark": {:hex, :earmark, "1.3.2", "b840562ea3d67795ffbb5bd88940b1bed0ed9fa32834915125ea7d02e35888a5", [:mix], [], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.19.3", "3c7b0f02851f5fc13b040e8e925051452e41248f685e40250d7e40b07b9f8c10", [:mix], [{:earmark, "~> 1.2", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, 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"},
"httpoison": {:hex, :httpoison, "1.5.0", "71ae9f304bdf7f00e9cd1823f275c955bdfc68282bc5eb5c85c3a9ade865d68e", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"ex_doc": {:hex, :ex_doc, "0.20.0", "47ef7d09d990fa4a4373c96c4bdff846836f011e88dd7695d31f54ec035ff38e", [:mix], [{:earmark, "~> 1.3", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.10", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
"hackney": {:hex, :hackney, "1.13.0", "24edc8cd2b28e1c652593833862435c80661834f6c9344e84b6a2255e7aeef03", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.2", [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.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
"idna": {:hex, :idna, "5.1.2", "e21cb58a09f0228a9e0b95eaa1217f1bcfc31a1aaa6e1fdf2f53a33f7dbd9494", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
"makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
"makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
"mime": {:hex, :mime, "1.3.1", "30ce04ab3175b6ad0bdce0035cba77bba68b813d523d1aac73d9781b4d193cf8", [:mix], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
"nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"},
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
"oauth2": {:hex, :oauth2, "1.0.0", "7ae134c369bb9f7e96ed9404d12f34e938daa14745f1601876526599be4c80f2", [:mix], [{:hackney, "~> 1.13.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
"parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"},
"plug": {:hex, :plug, "1.8.0", "9d2685cb007fe5e28ed9ac27af2815bc262b7817a00929ac10f56f169f43b977", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm"},
"plug_crypto": {:hex, :plug_crypto, "1.0.0", "18e49317d3fa343f24620ed22795ec29d4a5e602d52d1513ccea0b07d8ea7d4d", [:mix], [], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
"ueberauth": {:hex, :ueberauth, "0.6.1", "9e90d3337dddf38b1ca2753aca9b1e53d8a52b890191cdc55240247c89230412", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},
}

0 comments on commit 1e08d55

Please sign in to comment.