summary refs log tree commit diff
path: root/src/api/routes/users/@me/mfa
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/routes/users/@me/mfa')
-rw-r--r--src/api/routes/users/@me/mfa/codes-verification.ts18
-rw-r--r--src/api/routes/users/@me/mfa/codes.ts18
-rw-r--r--src/api/routes/users/@me/mfa/totp/disable.ts19
-rw-r--r--src/api/routes/users/@me/mfa/totp/enable.ts20
-rw-r--r--src/api/routes/users/@me/mfa/webauthn/credentials/#key_id/index.ts5
-rw-r--r--src/api/routes/users/@me/mfa/webauthn/credentials/index.ts72
6 files changed, 39 insertions, 113 deletions
diff --git a/src/api/routes/users/@me/mfa/codes-verification.ts b/src/api/routes/users/@me/mfa/codes-verification.ts

index f71704a9..f7083b53 100644 --- a/src/api/routes/users/@me/mfa/codes-verification.ts +++ b/src/api/routes/users/@me/mfa/codes-verification.ts
@@ -17,13 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - BackupCode, - CodesVerificationSchema, - DiscordApiErrors, - User, - generateMfaBackupCodes, -} from "@spacebar/util"; +import { BackupCode, CodesVerificationSchema, DiscordApiErrors, User, generateMfaBackupCodes } from "@spacebar/util"; import { Request, Response, Router } from "express"; const router = Router(); @@ -52,15 +46,11 @@ router.post( // Once that's done, this route can verify `key` // const user = await User.findOneOrFail({ where: { id: req.user_id } }); - if ((await User.count({ where: { id: req.user_id } })) === 0) - throw DiscordApiErrors.UNKNOWN_USER; + if ((await User.count({ where: { id: req.user_id } })) === 0) throw DiscordApiErrors.UNKNOWN_USER; let codes: BackupCode[]; if (regenerate) { - await BackupCode.update( - { user: { id: req.user_id } }, - { expired: true }, - ); + await BackupCode.update({ user: { id: req.user_id } }, { expired: true }); codes = generateMfaBackupCodes(req.user_id); await Promise.all(codes.map((x) => x.save())); @@ -78,7 +68,7 @@ router.post( return res.json({ backup_codes: codes.map((x) => ({ ...x, expired: undefined })), }); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/mfa/codes.ts b/src/api/routes/users/@me/mfa/codes.ts
index f9cfc4c4..d6e5a481 100644 --- a/src/api/routes/users/@me/mfa/codes.ts +++ b/src/api/routes/users/@me/mfa/codes.ts
@@ -17,13 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - BackupCode, - FieldErrors, - generateMfaBackupCodes, - MfaCodesSchema, - User, -} from "@spacebar/util"; +import { BackupCode, FieldErrors, generateMfaBackupCodes, MfaCodesSchema, User } from "@spacebar/util"; import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; @@ -36,8 +30,7 @@ router.post( route({ requestBody: "MfaCodesSchema", deprecated: true, - description: - "This route is replaced with users/@me/mfa/codes-verification in newer clients", + description: "This route is replaced with users/@me/mfa/codes-verification in newer clients", responses: { 200: { body: "APIBackupCodeArray", @@ -69,10 +62,7 @@ router.post( let codes: BackupCode[]; if (regenerate) { - await BackupCode.update( - { user: { id: req.user_id } }, - { expired: true }, - ); + await BackupCode.update({ user: { id: req.user_id } }, { expired: true }); codes = generateMfaBackupCodes(req.user_id); await Promise.all(codes.map((x) => x.save())); @@ -90,7 +80,7 @@ router.post( return res.json({ backup_codes: codes.map((x) => ({ ...x, expired: undefined })), }); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/mfa/totp/disable.ts b/src/api/routes/users/@me/mfa/totp/disable.ts
index 362152d7..6a0960d8 100644 --- a/src/api/routes/users/@me/mfa/totp/disable.ts +++ b/src/api/routes/users/@me/mfa/totp/disable.ts
@@ -17,12 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - BackupCode, - TotpDisableSchema, - User, - generateToken, -} from "@spacebar/util"; +import { BackupCode, TotpDisableSchema, User, generateToken } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import { verifyToken } from "node-2fa"; @@ -53,11 +48,7 @@ router.post( const backup = await BackupCode.findOne({ where: { code: body.code } }); if (!backup) { const ret = verifyToken(user.totp_secret || "", body.code); - if (!ret || ret.delta != 0) - throw new HTTPError( - req.t("auth:login.INVALID_TOTP_CODE"), - 60008, - ); + if (!ret || ret.delta != 0) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008); } await User.update( @@ -65,20 +56,20 @@ router.post( { mfa_enabled: false, totp_secret: "", - }, + } ); await BackupCode.update( { user: { id: req.user_id } }, { expired: true, - }, + } ); return res.json({ token: await generateToken(user.id), }); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/mfa/totp/enable.ts b/src/api/routes/users/@me/mfa/totp/enable.ts
index 19836e4d..6d66fb95 100644 --- a/src/api/routes/users/@me/mfa/totp/enable.ts +++ b/src/api/routes/users/@me/mfa/totp/enable.ts
@@ -17,12 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - TotpEnableSchema, - User, - generateMfaBackupCodes, - generateToken, -} from "@spacebar/util"; +import { TotpEnableSchema, User, generateMfaBackupCodes, generateToken } from "@spacebar/util"; import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; @@ -61,21 +56,16 @@ router.post( } } - if (!body.secret) - throw new HTTPError(req.t("auth:login.INVALID_TOTP_SECRET"), 60005); + if (!body.secret) throw new HTTPError(req.t("auth:login.INVALID_TOTP_SECRET"), 60005); - if (!body.code) - throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008); + if (!body.code) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008); if (verifyToken(body.secret, body.code)?.delta != 0) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008); const backup_codes = generateMfaBackupCodes(req.user_id); await Promise.all(backup_codes.map((x) => x.save())); - await User.update( - { id: req.user_id }, - { mfa_enabled: true, totp_secret: body.secret }, - ); + await User.update({ id: req.user_id }, { mfa_enabled: true, totp_secret: body.secret }); res.send({ token: await generateToken(user.id), @@ -84,7 +74,7 @@ router.post( expired: undefined, })), }); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/mfa/webauthn/credentials/#key_id/index.ts b/src/api/routes/users/@me/mfa/webauthn/credentials/#key_id/index.ts
index 9cf42def..ba5df994 100644 --- a/src/api/routes/users/@me/mfa/webauthn/credentials/#key_id/index.ts +++ b/src/api/routes/users/@me/mfa/webauthn/credentials/#key_id/index.ts
@@ -41,11 +41,10 @@ router.delete( }); // disable webauthn if there are no keys left - if (keys === 0) - await User.update({ id: req.user_id }, { webauthn_enabled: false }); + if (keys === 0) await User.update({ id: req.user_id }, { webauthn_enabled: false }); res.sendStatus(204); - }, + } ); export default router; diff --git a/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts b/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts
index f383ffb7..b8e33da7 100644 --- a/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts +++ b/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts
@@ -35,15 +35,11 @@ import { ExpectedAttestationResult } from "fido2-lib"; import { HTTPError } from "lambert-server"; const router = Router(); -const isGenerateSchema = ( - body: WebAuthnPostSchema, -): body is GenerateWebAuthnCredentialsSchema => { +const isGenerateSchema = (body: WebAuthnPostSchema): body is GenerateWebAuthnCredentialsSchema => { return "password" in body; }; -const isCreateSchema = ( - body: WebAuthnPostSchema, -): body is CreateWebAuthnCredentialSchema => { +const isCreateSchema = (body: WebAuthnPostSchema): body is CreateWebAuthnCredentialSchema => { return "credential" in body; }; @@ -67,7 +63,7 @@ router.get("/", route({}), async (req: Request, res: Response) => { securityKeys.map((key) => ({ id: key.id, name: key.name, - })), + })) ); }); @@ -94,24 +90,13 @@ router.post( where: { id: req.user_id, }, - select: [ - "data", - "id", - "disabled", - "deleted", - "totp_secret", - "mfa_enabled", - "username", - ], + select: ["data", "id", "disabled", "deleted", "totp_secret", "mfa_enabled", "username"], relations: ["settings"], }); if (isGenerateSchema(req.body)) { const { password } = req.body; - const same_password = await bcrypt.compare( - password, - user.data.hash || "", - ); + const same_password = await bcrypt.compare(password, user.data.hash || ""); if (!same_password) { throw FieldErrors({ password: { @@ -121,14 +106,11 @@ router.post( }); } - const registrationOptions = - await WebAuthn.fido2.attestationOptions(); + const registrationOptions = await WebAuthn.fido2.attestationOptions(); const challenge = JSON.stringify({ publicKey: { ...registrationOptions, - challenge: Buffer.from( - registrationOptions.challenge, - ).toString("base64"), + challenge: Buffer.from(registrationOptions.challenge).toString("base64"), user: { id: user.id, name: user.username, @@ -151,35 +133,22 @@ router.post( const clientAttestationResponse = JSON.parse(credential); - if (!clientAttestationResponse.rawId) - throw new HTTPError("Missing rawId", 400); + if (!clientAttestationResponse.rawId) throw new HTTPError("Missing rawId", 400); - const rawIdBuffer = Buffer.from( - clientAttestationResponse.rawId, - "base64", - ); + const rawIdBuffer = Buffer.from(clientAttestationResponse.rawId, "base64"); clientAttestationResponse.rawId = toArrayBuffer(rawIdBuffer); - const attestationExpectations: ExpectedAttestationResult = - JSON.parse( - Buffer.from( - clientAttestationResponse.response.clientDataJSON, - "base64", - ).toString(), - ); - - const regResult = await WebAuthn.fido2.attestationResult( - clientAttestationResponse, - { - ...attestationExpectations, - factor: "second", - }, + const attestationExpectations: ExpectedAttestationResult = JSON.parse( + Buffer.from(clientAttestationResponse.response.clientDataJSON, "base64").toString() ); + const regResult = await WebAuthn.fido2.attestationResult(clientAttestationResponse, { + ...attestationExpectations, + factor: "second", + }); + const authnrData = regResult.authnrData; - const keyId = Buffer.from(authnrData.get("credId")).toString( - "base64", - ); + const keyId = Buffer.from(authnrData.get("credId")).toString("base64"); const counter = authnrData.get("counter"); const publicKey = authnrData.get("credentialPublicKeyPem"); @@ -191,10 +160,7 @@ router.post( key_id: keyId, }); - await Promise.all([ - securityKey.save(), - User.update({ id: req.user_id }, { webauthn_enabled: true }), - ]); + await Promise.all([securityKey.save(), User.update({ id: req.user_id }, { webauthn_enabled: true })]); return res.json({ name, @@ -203,7 +169,7 @@ router.post( } else { throw DiscordApiErrors.INVALID_AUTHENTICATION_TOKEN; } - }, + } ); export default router;