pow-auth / assent

Multi-provider framework in Elixir
https://powauth.com
MIT License
406 stars 47 forks source link

Facebook user info is not decoded from JSON #151

Open JohnDoneth opened 6 months ago

JohnDoneth commented 6 months ago

It looks like the result for /me for Facebook is returning a JSON payload but the payload is never decoded and passed to normalize where it fails. I don't believe this a configuration issue but I could be wrong. I've included my config and some of the dbg trail below:

config #=> [
  strategy: Assent.Strategy.Facebook,
  base_url: "https://graph.facebook.com/v4.0",
  authorize_url: "https://www.facebook.com/v4.0/dialog/oauth",
  token_url: "/oauth/access_token",
  user_url: "/me",
  authorization_params: [scope: "email"],
  user_url_request_fields: "email,name,first_name,last_name,middle_name,link",
  auth_method: :client_secret_post,
  session_params: %{state: "b12f74c55b98953535c75f3143cd8d4e475f8c3b2a"},
  redirect_uri: "https://local.host:5301/auth/facebook/callback",
  client_id: "<redacted>",
  client_secret: "<redacted>",
  redirect_path: "/auth/facebook/callback"
]
|> process_user_response() #=> {:ok,
 "{\"email\":\"doneth7\\u0040me.com\",\"name\":\"John Doneth\",\"first_name\":\"John\",\"last_name\":\"Doneth\",\"id\":\"7425858337461382\"}"}
** (FunctionClauseError) no function clause matching in Access.get/3
    (elixir 1.16.1) lib/access.ex:307: Access.get("{\"email\":\"doneth7\\u0040me.com\",\"name\":\"John Doneth\",\"first_name\":\"John\",\"last_name\":\"Doneth\",\"id\":\"7425858337461382\"}", "id", nil)
    (assent 0.2.9) lib/assent/strategies/facebook.ex:92: Assent.Strategy.Facebook.normalize/2
rubynho commented 1 week ago

Hey @JohnDoneth! Did you discover anything to solve the issue? Having the same problem.

JohnDoneth commented 1 week ago

Hey @JohnDoneth! Did you discover anything to solve the issue? Having the same problem.

@rubynho Yes, I forked the Assent.Strategy.Facebook module and decoded the payload with Jason.

@impl true
  def fetch_user(config, access_token) do
    with {:ok, fields} <- Config.fetch(config, :user_url_request_fields),
         {:ok, client_secret} <- Config.fetch(config, :client_secret) do
      params = [
        appsecret_proof: appsecret_proof(access_token, client_secret),
        fields: fields,
        access_token: access_token["access_token"]
      ]

      # This decoding from JSON is the only difference between this module and
      # the original from Assent.
      case OAuth2.fetch_user(config, access_token, params) do
        {:ok, json} -> {:ok, Jason.decode!(json)}
        {:error, error} -> {:error, error}
      end
    end
  end