Password Reset
Forgot-password flow using secure reset tokens stored in {prefix}resets.
Flow
- User requests a password reset by email
resetPassword()creates a token and calls your callback with it- You send an email containing a link with the token
- User clicks the link and enters a new password
confirmResetPassword()validates the token and updates the password
Initiate Reset
app.post("/forgot-password", async (req, res) => {
try {
await req.auth.resetPassword(req.body.email, "6h", 2, (token) => {
sendEmail(req.body.email, "Reset your password", `
<p>Click to reset: <a href="${process.env.APP_URL}/reset/${token}">Reset password</a></p>
<p>This link expires in 6 hours.</p>
`);
});
} catch (error) {
// don't leak whether the account exists
}
// always return success to prevent user enumeration
res.json({ message: "If an account exists, reset instructions were sent." });
});
Parameters:
| Parameter | Default | Description |
|---|---|---|
email |
required | Account email address |
expiresAfter |
"6h" |
Token expiry, accepts ms format ("30m", "1d") |
maxOpenRequests |
2 |
Max concurrent reset tokens per user |
callback |
optional | Receives the token for sending the reset email |
Errors:
EmailNotVerifiedError- account not found or email not verifiedResetDisabledError- account hasresettable = falseTooManyResetsError- too many pending reset requests
Complete Reset
app.post("/reset-password", async (req, res) => {
try {
await req.auth.confirmResetPassword(req.body.token, req.body.password);
res.json({ message: "Password updated" });
} catch (error) {
if (error.name === "ResetExpiredError") {
return res.status(400).json({ error: "Reset link expired" });
}
res.status(400).json({ error: "Invalid reset link" });
}
});
By default, confirmResetPassword forces logout of all sessions after the password change. Pass false as the third argument to skip this.
Errors: ResetNotFoundError, ResetExpiredError, ResetDisabledError, InvalidPasswordError, InvalidTokenError, UserNotFoundError
Admin Reset
Initiate a reset for any user by identifier:
await req.auth.initiatePasswordResetForUserBy(
{ email: "user@example.com" },
"1h",
(token) => sendResetEmail(token),
);
Security
- Always return generic success messages to prevent user enumeration
- Tokens are hashed and verified against the account email
- Expired tokens are cleaned up via
cleanupExpiredTokens() - The
resettablecolumn allows disabling reset for specific accounts maxOpenRequestsprevents token flooding