diff --git a/lib/coherence_assent/strategies/oauth2.ex b/lib/coherence_assent/strategies/oauth2.ex index 9d42417..7347b78 100644 --- a/lib/coherence_assent/strategies/oauth2.ex +++ b/lib/coherence_assent/strategies/oauth2.ex @@ -29,11 +29,7 @@ defmodule CoherenceAssent.Strategy.OAuth2 do state |> check_state(client, params) |> get_access_token(config, params) - |> get_user(config[:user_url]) - |> case do - {:ok, user} -> {:ok, %{conn: conn, client: client, user: user}} - {:error, error} -> {:error, %{conn: conn, error: error}} - end + |> get_user_with_client(config[:user_url], conn) end @doc false @@ -82,6 +78,17 @@ defmodule CoherenceAssent.Strategy.OAuth2 do end def get_user({:error, error}, _user_url), do: {:error, error} + defp get_user_with_client({:ok, client}, user_url, conn) do + {:ok, client} + |> get_user(user_url) + |> case do + {:ok, user} -> {:ok, %{conn: conn, client: client, user: user}} + {:error, error} -> {:error, %{conn: conn, error: error}} + end + end + defp get_user_with_client({:error, error}, _user_url, conn), + do: {:error, %{conn: conn, error: error}} + defp process_user_response({:ok, %OAuth2.Response{body: user}}), do: {:ok, user} defp process_user_response({:error, %OAuth2.Response{status_code: 401}}), do: {:error, %CoherenceAssent.RequestError{message: "Unauthorized token"}} diff --git a/test/coherence_assent/strategies/basecamp_test.exs b/test/coherence_assent/strategies/basecamp_test.exs index 1aa1bae..db58ed8 100644 --- a/test/coherence_assent/strategies/basecamp_test.exs +++ b/test/coherence_assent/strategies/basecamp_test.exs @@ -4,6 +4,8 @@ defmodule CoherenceAssent.BasecampTest do import OAuth2.TestHelpers alias CoherenceAssent.Strategy.Basecamp + @access_token "access_token" + setup %{conn: conn} do conn = session_conn(conn) @@ -50,10 +52,12 @@ defmodule CoherenceAssent.BasecampTest do }] Bypass.expect_once bypass, "POST", "/authorization/token", fn conn -> - send_resp(conn, 200, Poison.encode!(%{access_token: "access_token"})) + send_resp(conn, 200, Poison.encode!(%{access_token: @access_token})) end Bypass.expect_once bypass, "GET", "/authorization.json", fn conn -> + assert_access_token_in_header conn, @access_token + user = %{"expires_at" => "2012-03-22T16:56:48-05:00", "identity" => %{ "id" => 9999999, diff --git a/test/coherence_assent/strategies/facebook_test.exs b/test/coherence_assent/strategies/facebook_test.exs index 9ebd67a..16bb51c 100644 --- a/test/coherence_assent/strategies/facebook_test.exs +++ b/test/coherence_assent/strategies/facebook_test.exs @@ -4,6 +4,8 @@ defmodule CoherenceAssent.Strategy.FacebookTest do import OAuth2.TestHelpers alias CoherenceAssent.Strategy.Facebook + @access_token "access_token" + setup %{conn: conn} do conn = session_conn(conn) @@ -31,14 +33,16 @@ defmodule CoherenceAssent.Strategy.FacebookTest do assert {:ok, body, _conn} = Plug.Conn.read_body(conn) assert body =~ "scope=email" - send_resp(conn, 200, Poison.encode!(%{"access_token" => "access_token"})) + send_resp(conn, 200, Poison.encode!(%{"access_token" => @access_token})) end Bypass.expect_once bypass, "GET", "/me", fn conn -> + assert_access_token_in_header conn, @access_token + conn = Plug.Conn.fetch_query_params(conn) assert conn.params["fields"] == "name,email" - assert conn.params["appsecret_proof"] == Base.encode16(:crypto.hmac(:sha256, "", "access_token"), case: :lower) + assert conn.params["appsecret_proof"] == Base.encode16(:crypto.hmac(:sha256, "", @access_token), case: :lower) user = %{name: "Dan Schultzer", email: "foo@example.com", diff --git a/test/coherence_assent/strategies/github_test.exs b/test/coherence_assent/strategies/github_test.exs index 4b1f835..de34be5 100644 --- a/test/coherence_assent/strategies/github_test.exs +++ b/test/coherence_assent/strategies/github_test.exs @@ -4,6 +4,8 @@ defmodule CoherenceAssent.Strategy.GithubTest do import OAuth2.TestHelpers alias CoherenceAssent.Strategy.Github + @access_token "access_token" + setup %{conn: conn} do conn = session_conn(conn) @@ -28,10 +30,12 @@ defmodule CoherenceAssent.Strategy.GithubTest do test "normalizes data", %{conn: conn, config: config, params: params, bypass: bypass} do Bypass.expect_once bypass, "POST", "/login/oauth/access_token", fn conn -> - send_resp(conn, 200, Poison.encode!(%{access_token: "access_token"})) + send_resp(conn, 200, Poison.encode!(%{access_token: @access_token})) end Bypass.expect_once bypass, "GET", "/user", fn conn -> + assert_access_token_in_header conn, @access_token + user = %{ login: "octocat", id: 1, @@ -68,6 +72,8 @@ defmodule CoherenceAssent.Strategy.GithubTest do end Bypass.expect_once bypass, "GET", "/user/emails", fn conn -> + assert_access_token_in_header conn, @access_token + emails = [ %{ email: "octocat@github.com", diff --git a/test/coherence_assent/strategies/google_test.exs b/test/coherence_assent/strategies/google_test.exs index 9ba5c0b..6fbe9a7 100644 --- a/test/coherence_assent/strategies/google_test.exs +++ b/test/coherence_assent/strategies/google_test.exs @@ -4,6 +4,8 @@ defmodule CoherenceAssent.GoogleTest do import OAuth2.TestHelpers alias CoherenceAssent.Strategy.Google + @access_token "access_token" + setup %{conn: conn} do conn = session_conn(conn) @@ -28,10 +30,12 @@ defmodule CoherenceAssent.GoogleTest do test "normalizes data", %{conn: conn, config: config, params: params, bypass: bypass} do Bypass.expect_once bypass, "POST", "/o/oauth2/token", fn conn -> - send_resp(conn, 200, Poison.encode!(%{access_token: "access_token"})) + send_resp(conn, 200, Poison.encode!(%{access_token: @access_token})) end Bypass.expect_once bypass, "GET", "/people/me/openIdConnect", fn conn -> + assert_access_token_in_header conn, @access_token + user = %{"kind" => "plus#personOpenIdConnect", "gender" => "", "sub" => "1", diff --git a/test/coherence_assent/strategies/oauth2_test.exs b/test/coherence_assent/strategies/oauth2_test.exs index e837b03..89b6c92 100644 --- a/test/coherence_assent/strategies/oauth2_test.exs +++ b/test/coherence_assent/strategies/oauth2_test.exs @@ -4,6 +4,8 @@ defmodule CoherenceAssent.Strategy.OAuth2Test do import OAuth2.TestHelpers alias CoherenceAssent.Strategy.OAuth2, as: OAuth2Strategy + @access_token "access_token" + setup %{conn: conn} do conn = session_conn(conn) @@ -31,10 +33,12 @@ defmodule CoherenceAssent.Strategy.OAuth2Test do test "normalizes data", %{conn: conn, config: config, params: params, bypass: bypass} do Bypass.expect_once bypass, "POST", "/oauth/token", fn conn -> - send_resp(conn, 200, Poison.encode!(%{access_token: "access_token"})) + send_resp(conn, 200, Poison.encode!(%{access_token: @access_token})) end Bypass.expect_once bypass, "GET", "/api/user", fn conn -> + assert_access_token_in_header conn, @access_token + user = %{name: "Dan Schultzer", email: "foo@example.com", uid: "1"} Plug.Conn.resp(conn, 200, Poison.encode!(user)) end @@ -71,7 +75,7 @@ defmodule CoherenceAssent.Strategy.OAuth2Test do config = Keyword.put(config, :user_url, nil) Bypass.expect_once bypass, "POST", "/oauth/token", fn conn -> - send_resp(conn, 200, Poison.encode!(%{access_token: "access_token"})) + send_resp(conn, 200, Poison.encode!(%{access_token: @access_token})) end expected = %CoherenceAssent.ConfigurationError{message: "No user URL set"} @@ -84,7 +88,7 @@ defmodule CoherenceAssent.Strategy.OAuth2Test do config = Keyword.put(config, :user_url, "http://localhost:8888/api/user") Bypass.expect_once bypass, "POST", "/oauth/token", fn conn -> - send_resp(conn, 200, Poison.encode!(%{access_token: "access_token"})) + send_resp(conn, 200, Poison.encode!(%{access_token: @access_token})) end expected = %OAuth2.Error{reason: :econnrefused} @@ -95,10 +99,11 @@ defmodule CoherenceAssent.Strategy.OAuth2Test do test "user url unauthorized access token", %{conn: conn, config: config, params: params, bypass: bypass} do Bypass.expect_once bypass, "POST", "/oauth/token", fn conn -> - send_resp(conn, 200, Poison.encode!(%{access_token: "access_token"})) + send_resp(conn, 200, Poison.encode!(%{access_token: @access_token})) end Bypass.expect_once bypass, "GET", "/api/user", fn conn -> + assert_access_token_in_header conn, @access_token Plug.Conn.resp(conn, 401, Poison.encode!(%{"error" => "Unauthorized"})) end diff --git a/test/coherence_assent/strategies/vk_test.exs b/test/coherence_assent/strategies/vk_test.exs index b1825e7..b0da113 100644 --- a/test/coherence_assent/strategies/vk_test.exs +++ b/test/coherence_assent/strategies/vk_test.exs @@ -4,6 +4,8 @@ defmodule CoherenceAssent.VKTest do import OAuth2.TestHelpers alias CoherenceAssent.Strategy.VK + @access_token "access_token" + setup %{conn: conn} do conn = session_conn(conn) @@ -33,15 +35,17 @@ defmodule CoherenceAssent.VKTest do assert {:ok, body, _conn} = Plug.Conn.read_body(conn) assert body =~ "scope=email" - send_resp(conn, 200, Poison.encode!(%{"access_token" => "access_token", "email" => "lindsay.stirling@example.com"})) + send_resp(conn, 200, Poison.encode!(%{"access_token" => @access_token, "email" => "lindsay.stirling@example.com"})) end Bypass.expect_once bypass, "GET", "/method/users.get", fn conn -> + assert_access_token_in_header conn, @access_token + conn = Plug.Conn.fetch_query_params(conn) assert conn.params["fields"] == "uid,first_name,last_name,photo_200,screen_name,verified" assert conn.params["v"] == "5.69" - assert conn.params["access_token"] == "access_token" + assert conn.params["access_token"] == @access_token users = [%{"id" => 210700286, "first_name" => "Lindsay", diff --git a/test/support/test_helpers.ex b/test/support/test_helpers.ex index a827d0e..ed3c713 100644 --- a/test/support/test_helpers.ex +++ b/test/support/test_helpers.ex @@ -1,5 +1,20 @@ defmodule OAuth2.TestHelpers do + @spec bypass_server(%Bypass{}) :: String.t def bypass_server(%Bypass{port: port}) do "http://localhost:#{port}" end + + @spec assert_access_token_in_header(Plug.Conn.t, String.t) :: true | no_return + def assert_access_token_in_header(conn, token) do + expected = {"authorization", "Bearer #{token}"} + + case Enum.find(conn.req_headers, &(elem(&1, 0) == "authorization")) do + ^expected -> + true + {"authorization", "Bearer " <> found_token} -> + ExUnit.Assertions.flunk("Expected bearer token #{token}, but received #{found_token}") + _ -> + ExUnit.Assertions.flunk("No bearer token found in headers") + end + end end