pow-auth / pow_assent

Multi-provider authentication for your Pow enabled app
https://powauth.com
MIT License
321 stars 50 forks source link

Get a profile picture from Google Oauth #161

Closed jagoanmamah closed 4 years ago

jagoanmamah commented 4 years ago

How to get a profile picture from Google Oauth?

danschultzer commented 4 years ago

It's part of the claims, and the process is described in the docs: https://hexdocs.pm/pow_assent/0.4.6/README.html#populate-fields

So you would do something like this:

defmodule MyApp.Users.User do
  use Ecto.Schema
  use Pow.Ecto.Schema
  use PowAssent.Ecto.Schema

  schema "users" do
    field :picture, :string

    pow_user_fields()

    timestamps()
  end

  def user_identity_changeset(user_or_changeset, user_identity, attrs, user_id_attrs) do
    user_or_changeset
    |> Ecto.Changeset.cast(attrs, [:picture])
    |> pow_assent_user_identity_changeset(user_identity, attrs, user_id_attrs)
  end
end
jagoanmamah commented 4 years ago

I meant how to get an avatar link from Google like this

a0943266-99d3-4179-90ca-106cf8143973

Does pow assent only get email address from Google Oauth?

danschultzer commented 4 years ago

picture is the avatar URL.

See these: https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims https://developers.google.com/identity/protocols/oauth2/openid-connect#an-id-tokens-payload

You can see all values that the Assent Google integration provides in the source: https://github.com/pow-auth/assent/blob/v0.1.8/lib/assent/strategies/google.ex#L33-L46

jagoanmamah commented 4 years ago

I got null in the picture column

jagoanmamah commented 4 years ago

SOLVED

defmodule MyApp.UserIdentities do
  use PowAssent.Ecto.UserIdentities.Context,
    repo: MyApp.Repo,
    user: MyApp.Users.User

  def upsert(user, user_identity_params) do
    MyApp.Repo.transaction fn ->
      case pow_assent_upsert(user, user_identity_params) do
        {:ok, user}     -> update_user(user, user_identity_params)
        {:error, error} -> {:error, error}
      end
    end
  end

  defp update_user(user, user_identity_params) do
    user
    |> MyApp.Users.User.changeset(user_identity_params)
    |> MyApp.Repo.update()
  end
end
danschultzer commented 4 years ago

When an identity is created with a user, the create_user method is called which will add the picture using the changeset above. This won't happen for users who already exist.

There's two issues in the approach you posted:

  1. user_identity_params only have user identity values namely uid, provider, and token. https://github.com/pow-auth/pow_assent/pull/160 would solve this though.

  2. pow_assent_upsert returns the identity and not the user. So the upsert method should return the identity as well. You are currently passing the user identity to the user changeset.