hawkyre

hawkyre

Server-side Elixir request to Google Cloud's OAuth endpoint fails in bare Elixir app but succeeds in Phoenix app with same package even though the request is exactly the same

I’ve already asked the question in the package’s hex module repo but I’m not sure I can expect an answer soon and I really need this to be done ASAP so I’m resorting to you guys.

I’m generating a google oauth user code in my Next.js frontend using this react oauth package , which is then sent to my server at /auth/google/callback and processed to obtain the user’s data.

This is the client’s code:

const googleLogin = useGoogleLogin({
  flow: 'auth-code',
  redirect_uri: `${process.env.NEXT_PUBLIC_SERVER_URL}/auth/google/callback`,
  ux_mode: 'popup',
  scope: 'email profile openid',
  onSuccess: async (codeResponse) => {
    console.log(codeResponse);

    const tokens = await getAxiosInstance().post(
      `${process.env.NEXT_PUBLIC_SERVER_URL}/auth/google/callback`,
      {
        code: codeResponse.code,
      }
    );

    console.log(tokens);
  },
  onError: (errorResponse) => console.log(errorResponse),
});

This is the server’s code #1 (I’ve copy pasted the relevant code from the elixir-auth-google package into my app to see if it changed anything but it doesn’t):

post "/callback" do
  conn = Plug.Conn.fetch_session(conn)

  {conn, status, body} =
    case conn.assigns[:user_id] do
      _ ->
        code = Map.get(conn.body_params, "code", "") |> IO.inspect()

        {:ok, token} =
          get_token(code, nil)
          |> IO.inspect()

        {:ok, profile} = ElixirAuthGoogle.get_user_profile(token.access_token) |> IO.inspect()

        IO.inspect([code, token, profile])

        Responses.r200(conn, %{})
    end

  send_resp(conn, status, body)
end

@google_token_url "https://oauth2.googleapis.com/token"

def get_token(code, redirect_uri) do
  # Build the request body
  body =
    %{
      client_id: "...",
      client_secret: "...",
      redirect_uri: "http://localhost:4000/auth/google/callback",
      grant_type: "authorization_code",
      code: code,
      scope: "email profile openid"
    }
    |> Jason.encode!()

  headers = [
    {"Content-Type", "application/json"}
  ]

  # Make the HTTP POST request
  case HTTPoison.post(@google_token_url, body, headers) do
    {:ok, %HTTPoison.Response{status_code: 200, body: response_body}} ->
      # Handle the response, typically converting JSON to an internal format
      case Jason.decode(response_body) do
        {:ok, decoded} -> {:ok, decoded}
        {:error, reason} -> {:error, reason}
      end

    {:ok, %HTTPoison.Response{status_code: status} = res} ->
      IO.inspect(res)
      {:error, "Failed to retrieve token, status code: #{status}"}

    {:error, reason} ->
      {:error, reason}
  end
end

And this is the server code #2, using the library:

post "/callback" do
  conn = Plug.Conn.fetch_session(conn)

  {conn, status, body} =
    case conn.assigns[:user_id] do
      _ ->
        code = Map.get(conn.body_params, "code", "") |> IO.inspect()

        {:ok, token} =
          ElixirAuthGoogle.get_token(code, conn)
          |> IO.inspect()

        {:ok, profile} = ElixirAuthGoogle.get_user_profile(token.access_token) |> IO.inspect()

        IO.inspect([code, token, profile])

        Responses.r200(conn, %{})
    end

  send_resp(conn, status, body)
end

Something very interesting happens. When I use the library as-is in my Elixir, the error is that the OAuth client is not found, even though the envvars are very much present BUT the only difference is that the variable has an extra \r at the end of itself. But If I recompile the library with hardcoded values or use the custom function that is based on the library where I also hardcode the values, the error instead is a redirect_uri_mismatch. However, I have checked 1000 times that the URL is the same, waited days between checking and created new OAuth clients, but the error persists.

Now, when I follow the elixir-auth-google guide and create the client with a phoenix app, the thing just works without modifying the library at all. No invalid client, no redirect_uri_mismatch, and I’ve checked again 1000 times that the values are exactly the same in both. If you look at the issue I opened on their repo, the requests sent to google are exactly the same, yet the bare Elixir one fails and the Phoenix one doesn’t.

Could this be due to how I’m generating the user code in the frontend? Is there any difference in how JSON is parsed and sent over in Phoenix versus no Phoenix when using HTTPoison? Any help or advice is appreciated.

Where Next?

Popular in Questions Top

aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
tduccuong
Hi, is there any work on GUI with Elixir, that is similar to Electron/Javascript? My idea is to bundle Phoenix and BEAM into a single se...
New
Phillipp
Hey, I have a NanoPi-M3 and try to install Elixir on their Ubuntu image. I followed the Raspberry Pi installation instructions from the ...
New
makeitrein
Hey all, just started picking up Elixir last week and am writing a scraper as a learning project. Baby step #1 is extracting the number ...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers' Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
idi527
I’ve been re-reading swift book again and noticed that multiline strings there don’t have a trailing line break, unlike in elixir iex(2)...
New

Other popular topics Top

JDanielMartinez
Hi! May someone helps me, please! I have two apps into an umbrella project: the first one is Database, which manages queries, and the se...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
chrismccord
As promised, the first release candidate of Phoenix 1.3.0 is out! This release focuses on code generators with improved project structure...
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
AstonJ
by Lance Halvorsen Elixir and Phoenix are generating tremendous excitement as an unbeatable platform for building modern web application...
460 27162 124
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New

We're in Beta

About us Mission Statement