-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
auth.signIn() with magic link creates users in Auth.users table #1176
auth.signIn() with magic link creates users in Auth.users table #1176
Comments
I think this could be an option. Some apps might want a magic sign-up/log-in while others might only want a magic log-in. |
Yeah, as @edgarasben points out, there are plenty of apps that use "magic signin" - i.e. the user never creates a password. So this is expected behaviour. I'll keep this open for a few days if there are comments or suggested improvements |
I would suggest to explain this in documentation to avoid confusion. Thanks! |
Disabling the registration and inviting people manually as you say could be a nice option too. (Log in only). I was talking more about having some way to separate sign up and log in, while still relying on magic link tech technique. I expect some people might be confused about what's happening with signin only. Am I creating an account? Am I logging in? But good point about the security. You could add "If your account exists, an email will be sent to your inbox". |
The current behavior mimics the behavior of Firebase Authentication which has both seamless sign-up (when a user doesn't exist) and login via email links. From the Firebase Authentication docs (see also this magic link login/signup guide):
I think that Supabase should continue to mimic that ☝️ behavior to make it easier and more intuitive for users (like me) who are migrating from Firebase to Supabase. I do agree with @pichichi91 that manual invites might be a common enough use-case. But I think a better solution (instead of changing the current signup/login behavior of the magic link) would be a "test mode" similar to Google OAuth2 where you have to manually specify "test user email addresses" that are allowed to login or signup at all: |
Since this is left open for opinions, I'll add mine. I think it's awesome that magic links has streamlined the signup/login paths into a single flow. It is also in-line with how the OAuth providers work. It's much cleaner and simpler. I can see how some users might be a bit perplexed, but if there is only one "sign in" page, seems like they will get it soon enough :) Also, I noticed that using a magic link for a new user signup will send the "confirmation" email template, while using a magic link for an existing user will send the "magic link" template. So, you can customize these email templates to help the user understand whether they have created an account or just logged in. |
I think we can just add an option called "Disable SignUps" with magic link. I personally like the automatic magic link signup. |
Automatic signup with magic link is nice, but it should only be available via supabase.auth.signUp() |
I like the idea but in practice how would we ever get new users in the system (auth.users) if there wasn't a way to sign them up? |
What about an argument like
That's still clumsy. Maybe a setting would be best. |
building on @richcorbs' suggestion, this could also go like supabase.auth.signIn({email: 'me@email.com', signUp: false }) I can create a pull request for this in |
I'm having the same issue. But in my case, I want users to only signUp with email and password. No magic link. An option to disable magic link signIn would solve my problem. |
Maybe magic link sign up/sign in should be explicitly stated like how we do with social auth. supabase.auth.signIn({ email: 'me@example.com', provider: 'magiclink' }) Of course this would be a breaking change, but I guess creating a new major version of the libraries could solve this. |
since the magic link issue applies to both for signIn: supabase.auth.signIn({email: 'me@example.com', magicLink: false}) for signUp: supabase.auth.signUp({email: 'me@example.com', password: 'my-super-secret-pwd', magicLink: false}) This has the advantage of not breaking current behaviour but still allows you to turn off magic links |
I believe the problem is only in |
I also think this is strange. My website has a paid subscription offering and there is no free tier, so it makes no sense for people who are not customers to be able to sign up and log in. However, now people are able to create accounts by entering their email into my magic link login form. That doesn't make sense for my use case, which I believe is pretty common. The signIn function should just sign users in, not create accounts. For that we have signUp already. Adding a setting in the dashboard or in the signIn function to modify this functionality would be great. There are some good suggestions above. |
The way I dealt with that was adding an "authorized" field to the profiles table, and modifying security policies accordingly. Initially, it felt like a hack, but after some thinking, I believe it's conceptually correct. A local user/password table is a direct means of authentication; a Google or GitHub account is a delegated (via OAuth) means of authentication; an email account is another delegated (via magiclink) means of authentication. In principle, all of them only answer the question, "who's this user?", and not the question "what is this user allowed to do?" Yes, there's often the implied rule that, if the user can authenticate against the local user/password table, it also means "this user is authorized". But the moment you add social login to the mix, you run into a problem similar to what we're talking about here: users can authenticate regardless of what's in your user/password table (because you've delegated identity), and you can't block them from doing so (because you don't know the user's id the identity provider tells you). So "authenticated" no longer implies "has an account" no longer implies "is authorized". Similar cases could be made when you need to deactivate accounts but cannot delete them (because of data consistency, compliance, etc): existence of account is distinct from authorization of the account owner. Now, if we could replace the overloaded |
I'd need to double check the workflow, but I'm pretty sure no user will be created if you disable signups in the Dashboard under Auth > Settings > Disable signups After that, you can manually create new users using the |
Would this also disable the auth.signUp()? |
yes it would, which should be expected right? the reason why we create users on magic link signIn() is because otherwise a developer would need to implement one of these:
To address some of the comments:
That's the same as the password functionality - if you call signUp with username and password you'll also receive a success confirmation. Even if we switched the magic link to signUp() only it would have this issue.
This seems like a viable option since there is backwards compatibility. I'd probably rename the param to be a bit clearer which side-effect it's preventing. eg: I'll keep this open a bit for feedback so that we can decide what the community feels is best |
Thanks for clarifying, and +1 for "disableSignUp: true" |
I would appreciate this extension to the interface to better control the sign up process. Greate suggestion :) |
I would also like the |
Another vote for adding a Sign up flows may require users to accept terms and conditions, privacy policies, or provide additional information such as names, companies, etc. For me, this is pretty confusing behaviour for handling the user experience and complicates the front end logic. |
Added the chore to our Auth server here: supabase/auth#311 |
Hey everyone, we have started working on adding this to gotrue and would like to get some feedback on this issue (supabase/auth#318 (comment)). There are a few possible solutions being thrown around right now: Problem: Including a
Decided to go with (2), but renaming the flag to cc @dthyresson |
Agreed, #1 seems like a good choice. |
I wanted to implement this but I am getting a typescript error when I try to add the "create_user" flag to my signIn function: "Argument of type '{ email: string; create_user: boolean; }' is not assignable to parameter of type 'UserCredentials'. Here's my code:
|
hey @kristjanmar, we haven't added it to hope this new param helps everyone on this thread to build better magiclink login flows 💪🏻 |
Thanks @kangmingtay -- I managed to get rid of the type error by adding // @ts-ignore above the line. However, the "create_user: false" flag is not working. When I type an email that is not signed up in the login form, it creates the user in Supabase. I already updated to the latest version of supabase-js and tested this several times. The user is always created, just like before. |
yeah this is because the gotrue version that your supabase project is currently on is not updated to the latest one yet, we'll be rolling out the updates to all existing projects soon! |
That makes sense, thanks for clarifying. |
I see that supabase/gotrue-js has been updated. Does this mean that the create_user: false flag should work? |
Any updates on this? |
Creating the user is fine in my case, but how can we tell if it's a new user and therefore the magic link has The email message says to click the link or "Alternatively, enter the code", so I guess I also need to show an input box for the user to manually enter the code if they so choose, calling GET /verify that requires the right |
hey @mirkonasato,
Good point, I've created a PR to address this
Hmm let me check on this. We recently merged a PR that would send both the confirmation link and token to the user's email. But you can also modify the email template to only send the email link. |
Thanks @kangmingtay. It is possible to modify the magic link template email so it's not a big deal. I could also call generateLink() and send the email myself. From what I can see |
This is still not working, unfortunately. The user gets added when typing an email into the login form even when the flag is activated. async function signIn(email: string) {
const { error } = await supabase.auth.signIn({
email,
shouldCreateUser: false
})
return { error }
} I've tried shouldCreateUser, create_user and noSignup as the flag, since it is unclear which one it's supposed to be. But none of them work. |
@kristjanmar I think you need to put the shouldCreateUser in the second parameter, that is:
|
I've just been trying this with phone login, and unfortunately, when set to supabase.auth.signIn(
{ phone: `+${phone number for existing account}` },
{ shouldCreateUser: false },
) If I set it to This is when using the library |
Hey @ChronSyn, thanks for reporting this with the repro steps. I'll take a look at this soon! |
Bug report
Describe the bug
Using magic link feature to login creates the user if the email provided doesn't exist on Auth.users table.
To Reproduce
const { user, session, error } = await supabase.auth.signIn({ email: 'example@email.com' })
Expected behavior
If the email provided is not in Auth.users table it shouldn't be created and an error should be thrown.
The text was updated successfully, but these errors were encountered: