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

Ability to hook into signup #1356

Closed
jasonkuhrt opened this issue Feb 22, 2021 · 21 comments
Closed

Ability to hook into signup #1356

jasonkuhrt opened this issue Feb 22, 2021 · 21 comments
Labels
enhancement New feature or request stale Did not receive any activity for 60 days

Comments

@jasonkuhrt
Copy link

Summary of proposed feature

GitHub provider does not guarantee user email. It also does not provide user name.

In our case we want to enforce that all users have email and user name, before creating a new user record in the database for them.

We would like a signup callback hook where we can augment the profile data and validate it. When validation fails there should be a mechanism to display a nice error to the user.

Detail about proposed feature
In order to satisfy this requirement we would like to hook into a callback called signUp. In here we would like to be able to:

  1. Augment the profile information.

  2. Throw an error with structured metadata. We would like this structured data to be made available to the client for nice error feedback. In our case here we might say something like:

    Please change your settings on GitHub so that your email is not private.

In the future instead of blocking GitHUb signup when their email is private, we might want to augment the flow with custom UI views where the user can input their email manually.

We're not sure how this should be achieved but an idea... redirect to a view (configurable, default /auth/signup). The view will do what it needs to do, and send back a request to e.g. /api/auth/custom-signup-flow-complete. The payload to this request will contain some data that can be merged into the profile on the backend to complete the signup flow.

And of course a callback hook could be available for any server side processing needs between /api/auth/custom-signup-flow-complete and it continuing the the Next Auth signup logic.

To keep things secure a temporary hash could be generated before redirecting to /auth/signup that is required to hit /api/auth/custom-signup-flow-complete. This hash could be kept in memory or when a db is setup, in the db. This would protect the endpoint from being hit in unexpected ways.

Potential problems
Describe any potential problems or potential limitations or caveats that might apply to the proposed solution.

The custom signup redirection stuff seems tricky to get right from a generalized point of view.

Describe any alternatives you've considered

Writing our own GitHub provider?

@jasonkuhrt jasonkuhrt added the enhancement New feature or request label Feb 22, 2021
@balazsorban44
Copy link
Member

balazsorban44 commented Feb 22, 2021

Hi there, could this recently added feature help here?:

#1329

@jasonkuhrt
Copy link
Author

Hey @balazsorban44, would that solution entail creating a custom provider? https://next-auth.js.org/configuration/providers#using-a-custom-provider

@balazsorban44
Copy link
Member

No, just add the profile callback to your provider config.

@jasonkuhrt
Copy link
Author

Ok, TS typings must be off

image

@balazsorban44
Copy link
Member

balazsorban44 commented Feb 22, 2021

You can override as many provider options https://next-auth.js.org/configuration/providers#oauth-provider-options as you like.

You can also verify this here: https://github.com/nextauthjs/next-auth/blob/main/src/providers/github.js
(Notice that ...options at the end)

About TS support: https://github.com/nextauthjs/next-auth#typescript 🙂

@jasonkuhrt
Copy link
Author

jasonkuhrt commented Feb 22, 2021

@balazsorban44 Just tried it out and that helps a lot!

Makes sense to have this hook at the provider level.

I guess what's mostly left to track for this issue is a way to block with a nice user-facing error and the custom-view-flow idea.

@balazsorban44
Copy link
Member

balazsorban44 commented Feb 22, 2021

you can use the signIn callback where if you return a string, you can redirect the user to any page you want.

For example you can check if profile.email is undefined.

https://next-auth.js.org/configuration/callbacks#sign-in-callback

@jasonkuhrt
Copy link
Author

@balazsorban44 I guess with that pattern we could effectively lock the user out of the app until they have fulfilled certain user record requirements.

@balazsorban44
Copy link
Member

if you return false or a string from the signIn callback, the users won't be logged in to your app! that's the whole point of the signIn callback.

@jasonkuhrt
Copy link
Author

jasonkuhrt commented Feb 22, 2021

In our case we would prefer to make strong guarantees about the User model in the database. So we'd want to intercept at signup time. Instead of e.g. a optional db field for User email that is only optional so that it can be filled in lazily later in the UI.

@Fronix
Copy link

Fronix commented Mar 22, 2021

In our case we would prefer to make strong guarantees about the User model in the database. So we'd want to intercept at signup time. Instead of e.g. a optional db field for User email that is only optional so that it can be filled in lazily later in the UI.

A way to intercept sign up would be great! There are several cases where you would want to sign in using an external provider, but you want additional information from the user before actually creating the user.

@stale
Copy link

stale bot commented May 22, 2021

