diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c376a9..acaf3aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## v0.1.19 (TBA) * Updated docs to detail `:inets` compilation +* `Assent.OAuth2.authorize_url/1` now returns the state, if defined, from `authorization_params` ## v0.1.18 (2020-11-08) diff --git a/lib/assent/strategies/oauth2.ex b/lib/assent/strategies/oauth2.ex index f333a5c..67d8bba 100644 --- a/lib/assent/strategies/oauth2.ex +++ b/lib/assent/strategies/oauth2.ex @@ -84,27 +84,35 @@ defmodule Assent.Strategy.OAuth2 do with {:ok, redirect_uri} <- Config.fetch(config, :redirect_uri), {:ok, site} <- Config.fetch(config, :site), {:ok, client_id} <- Config.fetch(config, :client_id) do - state = gen_state() - params = authorization_params(config, client_id, state, redirect_uri) + params = authorization_params(config, client_id, redirect_uri) authorize_url = Config.get(config, :authorize_url, "/oauth/authorize") url = Helpers.to_url(site, authorize_url, params) - {:ok, %{url: url, session_params: %{state: state}}} + {:ok, %{url: url, session_params: %{state: params[:state]}}} end end - defp authorization_params(config, client_id, state, redirect_uri) do + defp authorization_params(config, client_id, redirect_uri) do params = Config.get(config, :authorization_params, []) [ response_type: "code", client_id: client_id, - state: state, + state: gen_state(), redirect_uri: redirect_uri] |> Keyword.merge(params) |> List.keysort(0) end + defp gen_state do + 24 + |> :crypto.strong_rand_bytes() + |> :erlang.bitstring_to_list() + |> Enum.map(fn x -> :erlang.integer_to_binary(x, 16) end) + |> Enum.join() + |> String.downcase() + end + @doc """ Callback phase for generating access token with authorization code and fetch user data. Returns a map with access token in `:token` and user data in @@ -348,13 +356,4 @@ defmodule Assent.Strategy.OAuth2 do defp process_user_response({:ok, %HTTPResponse{status: 200, body: user}}), do: {:ok, user} defp process_user_response({:error, %HTTPResponse{status: 401}}), do: {:error, %RequestError{message: "Unauthorized token"}} defp process_user_response(any), do: process_response(any) - - defp gen_state do - 24 - |> :crypto.strong_rand_bytes() - |> :erlang.bitstring_to_list() - |> Enum.map(fn x -> :erlang.integer_to_binary(x, 16) end) - |> Enum.join() - |> String.downcase() - end end diff --git a/test/assent/strategies/oauth2_test.exs b/test/assent/strategies/oauth2_test.exs index 6a15ccd..b42d34c 100644 --- a/test/assent/strategies/oauth2_test.exs +++ b/test/assent/strategies/oauth2_test.exs @@ -57,6 +57,16 @@ defmodule Assent.Strategy.OAuth2Test do assert url =~ "http://localhost:#{bypass.port}/oauth/authorize?client_id=#{@client_id}&redirect_uri=http%3A%2F%2Flocalhost%3A4000%2Fauth%2Fcallback&response_type=code&state=#{state}" end + test "authorize_url/2 with state in authorization_param", %{config: config} do + assert {:ok, %{session_params: %{state: state}}} = + config + |> Keyword.put(:client_id, @client_id) + |> Keyword.put(:authorization_params, state: "state_test_value") + |> OAuth2.authorize_url() + + assert state == "state_test_value" + end + describe "callback/2" do setup %{config: config} do config =