Created
May 7, 2024 17:04
-
-
Save mobyjames/556552f039b176bb930a380f7f2092ae to your computer and use it in GitHub Desktop.
passwordless auth sample
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export async function beginAuthentication(email: string | null): Promise<boolean> { | |
if (!email || email.length === 0 || !email.includes('@')) { | |
throw ApiError.required('email'); | |
} | |
email = email.trim(); | |
const existingUser = await User.findOne({ email }); | |
let authKey = getRandomDigitString(4); | |
const authKeyExpiration = dateWithMinutesFromNow(10); | |
if (existingUser) { | |
await User.updateOne( | |
{ _id: existingUser._id }, | |
{ | |
authKey, | |
authKeyExpiration, | |
} | |
); | |
} else { | |
await createUser({ email, authKey, authKeyExpiration }); | |
} | |
if (DEV_MODE) { | |
console.log(`Auth Key: ${authKey}`); | |
} else { | |
try { | |
await sendEmail( | |
email, | |
`Your [GAME NAME] sign-in code: ${authKey}`, | |
`Enter this code in the game to finish signing in:\n\n${authKey}`, | |
'magic-login', | |
{ loginCode: authKey } | |
); | |
} catch (error) { | |
console.error(error); | |
throw ApiError.single({ field: 'email', code: ErrorCode.AuthEmailSendFailed, message: 'could not be sent' }); | |
} | |
} | |
return true; | |
} | |
export async function authenticate(email: string | null, authKey: string | null): Promise<TokenData> { | |
if (!email || email.length === 0) { | |
throw ApiError.required('email'); | |
} | |
if (!authKey || authKey.length === 0) { | |
throw ApiError.required('authKey'); | |
} | |
authKey = authKey.trim(); | |
const existingUser = await User.findOne({ email, authKey }); | |
if (!existingUser) { | |
throw ApiError.invalidValue('authKey'); | |
} | |
const authKeyExpiration = existingUser.authKeyExpiration ?? MIN_DATE; | |
if (minutesSince(authKeyExpiration) > 0) { | |
throw ApiError.single({ field: 'authKey', code: ErrorCode.ExpiredAuthKey, message: 'has expired' }); | |
} | |
// clear authentication key | |
const $set: any = { authKey: null, authKeyExpiration: null }; | |
await User.updateOne({ _id: existingUser._id }, { $set }); | |
return createToken(existingUser); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Workflow:
beginAuthentication
.authenticate