Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

resetToken for password not working

default discord avatar
hankier11 months ago
2

Hey guys,


I have a problemem with building my ecommerce with PayloadCMS.



I've have a logic that after order if there is no account with given email its created.



I wanted to send an email so client can set passowrd on its own using

payload.forgotPassword

.



Im doing it in afterCreate hook.


Here it is:


export const userWelcomeHook: CollectionAfterChangeHook = async ({
  doc,
  operation,
  previousDoc,
  req,
}) => {
  // Only handle user creation
  if (operation !== 'create') {
    return doc
  }

  console.log(`πŸ‘‹ [USER WELCOME HOOK] New user created: ${doc.email}`)
  
  try {
    console.log(`πŸ“§ [USER WELCOME HOOK] Attempting to send welcome email to: ${doc.email}`)
    
    // Try generating the reset token and handle any issues gracefully
    let resetToken = null
    try {
      console.log(`πŸ” [USER WELCOME HOOK] Trying to generate reset token for: ${doc.email}`)
      
      // Give user record a moment to be fully persisted
      await new Promise(resolve => setTimeout(resolve, 200))
      
      const resetTokenResponse = await req.payload.forgotPassword({
        collection: 'users',
        data: { email: doc.email },
        disableEmail: true, // Don't send default email, we'll send custom one
      })

      console.log(`πŸ” [USER WELCOME HOOK] Reset token response type:`, typeof resetTokenResponse)
      console.log(`πŸ” [USER WELCOME HOOK] Reset token response:`, resetTokenResponse)

      // According to PayloadCMS docs, forgotPassword with disableEmail: true should return the token string
      if (typeof resetTokenResponse === 'string' && resetTokenResponse) {
        resetToken = resetTokenResponse
      } else if (resetTokenResponse && typeof resetTokenResponse === 'object') {
        // Try different property names that might contain the token
        resetToken = (resetTokenResponse as any).token || 
                    (resetTokenResponse as any).resetToken || 
                    (resetTokenResponse as any).passwordResetToken ||
                    null
      }

      console.log(`πŸ”‘ [USER WELCOME HOOK] Reset token result:`, resetToken ? 'SUCCESS' : 'FAILED')
      if (resetToken) {
        console.log(`πŸ”‘ [USER WELCOME HOOK] Token length:`, resetToken.length)
      }
    } catch (tokenError) {
      console.warn(`⚠️ [USER WELCOME HOOK] Could not generate reset token for ${doc.email}:`, tokenError)
      // Continue without token - we'll send a different email
    }

    // Send welcome email (with or without reset token)
    await sendWelcomeEmailWithCredentials({
      user: doc,
      resetToken: resetToken || null
    })

    console.log(`βœ… [USER WELCOME HOOK] Welcome email sent to: ${doc.email}`)
  } catch (error) {
    console.error(`❌ [USER WELCOME HOOK] Failed to send welcome email to: ${doc.email}`, error)
    // Don't throw - user creation should still succeed
  }

  return doc
} 


But I got failure with generation password reset.


I tried both, created user with order or created from admin panel.


What am I missing here?



There are also logs which might help:


πŸ‘‹ [USER WELCOME HOOK] New user created: gg@hqr.sh
πŸ“§ [USER WELCOME HOOK] Attempting to send welcome email to: gg@hqr.sh
πŸ” [USER WELCOME HOOK] Trying to generate reset token for: gg@hqr.sh
πŸ” [USER WELCOME HOOK] Reset token response type: object
πŸ” [USER WELCOME HOOK] Reset token response: null
πŸ”‘ [USER WELCOME HOOK] Reset token result: FAILED
πŸ“§ [MAIL SERVICE] [WELCOME] User data: {
  id: 17,
  name: 'GG GG',
  roles: [ 'customer' ],
  cart: { items: [] },
  firstName: null,
  lastName: null,
  addresses: [],
  discordId: null,
  discordUsername: null,
  discordRoles: [],
  accessCodes: [],
  tickets: [],
  isDiscordVerified: false,
  discordVerifiedAt: null,
  updatedAt: '2025-06-26T21:18:11.644Z',
  createdAt: '2025-06-26T21:18:11.558Z',
  email: 'gg@hqr.sh',
  loginAttempts: 0
}
πŸ“§ [MAIL SERVICE] [WELCOME] Email sent successfully to: gg@hqr.sh
  • discord user avatar
    dribbens
    11 months ago

    I think you're not finding the user in your resetPassword local because you're not passing

    req

    so when the operation tries to find the user it is not within the same transaction and the user record isn't committed yet to the DB.



        // We don't want to indicate specifically that an email was not found,
        // as doing so could lead to the exposure of registered emails.
        // Therefore, we prefer to fail silently.
        if (!user) {
          await commitTransaction(args.req)
          return null
        }


    this is the block of code in the forgotPassword operation that you're hitting by the looks of it



    https://github.com/payloadcms/payload/blob/6ec21a53ffc99c155c2ef16c154e0b0ab1763f50/packages/payload/src/auth/operations/forgotPassword.ts#L135

    In your hook, add

    req

    to your local api call


          const resetTokenResponse = await req.payload.forgotPassword({
            collection: 'users',
            data: { email: doc.email },
            disableEmail: true, // Don't send default email, we'll send custom one
    // ADD THIS LINE
            req,
          })
  • default discord avatar
    hankier11 months ago

    Gonna check it!



    It worked!


    Thank you

    @969226489549713438

    ❀️



    Doing thing in the midnight is sometimes too much πŸ˜„

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.