Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does this work with barebones Elixir / no Phoenix? #123

Open
hawkyre opened this issue Apr 21, 2024 · 2 comments
Open

Does this work with barebones Elixir / no Phoenix? #123

hawkyre opened this issue Apr 21, 2024 · 2 comments
Labels
help wanted Extra attention is needed question Further information is requested technical user-feedback

Comments

@hawkyre
Copy link

hawkyre commented Apr 21, 2024

I'm trying to use this in a project without Phoenix and, with the same exact credentials, it will work on the Phoenix project but not on the Elixir one. It keeps throwing the "invalid_client" and "The OAuth client was not found." error after I request the token. I am running the server and client separately.

Here's the code:

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

  code = Map.get(conn.body_params, "code", "")

  {:ok, token} =
    ElixirAuthGoogle.get_token(
      code,
      "#{Application.get_env(:root, :frontend_url)}"
    )
    |> IO.inspect()

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

  ...
end

Am I doing something wrong? This is the only relevant code to the project, and it is throwing after ElixirAuthGoogle.get_token/2

@nelsonic
Copy link
Member

Great question. ❓ ❤️
The quick answer is yes. 👍
But we only tend to use it with Phoenix so we haven't written an example without it. 🙃
Please confirm your Elixir App has access to the required environment variable. 🔑

@nelsonic nelsonic added help wanted Extra attention is needed question Further information is requested user-feedback technical labels Apr 22, 2024
@hawkyre
Copy link
Author

hawkyre commented Apr 22, 2024

Yes, it does. The request is done successfully and I've compared the payload and it seems to be the same in both the phoenix and the bare elixir, but the phoenix one does return the proper profile data while the elixir can't exchange the user code for the token. Could it be the JSON parsing somehow being different? I'm also using HTTPoison.

Btw, if it's any helpful, I was testing yesterday and even though the variables were being added as I could see in the request, I modified the module code to have the client id and secret be static and that instead throws a redirect_uri_mismatch even though the redirect uri is added to the GC project.

I also wrote a different function with the same structure as the module and this one does throw the redirect_uri_mismatch as well. Here's the code:

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

  headers = []

  # 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

Here are the response's request objects in both projects, copy pasted straight from the raw response (I'm pretty sure they are the same):

Bare elixir:

request: %HTTPoison.Request{
    method: :post,
    url: "https://oauth2.googleapis.com/token",
    headers: [],
    body: "{\"code\":\"code\",\"client_id\":\"client-id\",\"client_secret\":\"client-secret\",\"grant_type\":\"authorization_code\",\"redirect_uri\":\"http://localhost:4000/auth/google/callback\"}",
    params: %{},
    options: []
  }

Phoenix

request: %HTTPoison.Request{
     method: :post,
     url: "https://oauth2.googleapis.com/token",
     headers: [],
     body: "{\"code\":\"code\",\"client_id\":\"client-id\",\"client_secret\":\"client-secret\",\"redirect_uri\":\"http://localhost:4000/auth/google/callback\",\"grant_type\":\"authorization_code\"}",
     params: %{},
     options: []
   }

I can also provide how I'm treating the code in the Next.js frontend (I'm using a popup instead of a redirect):

const googleLogin = useGoogleLogin({
  flow: 'auth-code',
  redirect_uri: `${process.env.NEXT_PUBLIC_SERVER_URL}/auth/google/callback`,
  ux_mode: 'popup',
  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),
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed question Further information is requested technical user-feedback
Projects
None yet
Development

No branches or pull requests

2 participants