diff --git a/packages/payload/src/auth/operations/forgotPassword.ts b/packages/payload/src/auth/operations/forgotPassword.ts index 1651a4725..45e899f26 100644 --- a/packages/payload/src/auth/operations/forgotPassword.ts +++ b/packages/payload/src/auth/operations/forgotPassword.ts @@ -1,5 +1,6 @@ import crypto from 'crypto' import { URL } from 'url' +import httpStatus from 'http-status' import type { Collection } from '../../collections/config/types.d.ts' import type { PayloadRequest } from '../../types/index.d.ts' @@ -25,7 +26,7 @@ export type Result = string export const forgotPasswordOperation = async (incomingArgs: Arguments): Promise => { if (!Object.prototype.hasOwnProperty.call(incomingArgs.data, 'email')) { - throw new APIError('Missing email.', 400) + throw new APIError('Missing email.', httpStatus.BAD_REQUEST) } let args = incomingArgs @@ -75,7 +76,7 @@ export const forgotPasswordOperation = async (incomingArgs: Arguments): Promise< } if (!data.email) { - throw new APIError('Missing email.') + throw new APIError('Missing email.', httpStatus.BAD_REQUEST) } let user = await payload.db.findOne({ @@ -84,6 +85,9 @@ export const forgotPasswordOperation = async (incomingArgs: Arguments): Promise< where: { email: { equals: data.email.toLowerCase() } }, }) + // 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) return null user.resetPasswordToken = token diff --git a/packages/payload/src/auth/operations/resetPassword.ts b/packages/payload/src/auth/operations/resetPassword.ts index e07431a01..45cdca40a 100644 --- a/packages/payload/src/auth/operations/resetPassword.ts +++ b/packages/payload/src/auth/operations/resetPassword.ts @@ -1,4 +1,5 @@ import jwt from 'jsonwebtoken' +import httpStatus from 'http-status' import type { Collection } from '../../collections/config/types.d.ts' import type { PayloadRequest } from '../../types/index.d.ts' @@ -32,7 +33,7 @@ export const resetPasswordOperation = async (args: Arguments): Promise = !Object.prototype.hasOwnProperty.call(args.data, 'token') || !Object.prototype.hasOwnProperty.call(args.data, 'password') ) { - throw new APIError('Missing required data.') + throw new APIError('Missing required data.', httpStatus.BAD_REQUEST) } const { @@ -63,7 +64,7 @@ export const resetPasswordOperation = async (args: Arguments): Promise = }, }) - if (!user) throw new APIError('Token is either invalid or has expired.') + if (!user) throw new APIError('Token is either invalid or has expired.', httpStatus.FORBIDDEN) // TODO: replace this method const { hash, salt } = await generatePasswordSaltHash({ password: data.password }) diff --git a/packages/payload/src/auth/operations/unlock.ts b/packages/payload/src/auth/operations/unlock.ts index e44bc6815..b568a755a 100644 --- a/packages/payload/src/auth/operations/unlock.ts +++ b/packages/payload/src/auth/operations/unlock.ts @@ -1,3 +1,5 @@ +import httpStatus from 'http-status' + import type { Collection } from '../../collections/config/types.d.ts' import type { PayloadRequest } from '../../types/index.d.ts' @@ -19,7 +21,7 @@ export type Args = { export const unlockOperation = async (args: Args): Promise => { if (!Object.prototype.hasOwnProperty.call(args.data, 'email')) { - throw new APIError('Missing email.') + throw new APIError('Missing email.', httpStatus.BAD_REQUEST) } const { @@ -49,7 +51,7 @@ export const unlockOperation = async (args: Args): Promise => { // ///////////////////////////////////// if (!data.email) { - throw new APIError('Missing email.') + throw new APIError('Missing email.', httpStatus.BAD_REQUEST) } const user = await req.payload.db.findOne({ diff --git a/packages/payload/src/auth/operations/verifyEmail.ts b/packages/payload/src/auth/operations/verifyEmail.ts index bf1fa7fa1..9cfc26005 100644 --- a/packages/payload/src/auth/operations/verifyEmail.ts +++ b/packages/payload/src/auth/operations/verifyEmail.ts @@ -31,7 +31,7 @@ export const verifyEmailOperation = async (args: Args): Promise => { }, }) - if (!user) throw new APIError('Verification token is invalid.', httpStatus.BAD_REQUEST) + if (!user) throw new APIError('Verification token is invalid.', httpStatus.FORBIDDEN) if (user && user._verified === true) throw new APIError('This account has already been activated.', httpStatus.ACCEPTED)