Waffleophagus
Waffleophagus2w ago

"Upgrading" Anonymous accounts to "real" accounts with email

Out of the gate when you log in to my react native application, I give you an anonymous account. My goal is to push the user into signing up and at that point we "upgrade" the account from an anon to a "proper" account. I know that this will require some custom account linking outlined briefly here: https://labs.convex.dev/auth/advanced#account-linking But from where I'm sitting I'm trying to nail down the best pattern that makes it such that the user does not lose any data. The goal being give them access to the app with as little barrier as possible and make them want to sign up. The thing that is a sticking point is right now I'm using Resend OTP codes, and I don't see a clean way to just give the built in Resend/Email functionality an existing userID, and the built in flow generates a new UserID when the flow begins. Is there a way to better call these internal things or should I just kinda... re-implement the OTP functionality? Will I have to do the same with the OAuth providers when I get to that? (Was planning on adding them in addition to OTP when the app is closer to production) Is there an example somewhere of this upgrade path? I'll happily share anything I have so far.
Advanced: Details - Convex Auth
Authentication library for your Convex backend
15 Replies
Waffleophagus
WaffleophagusOP2w ago
Ok, I just had an idea and wanted to know how dumb it is: 1. Call hook that takes in email + anon user id 2. Check if email is in use, if so, normal auth flow. If not in use, store in an anon userID+email table 3. Pass off to normal OTP flow 4. When OTP is complete, if email is in pivot table, replace userID. Reference: https://labs.convex.dev/auth/api_reference/server#callbacksafterusercreatedorupdated
server - Convex Auth
Authentication library for your Convex backend
Waffleophagus
WaffleophagusOP2w ago
Or, as an alternative, if swapping out the raw _id is a bad idea (it’s probably a real bad idea isn’t it?) Changing the userID on the authAccount table Update the anon user table to change the email, email verification time, and isAnon field Delete the NEW account
erquhart
erquhart2w ago
Hmm yeah the catch with account linking seems to be point 3:
If an untrusted method is used, the new account will not be linked to any existing one.
I'm curious how this is supposed to work for Auth.js, like I would assume this is the primary use case for the Anonymous provider.
erquhart
erquhart2w ago
Found this docs page about Anonymous users, I don't know if it's excluded from the nav because it's somehow incorrect, but it's here: https://labs.convex.dev/auth/config/anonymous
Anonymous Users - Convex Auth
Authentication library for your Convex backend
erquhart
erquhart2w ago
It also cites implementing custom account linking with a createOrUpdateUser function, so there should be a way to do it from there
erquhart
erquhart2w ago
Here's a test marked todo for converting a user, so you can at least see the intent: https://github.com/get-convex/convex-auth/blob/aa27918cdf69ceced04651350be77c36a179cbec/test/convex/anonymous.test.ts#L20-L37
GitHub
convex-auth/test/convex/anonymous.test.ts at aa27918cdf69ceced04651...
Library for built-in auth. Contribute to get-convex/convex-auth development by creating an account on GitHub.
Waffleophagus
WaffleophagusOP2w ago
Thanks for the response! Instead of replying to every one and @ing you like 4 times I’ll just do it in one go. I found that doc, and saw the vague upgrade path, and hand waves “do it custom” I guess my question at this point is what is the cleanest way to do that? That said, this specific callout I totally missed and makes a ton of sense. The “won’t be linked if insecure” thing. That explains a lot. I think, for now, especially if the test for how to do this is a “todo” state is make a second call to associate the anon userID in an unofficial manner to the email, so I can go through and move all the user data from the old to the new, cause where I’m sitting, once you start the auth process any link to the anon account kinda dies? So like 1. Make a call to an email/userID pivot table, (add logic if the email already exists in the system but let’s assume not for now) 2. Normal auth flow 3. Move user data from ID stored in 1 to the newly formed user. 4. Be really careful to not give a user the ability to hijack an account this way (oh buddy this one will be a doozy) I’m half tempted to not use anon accounts for now sadly
erquhart
erquhart2w ago
Yeah I'm not sure what a reliable path would look like here, seems like maybe one never quite landed
Waffleophagus
WaffleophagusOP2w ago
Ok, would love a sanity check, cause I think this is the path forward: 1. Before login, client calls the back end with their current anon userID and email they intend to link 2. That endpoint checks if the email exists in the system, if it doesn’t it creates the pivot table as mentioned. If it does it just returns doing nothing (since this is a user logging in, not signing up) 3. Using the above mentioned afterUserCreated call, query the pivot table for the freshly added email, if it exists in the table, move all user data from that anonymous account to the newly created one and delete the entry in the table. That’s…. Safe right? I don’t see a clear way to exploit this
erquhart
erquhart2w ago
Yeah, especially considering an anonymous account really shouldn't be allowed to have any security concern worthy data, should be fine So if there's anything they can do in the app that would result in sensitive data existing in the db, good spot to require a full sign in
Waffleophagus
WaffleophagusOP2w ago
Fwiw, my app isn’t really one where security is a huge concern to begin with, it’s gonna be like a miles per gallon tracker on steroids My main concern is that some how in this process you make an anon account and do this process and hijack my account somehow But I don’t see a way to do that
erquhart
erquhart2w ago
Anon accounts can't be re-logged into I don't think, unless you're doing something custom. So no concern there.
Waffleophagus
WaffleophagusOP2w ago
It’s a react native app, I actually have it refreshing the token on app re-launch, so you can effectively use the app for a while without “signing up” the idea here would be to let them figure out how to use the app and get a good taste before requiring it.
erquhart
erquhart2w ago
Right, but there's no way for anyone to log in and get an existing anon account. Even that anon user, if they signed out, wouldn't have a way to sign back in to that same account. (So no way to hijack) Again, that's how anon accounts work out of the box, haven't looked at whether configuration can change this.
Waffleophagus
WaffleophagusOP2w ago
Ohhhh I see what you’re saying. That’s a really good point. You’ve been wildly helpful @erquhart! thank you so much. I have a good path forward now I think

Did you find this page helpful?