I’m using dbAuth and adding a step to the process in which we send a verification email to new users to make sure they own the email they use to sign up. The verification email has a link in it with a token that sends the user back to our site and passes the token to the server for validation.
I would like the verification token not only to check the user’s ownership of the email address but also log them in to the application if they are currently logged out, like a “magic link” sign in URL. I am having trouble finding a way to log in a user programmatically on the API side.
Is there a function I can call on the API side to “log in” a user based on their user ID, without their password? I suppose this would mean generating a login JWT that I send back to the client from my token verification resolver.
Thanks!
Hi, that ability seems like it would introduce quite a security hole — even if you only allowed it on accounts that were verified within the past 10 seconds or some threshold.
That said, I would personally want to re-authenticate with my known credentials even when I verify.
I could sign up and not check my mail and walk away and if someone has access to it could click and then get into my account.
This way I know the user knows their password and is likely the one who signed up.
Clerk and Supabase offer this as do others.
It would be great if dbAuth could be enhanced with invites and verification (in conjunction with new Redwood mailer) to make this a core capability rather than some tacked on flow.
Interested in a PR to add these back into the framework?
Actually, on further thought if you have a verification token and can lookup the user by it and know who they are, you could likely response as if they have logged in by replicating this : https://github.com/redwoodjs/redwood/blob/61f0f51d8557c591e0432ffe9b75520c0df86ed1/packages/auth-providers/dbAuth/api/src/DbAuthHandler.ts#L583
That said. I think this verification login and also schema to store the verification token and verified at and sent at and ability to re-generate verification and re-send should be added to dbAuth as core functionality rather than tacked on as some workaround.
I do a modified version of the passwordless guide where I don’t automatically log the user in on sign up. After signup I redirect to the login page and send the login token to the email. That way if a user ever logs in then they’ve confirmed they have access to the email address.
I definitely think Redwood would benefit from offering verification emails as part of dbAuth, but I am not familiar with the mailer! We have added our own simple verification step and mailer in the meantime, which offers a lot of flexibility but requires some knowledge of best practices for both.
One pitfall of something like Supabase is that their email templates and in general the user flow are very basic and limited to their short list of supported cases. Supabase doesn’t easily allow you to swap out the email template for a custom HTML one, or have multiple emails in an onboarding flow. I value the flexibility Redwood offers us in choosing how bespoke to make each interaction over the sane defaults. That said, using dbAuth without email verification and with emails as usernames is pretty unsafe by default, because people can claim each other’s accounts and it’s up to the app author to understand that emails are meaningless usernames unless verified.
As for the threat model, we’re considering access to the user’s email to be equivalent to access to the account on our system, because the user can reset their password via email. They aren’t technically equal, because a user could conceivably leak or forward their verification email and someone else could use it to sign in, but the verification token can only be used once so the risk is relatively low. In the case where an attacker can read the user’s email on an ongoing basis, there is only a tiny bit of friction added to an attack by requiring the password.
I’m a bit late on this, but you can use the dbAuth handler’s internal methods for this! See here:
For one example of how to use this in your own code, check out the dbAuth OAuth plugin: