UNPKG

better-auth

Version:

The most comprehensive authentication framework for TypeScript.

1 lines • 6.71 kB
{"version":3,"file":"verify-two-factor.mjs","names":["session","ctx"],"sources":["../../../src/plugins/two-factor/verify-two-factor.ts"],"sourcesContent":["import type { GenericEndpointContext } from \"@better-auth/core\";\nimport { createHMAC } from \"@better-auth/utils/hmac\";\nimport { APIError } from \"better-call\";\nimport { getSessionFromCtx } from \"../../api\";\nimport { setSessionCookie } from \"../../cookies\";\nimport {\n\tTRUST_DEVICE_COOKIE_MAX_AGE,\n\tTRUST_DEVICE_COOKIE_NAME,\n\tTWO_FACTOR_COOKIE_NAME,\n} from \"./constant\";\nimport { TWO_FACTOR_ERROR_CODES } from \"./error-code\";\nimport type { UserWithTwoFactor } from \"./types\";\n\nexport async function verifyTwoFactor(ctx: GenericEndpointContext) {\n\tconst invalid = (errorKey: keyof typeof TWO_FACTOR_ERROR_CODES) => {\n\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\tmessage: TWO_FACTOR_ERROR_CODES[errorKey],\n\t\t});\n\t};\n\n\tconst session = await getSessionFromCtx(ctx);\n\tif (!session) {\n\t\tconst cookieName = ctx.context.createAuthCookie(TWO_FACTOR_COOKIE_NAME);\n\t\tconst twoFactorCookie = await ctx.getSignedCookie(\n\t\t\tcookieName.name,\n\t\t\tctx.context.secret,\n\t\t);\n\t\tif (!twoFactorCookie) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: TWO_FACTOR_ERROR_CODES.INVALID_TWO_FACTOR_COOKIE,\n\t\t\t});\n\t\t}\n\t\tconst verificationToken =\n\t\t\tawait ctx.context.internalAdapter.findVerificationValue(twoFactorCookie);\n\t\tif (!verificationToken) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: TWO_FACTOR_ERROR_CODES.INVALID_TWO_FACTOR_COOKIE,\n\t\t\t});\n\t\t}\n\t\tconst user = (await ctx.context.internalAdapter.findUserById(\n\t\t\tverificationToken.value,\n\t\t)) as UserWithTwoFactor;\n\t\tif (!user) {\n\t\t\tthrow new APIError(\"UNAUTHORIZED\", {\n\t\t\t\tmessage: TWO_FACTOR_ERROR_CODES.INVALID_TWO_FACTOR_COOKIE,\n\t\t\t});\n\t\t}\n\t\tconst dontRememberMe = await ctx.getSignedCookie(\n\t\t\tctx.context.authCookies.dontRememberToken.name,\n\t\t\tctx.context.secret,\n\t\t);\n\t\treturn {\n\t\t\tvalid: async (ctx: GenericEndpointContext) => {\n\t\t\t\tconst session = await ctx.context.internalAdapter.createSession(\n\t\t\t\t\tverificationToken.value,\n\t\t\t\t\t!!dontRememberMe,\n\t\t\t\t);\n\t\t\t\tif (!session) {\n\t\t\t\t\tthrow new APIError(\"INTERNAL_SERVER_ERROR\", {\n\t\t\t\t\t\tmessage: \"failed to create session\",\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\t// Delete the verification token from the database after successful verification\n\t\t\t\tawait ctx.context.internalAdapter.deleteVerificationValue(\n\t\t\t\t\tverificationToken.id,\n\t\t\t\t);\n\t\t\t\tawait setSessionCookie(ctx, {\n\t\t\t\t\tsession,\n\t\t\t\t\tuser,\n\t\t\t\t});\n\t\t\t\t// Always clear the two factor cookie after successful verification\n\t\t\t\tctx.setCookie(cookieName.name, \"\", {\n\t\t\t\t\tmaxAge: 0,\n\t\t\t\t});\n\t\t\t\tif (ctx.body.trustDevice) {\n\t\t\t\t\tconst trustDeviceCookie = ctx.context.createAuthCookie(\n\t\t\t\t\t\tTRUST_DEVICE_COOKIE_NAME,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tmaxAge: TRUST_DEVICE_COOKIE_MAX_AGE,\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\t/**\n\t\t\t\t\t * create a token that will be used to\n\t\t\t\t\t * verify the device\n\t\t\t\t\t */\n\t\t\t\t\tconst token = await createHMAC(\"SHA-256\", \"base64urlnopad\").sign(\n\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\t`${user.id}!${session.token}`,\n\t\t\t\t\t);\n\t\t\t\t\tawait ctx.setSignedCookie(\n\t\t\t\t\t\ttrustDeviceCookie.name,\n\t\t\t\t\t\t`${token}!${session.token}`,\n\t\t\t\t\t\tctx.context.secret,\n\t\t\t\t\t\ttrustDeviceCookie.attributes,\n\t\t\t\t\t);\n\t\t\t\t\t// delete the dont remember me cookie\n\t\t\t\t\tctx.setCookie(ctx.context.authCookies.dontRememberToken.name, \"\", {\n\t\t\t\t\t\tmaxAge: 0,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\treturn ctx.json({\n\t\t\t\t\ttoken: session.token,\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: user.id,\n\t\t\t\t\t\temail: user.email,\n\t\t\t\t\t\temailVerified: user.emailVerified,\n\t\t\t\t\t\tname: user.name,\n\t\t\t\t\t\timage: user.image,\n\t\t\t\t\t\tcreatedAt: user.createdAt,\n\t\t\t\t\t\tupdatedAt: user.updatedAt,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t},\n\t\t\tinvalid,\n\t\t\tsession: {\n\t\t\t\tsession: null,\n\t\t\t\tuser,\n\t\t\t},\n\t\t\tkey: twoFactorCookie,\n\t\t};\n\t}\n\treturn {\n\t\tvalid: async (ctx: GenericEndpointContext) => {\n\t\t\treturn ctx.json({\n\t\t\t\ttoken: session.session.token,\n\t\t\t\tuser: {\n\t\t\t\t\tid: session.user.id,\n\t\t\t\t\temail: session.user.email,\n\t\t\t\t\temailVerified: session.user.emailVerified,\n\t\t\t\t\tname: session.user.name,\n\t\t\t\t\timage: session.user.image,\n\t\t\t\t\tcreatedAt: session.user.createdAt,\n\t\t\t\t\tupdatedAt: session.user.updatedAt,\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tinvalid,\n\t\tsession,\n\t\tkey: `${session.user.id}!${session.session.id}`,\n\t};\n}\n"],"mappings":";;;;;;;;;AAaA,eAAsB,gBAAgB,KAA6B;CAClE,MAAM,WAAW,aAAkD;AAClE,QAAM,IAAI,SAAS,gBAAgB,EAClC,SAAS,uBAAuB,WAChC,CAAC;;CAGH,MAAM,UAAU,MAAM,kBAAkB,IAAI;AAC5C,KAAI,CAAC,SAAS;EACb,MAAM,aAAa,IAAI,QAAQ,iBAAiB,uBAAuB;EACvE,MAAM,kBAAkB,MAAM,IAAI,gBACjC,WAAW,MACX,IAAI,QAAQ,OACZ;AACD,MAAI,CAAC,gBACJ,OAAM,IAAI,SAAS,gBAAgB,EAClC,SAAS,uBAAuB,2BAChC,CAAC;EAEH,MAAM,oBACL,MAAM,IAAI,QAAQ,gBAAgB,sBAAsB,gBAAgB;AACzE,MAAI,CAAC,kBACJ,OAAM,IAAI,SAAS,gBAAgB,EAClC,SAAS,uBAAuB,2BAChC,CAAC;EAEH,MAAM,OAAQ,MAAM,IAAI,QAAQ,gBAAgB,aAC/C,kBAAkB,MAClB;AACD,MAAI,CAAC,KACJ,OAAM,IAAI,SAAS,gBAAgB,EAClC,SAAS,uBAAuB,2BAChC,CAAC;EAEH,MAAM,iBAAiB,MAAM,IAAI,gBAChC,IAAI,QAAQ,YAAY,kBAAkB,MAC1C,IAAI,QAAQ,OACZ;AACD,SAAO;GACN,OAAO,OAAO,UAAgC;IAC7C,MAAMA,YAAU,MAAMC,MAAI,QAAQ,gBAAgB,cACjD,kBAAkB,OAClB,CAAC,CAAC,eACF;AACD,QAAI,CAACD,UACJ,OAAM,IAAI,SAAS,yBAAyB,EAC3C,SAAS,4BACT,CAAC;AAGH,UAAMC,MAAI,QAAQ,gBAAgB,wBACjC,kBAAkB,GAClB;AACD,UAAM,iBAAiBA,OAAK;KAC3B;KACA;KACA,CAAC;AAEF,UAAI,UAAU,WAAW,MAAM,IAAI,EAClC,QAAQ,GACR,CAAC;AACF,QAAIA,MAAI,KAAK,aAAa;KACzB,MAAM,oBAAoBA,MAAI,QAAQ,iBACrC,0BACA,EACC,QAAQ,6BACR,CACD;;;;;KAKD,MAAM,QAAQ,MAAM,WAAW,WAAW,iBAAiB,CAAC,KAC3DA,MAAI,QAAQ,QACZ,GAAG,KAAK,GAAG,GAAGD,UAAQ,QACtB;AACD,WAAMC,MAAI,gBACT,kBAAkB,MAClB,GAAG,MAAM,GAAGD,UAAQ,SACpBC,MAAI,QAAQ,QACZ,kBAAkB,WAClB;AAED,WAAI,UAAUA,MAAI,QAAQ,YAAY,kBAAkB,MAAM,IAAI,EACjE,QAAQ,GACR,CAAC;;AAEH,WAAOA,MAAI,KAAK;KACf,OAAOD,UAAQ;KACf,MAAM;MACL,IAAI,KAAK;MACT,OAAO,KAAK;MACZ,eAAe,KAAK;MACpB,MAAM,KAAK;MACX,OAAO,KAAK;MACZ,WAAW,KAAK;MAChB,WAAW,KAAK;MAChB;KACD,CAAC;;GAEH;GACA,SAAS;IACR,SAAS;IACT;IACA;GACD,KAAK;GACL;;AAEF,QAAO;EACN,OAAO,OAAO,UAAgC;AAC7C,UAAOC,MAAI,KAAK;IACf,OAAO,QAAQ,QAAQ;IACvB,MAAM;KACL,IAAI,QAAQ,KAAK;KACjB,OAAO,QAAQ,KAAK;KACpB,eAAe,QAAQ,KAAK;KAC5B,MAAM,QAAQ,KAAK;KACnB,OAAO,QAAQ,KAAK;KACpB,WAAW,QAAQ,KAAK;KACxB,WAAW,QAAQ,KAAK;KACxB;IACD,CAAC;;EAEH;EACA;EACA,KAAK,GAAG,QAAQ,KAAK,GAAG,GAAG,QAAQ,QAAQ;EAC3C"}