Hi there! It looks like this issue hasn't had any activity for a while. It will be closed if no further activity occurs. If you think your issue is still relevant, feel free to comment on it to keep it open. (Read more at #912) Thanks!

@stale stale bot added the stale Did not receive any activity for 60 days label May 22, 2021
@stale
Copy link

stale bot commented May 29, 2021

Hi there! It looks like this issue hasn't had any activity for a while. To keep things tidy, I am going to close this issue for now. If you think your issue is still relevant, just leave a comment and I will reopen it. (Read more at #912) Thanks!

@stale stale bot closed this as completed May 29, 2021
@trompx
Copy link

trompx commented Feb 24, 2022

Hey @jasonkuhrt, did you manage to add custom data before the user is created or you ended up just login the user, then with a HOC, check if some data are missing and ask for it before redirecting him?
For a user onboarding flow, I'd also prefer to create the user only if all data are provided, so if this is still not supported, could this be reopened please?
Thanks

@Fronix
Copy link

Fronix commented Feb 24, 2022

Hey @jasonkuhrt, did you manage to add custom data before the user is created or you ended up just login the user, then with a HOC, check if some data are missing and ask for it before redirecting him? For a user onboarding flow, I'd also prefer to create the user only if all data are provided, so if this is still not supported, could this be reopened please? Thanks

Quick tip if you want to solve this without waiting, you can do a patch and add your own callback in callback-handler.ts after user is signed in and before user is created. At least that's how I've solved it because we use certain providers that don't have email or usernames.

I won't go into much detail on this solution though because it's kind of a hack and now that nextjs has middleware support there might be a much better solution.

1 similar comment
@Fronix
Copy link

Fronix commented Feb 24, 2022

Hey @jasonkuhrt, did you manage to add custom data before the user is created or you ended up just login the user, then with a HOC, check if some data are missing and ask for it before redirecting him? For a user onboarding flow, I'd also prefer to create the user only if all data are provided, so if this is still not supported, could this be reopened please? Thanks

Quick tip if you want to solve this without waiting, you can do a patch and add your own callback in callback-handler.ts after user is signed in and before user is created. At least that's how I've solved it because we use certain providers that don't have email or usernames.

I won't go into much detail on this solution though because it's kind of a hack and now that nextjs has middleware support there might be a much better solution.

@jasonkuhrt
Copy link
Author

I don't have power to re-open this issue.

@trompx
Copy link

trompx commented Mar 4, 2022

Thanks for your suggestion @Fronix but I'd rather not resort to a hack to solve this and have to maintain it at each upgrade.
Concerning middlewares, you mean to check if some data are missing in a middleware and redirect to an onboarding page until the data is correctly filled?

@Fronix
Copy link

Fronix commented Mar 6, 2022

Thanks for your suggestion @Fronix but I'd rather not resort to a hack to solve this and have to maintain it at each upgrade. Concerning middlewares, you mean to check if some data are missing in a middleware and redirect to an onboarding page until the data is correctly filled?

I understand, in our case we had no choice.

Yes, exactly, doing a check in the middleware that will decide if the user need to "do something extra" before being allowed to continue.

@shawnmclean
Copy link
Contributor

shawnmclean commented Feb 2, 2023

Yes, exactly, doing a check in the middleware that will decide if the user need to "do something extra" before being allowed to continue.

Is this still the case today?

Do you have any examples of this? They're talking about not using databases in the middleware in the docs.

I'm fine with having an optional database field. I'm trying to have a username that can be set by the user before moving forward, although preferably before the adapter creates the user.

@Fronix
Copy link

Fronix commented Feb 3, 2023

Yes, exactly, doing a check in the middleware that will decide if the user need to "do something extra" before being allowed to continue.

Is this still the case today?

Do you have any examples of this? They're talking about not using databases in the middleware in the docs.

I'm fine with having an optional database field. I'm trying to have a username that can be set by the user before moving forward, although preferably before the adapter creates the user.

That's correct you can't use middlewares for databasecalls so it might not be possible (?).

I've solved this another way now by using a custom ensureAuthGetServerSideProps function on all pages that checks for these conditions and forces the user to complete certain steps before gaining access to the application. It's not hacky but it's not pretty either, and it requires us to always remember to use that function.

It would however, be much cleaner if this could be handled in the callbacks with a nafterSignIn callback that needs to return true. This would make it possible to check for a condition, if it fails you redirect the user to complete the required condition (while still being signed in) and then it returns true. It would be called every time user interacts with the application.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request stale Did not receive any activity for 60 days
Projects
None yet
Development

No branches or pull requests

5 participants