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

Add a a way to use the same provider strat more than once with different client ids. #204

Open
mitcheaton1 opened this issue Jan 23, 2021 · 4 comments

Comments

@mitcheaton1
Copy link

mitcheaton1 commented Jan 23, 2021

We use the google oauth strategy for web, and for ios, but the client ids are different for each, and no secret is needed for ios. We used two different provider ids [google, google_ios] in our config to differentiate how to store the secrets for client id and secret which come form env vars.

The issue is PowAssent.Plug.callback_upsert tries to insert a new user in the database schema if the provider is different, and it fails as the user already exists as we have a unique constraint on email.

the call @SPEC callback_upsert(Conn.t(), binary(), map(), binary()) calls another method maybe_authenticate() which calls authenticate in the same module that takes the provider to see if a user exists.

I forked and temp fixed this by just converting the provider var to be google if provider comes in as google_ios and it works like a charm. not sure how a permanent fix would look to use 2 providers with the same strat, without breaking PowAssent.Plug.callback_upsert

The error was user already exists with this email

@danschultzer
Copy link
Collaborator

danschultzer commented Jan 31, 2021

If I understand this correctly, the only difference in with the two strategies is the client id (and no client secret for ios)? You use PowAssent in the API with the ios config, and in web with the web config?

In that case, it's best handled by dynamically updating the client id depending if the API or the web interface is accessed. You can use PowAssent.Plug.merge_provider_config/3 helper for this, and handle it in a plug:

# config/prod.exs
config :my_app_web, google_ios_client_id: "GOOGLE_CLIENT_ID"

# my_app_web/router.ex

  pipeline :api do
    # ...
    plug :put_google_ios_client_id
  end

  defp put_google_ios_client_id(conn, _opts) do
    PowAssent.Plug.merge_provider_config(:google, client_id: Application.get_env(:my_app_web, :google_ios_client_id), client_secret: nil)
  end

Above is untested, but should give you an idea of how you just need to adjust the config when the request comes in.

@mitcheaton1
Copy link
Author

we will give this a shot. thanks dan!

@sherbondy
Copy link
Contributor

Hey @danschultzer happy I happened across this issue.

I'm working on adding "incremental auth" support for a Pow Assent powered web application, and figure merge_provider_config would also be the recommended path for achieving such a thing?

Eg the scenario in mind is:

  • On first signup users can join via Google OAuth with minimal scopes provided (just basic profile info scope)
  • Later from a settings page the user can "incrementally authorize" to grant additional scopes to the application (eg calendar access).

In this case I was initially scratching my head looking for a way to dynamically change the config for the Google provider, similar to this issue.

Would you be keen if I wrote up a quick community guides PR for the docs to elaborate on this? (name TBD, maybe something like "Supporting Incremental Authorization and other dynamic per-request configuration" re: how to effectively use merge_provider_config ?)

@danschultzer
Copy link
Collaborator

danschultzer commented Oct 12, 2021

I'm working on adding "incremental auth" support for a Pow Assent powered web application, and figure merge_provider_config would also be the recommended path for achieving such a thing?

Yeah it should work well here. You could probably pass a query param with scopes to the auth route and set up a plug to pull them into the strategy config. Unless you have a custom auth controller, then it would be cleaner to just add it to the controller.

Would you be keen if I wrote up a quick community guides PR for the docs to elaborate on this?

I would be very happy to see that, thanks!

For the title, it could just be called something simple like Dynamic Strategy Configuration that starts out by explaining how the config can be updated dynamically, and then go into a practical example like the incremental authorization.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants