diff --git a/packages/pds/src/account-manager/helpers/email-token.ts b/packages/pds/src/account-manager/helpers/email-token.ts index 7d3690ad0e9..dae7bb2b2f2 100644 --- a/packages/pds/src/account-manager/helpers/email-token.ts +++ b/packages/pds/src/account-manager/helpers/email-token.ts @@ -1,6 +1,9 @@ import { InvalidRequestError } from '@atproto/xrpc-server' import { MINUTE, lessThanAgoMs } from '@atproto/common' -import { getRandomToken } from '../../api/com/atproto/server/util' +import { + getEmailToken, + normalizeEmailToken, +} from '../../api/com/atproto/server/util' import { AccountDb, EmailTokenPurpose } from '../db' export const createEmailToken = async ( @@ -8,7 +11,7 @@ export const createEmailToken = async ( did: string, purpose: EmailTokenPurpose, ): Promise => { - const token = getRandomToken().toUpperCase() + const token = getEmailToken() const now = new Date().toISOString() await db.executeWithRetry( db.db @@ -73,7 +76,7 @@ export const assertValidTokenAndFindDid = async ( .selectFrom('email_token') .selectAll() .where('purpose', '=', purpose) - .where('token', '=', token.toUpperCase()) + .where('token', '=', normalizeEmailToken(token)) .executeTakeFirst() if (!res) { throw new InvalidRequestError('Token is invalid', 'InvalidToken') diff --git a/packages/pds/src/api/com/atproto/server/util.ts b/packages/pds/src/api/com/atproto/server/util.ts index e6f52b8df59..1324acde4d9 100644 --- a/packages/pds/src/api/com/atproto/server/util.ts +++ b/packages/pds/src/api/com/atproto/server/util.ts @@ -22,12 +22,18 @@ export const genInvCodes = (cfg: ServerConfig, count: number): string[] => { return codes } -// Formatted xxxxx-xxxxx where digits are in base32 -export const getRandomToken = () => { - const token = crypto.randomStr(8, 'base32').slice(0, 10) - return token.slice(0, 5) + '-' + token.slice(5, 10) +// Random token formatted XXXXX-XXXXX where digits are in base32 +export const getEmailToken = () => { + return normalizeEmailToken(crypto.randomStr(8, 'base32')) } +// Transforms a badly-formed email token to XXXXX-XXXXX +// (i.e from xxXxxxx-xxx or xxxxxxxxxx) +export const normalizeEmailToken = (input: string): string => { + const normalized = input.trim().toUpperCase().replace('-', ''); // normalize to XXXXXXXXXX + return normalized.slice(0, 5) + '-' + normalized.slice(5, 10); // insert hyphen +}; + export const safeResolveDidDoc = async ( ctx: AppContext, did: string,