forgotPassword should optionally reset header

I’m using forgotPassword as the easiest, most straightforward way to send an email to my new users when signing up, because there’s been a modification recently about how we store the tokens in the db. The raw version of a token is only displayed once and its hashed version is stored in the db, so if I want to pass the raw version of the token in my email template - I have to do it using forgotPassword.

The issue with this is that it effectively kills my session, thus preventing my new user to get logged in right at sign up: https://github.com/redwoodjs/redwood/blob/main/packages/auth-providers/dbAuth/api/src/DbAuthHandler.ts#L539

      return [
        response ? JSON.stringify(responseObj) : '',
        {
          ...this._deleteSessionHeader,
        },
      ]

Should I use a different workflow to achieve this? Or would it be acceptable to make an option for api/src/functions/auth.ts>handler>forgotPasswordOptions?

What kind of email are you trying to send? A generic “Welcome” email, or something specific about the password?

I’m sending a welcome email with a link to invite the user to set their password - which they are not doing in the app yet.

I’d prefer to send emails like that out-of-band. I’ve recently been playing with both Inngest and Trigger.dev. They’d both be great for this kind of thing.
But that doesn’t solve your token issue.

Why can’t you just have the users pick their password when signing up?

1 Like

I’m trying a sign up process i have implemented for a client, minimalist on the credentials because it’s packed with a necessary onboarding process.

Once the onboarding is done the user can update their password through UI - or use the forgotten password at any time.

Why do you prefer to handle this out of band?

Because I can just fire off an event and then not have to care about it. I know it’ll get done eventually. I find my code gets a bit cleaner that way.

Unfortunately I can’t think of a great way to solve your usecase right now though :frowning:

Me neither!

I’m considering switching Auth provider but that would add extra days of work i find hard to accept - the change is breaking and the changelog didn’t really highlight it.

The easiest way is to let users set their own password, but this cannot be a permanent situation.

Could this get a bit more discussion within the CT? I am curious as to what would be a broader opinion on this limitation.

@noire.munich do you know which major broke the way you were doing this? And just to make sure I understand what you’d like, it sounds like you want an option to disable forgotPassword logging users out of their session?

@dom I would think it was 5.0.0, but I’d need to investigate way further to confirm. I haven’t pass through 6 yet and 4 didn’t have the issue as far as I remember.

That would help! If it defaults to logging out, current apps wouldn’t have to update and those looking for this would be able to have their needs met.

Hmm, I didn’t envision the Forgot Password flow to be used to set a password! I can’t see a way to do what you need the way the code currently is (forcibly logging the user out). Logging someone out is more of a security measure and I don’t know that skirting that is a good thing to do, but maybe I’m wrong and it’s not that big of a deal?

If you’re okay with doing a little more work, could I suggest a flow that’ll accomplish what you need without changes to Redwood itself?

  1. Add a field to the User table, something like verified and set to false by default.
  2. When a user signs up, you set a default password, even if it’s just a random string, and keep verified false
  3. After the user is created, send an email with a link to a new page you’re going to create, that will let them set their password
  4. In a layout, or some place that “wraps” the rest of your logged in app pages, have a check that if currentUser.verified === false then redirect to a “We sent you an email to set your password” page (and maybe a “Click here to resend” link). Note that the user is still logged in and their session is good, they just can’t go anywhere useful (yet)
  5. The user follows the link in the email, sending them to the new page to set their password
  6. On submit, use this code on the server side to hash the password the same way that dbAuth does internally, save it to the DB and set verified to true (I think you can also import the hashPassword function from @redwood/auth-dbauth-api)
  7. Do a reauthenticate() after submitting their new password and verified is now true, so you can redirect them anywhere you’d like and the app will work as normal!

Personally, doing that feels more “right” to me, and keeps the concerns around forgetting your password consistent, not mixed with setting the password in the first place.

3 Likes

One thing I realized yesterday when I discussed this with Dom is that this behavior lets any user log out any other user as long as they know (or can guess) their email address, right? Just have to type “john.smith@gmail.com” into the forgot password box and whatever user is connected to that email will be logged out. Could be pretty annoying…

Remember that with dbAuth “logging out” just means deleting the session cookie. So putting in someone else’s email doesn’t do anything to that other person: only the browser that’s actually accessing the Forgot Password form would have their cookie removed!

1 Like

This reply might be irrelevant since the post is a month old by now. But I also had to build a custom onboarding flow for my app. Regular registration was not feasible. Here is how I solved it.

  1. Wrote a rw script that imports user data from external system.
  2. Create a User record with an encrypted and hashed random password. I copy pasted the implementation used by the password reset package in the framework for that.
  3. Emulate the password reset mechanism by storing a new token (with a long duration)
  4. Sent off a “welcome to the app” email with the token in the email cta link
  5. Built a custom password page that said “create a password” instead of “reset your password”.

I liked this approach because this way I could reuse all the web helpers that are used in the regular password reset pages

1 Like