better-auth
Version:
The most comprehensive authentication framework for TypeScript.
1 lines • 4.59 kB
Source Map (JSON)
{"version":3,"file":"jwt.mjs","names":["info: Uint8Array"],"sources":["../../src/crypto/jwt.ts"],"sourcesContent":["import { hkdf } from \"@noble/hashes/hkdf.js\";\nimport { sha256 } from \"@noble/hashes/sha2.js\";\nimport {\n\tbase64url,\n\tcalculateJwkThumbprint,\n\tEncryptJWT,\n\tjwtDecrypt,\n\tjwtVerify,\n\tSignJWT,\n} from \"jose\";\n\nexport async function signJWT(\n\tpayload: any,\n\tsecret: string,\n\texpiresIn: number = 3600,\n): Promise<string> {\n\tconst jwt = await new SignJWT(payload)\n\t\t.setProtectedHeader({ alg: \"HS256\" })\n\t\t.setIssuedAt()\n\t\t.setExpirationTime(Math.floor(Date.now() / 1000) + expiresIn)\n\t\t.sign(new TextEncoder().encode(secret));\n\n\treturn jwt;\n}\n\nexport async function verifyJWT<T = any>(\n\ttoken: string,\n\tsecret: string,\n): Promise<T | null> {\n\ttry {\n\t\tconst verified = await jwtVerify(token, new TextEncoder().encode(secret));\n\t\treturn verified.payload as T;\n\t} catch {\n\t\treturn null;\n\t}\n}\n\n// \"BetterAuth.js Generated Encryption Key\"\nconst info: Uint8Array = new Uint8Array([\n\t66, 101, 116, 116, 101, 114, 65, 117, 116, 104, 46, 106, 115, 32, 71, 101,\n\t110, 101, 114, 97, 116, 101, 100, 32, 69, 110, 99, 114, 121, 112, 116, 105,\n\t111, 110, 32, 75, 101, 121,\n]);\n\nconst now = () => (Date.now() / 1000) | 0;\n\nconst alg = \"dir\";\nconst enc = \"A256CBC-HS512\"; // 64 bytes key\n\nexport async function symmetricEncodeJWT<T extends Record<string, any>>(\n\tpayload: T,\n\tsecret: string,\n\tsalt: string,\n\texpiresIn: number = 3600,\n): Promise<string> {\n\tconst encryptionSecret = hkdf(\n\t\tsha256,\n\t\tnew TextEncoder().encode(secret),\n\t\tnew TextEncoder().encode(salt),\n\t\tinfo,\n\t\t64,\n\t);\n\n\tconst thumbprint = await calculateJwkThumbprint(\n\t\t{ kty: \"oct\", k: base64url.encode(encryptionSecret) },\n\t\t\"sha256\",\n\t);\n\n\treturn await new EncryptJWT(payload)\n\t\t.setProtectedHeader({ alg, enc, kid: thumbprint })\n\t\t.setIssuedAt()\n\t\t.setExpirationTime(now() + expiresIn)\n\t\t.setJti(crypto.randomUUID())\n\t\t.encrypt(encryptionSecret);\n}\n\nexport async function symmetricDecodeJWT<T = any>(\n\ttoken: string,\n\tsecret: string,\n\tsalt: string,\n): Promise<T | null> {\n\tif (!token) return null;\n\ttry {\n\t\tconst { payload } = await jwtDecrypt(\n\t\t\ttoken,\n\t\t\tasync ({ kid }) => {\n\t\t\t\tconst encryptionSecret = hkdf(\n\t\t\t\t\tsha256,\n\t\t\t\t\tnew TextEncoder().encode(secret),\n\t\t\t\t\tnew TextEncoder().encode(salt),\n\t\t\t\t\tinfo,\n\t\t\t\t\t64,\n\t\t\t\t);\n\t\t\t\tif (kid === undefined) return encryptionSecret;\n\n\t\t\t\tconst thumbprint = await calculateJwkThumbprint(\n\t\t\t\t\t{ kty: \"oct\", k: base64url.encode(encryptionSecret) },\n\t\t\t\t\t\"sha256\",\n\t\t\t\t);\n\t\t\t\tif (kid === thumbprint) return encryptionSecret;\n\n\t\t\t\tthrow new Error(\"no matching decryption secret\");\n\t\t\t},\n\t\t\t{\n\t\t\t\tclockTolerance: 15,\n\t\t\t\tkeyManagementAlgorithms: [alg],\n\t\t\t\tcontentEncryptionAlgorithms: [enc, \"A256GCM\"],\n\t\t\t},\n\t\t);\n\t\treturn payload as T;\n\t} catch {\n\t\treturn null;\n\t}\n}\n"],"mappings":";;;;;AAWA,eAAsB,QACrB,SACA,QACA,YAAoB,MACF;AAOlB,QANY,MAAM,IAAI,QAAQ,QAAQ,CACpC,mBAAmB,EAAE,KAAK,SAAS,CAAC,CACpC,aAAa,CACb,kBAAkB,KAAK,MAAM,KAAK,KAAK,GAAG,IAAK,GAAG,UAAU,CAC5D,KAAK,IAAI,aAAa,CAAC,OAAO,OAAO,CAAC;;AAKzC,eAAsB,UACrB,OACA,QACoB;AACpB,KAAI;AAEH,UADiB,MAAM,UAAU,OAAO,IAAI,aAAa,CAAC,OAAO,OAAO,CAAC,EACzD;SACT;AACP,SAAO;;;AAKT,MAAMA,OAAmB,IAAI,WAAW;CACvC;CAAI;CAAK;CAAK;CAAK;CAAK;CAAK;CAAI;CAAK;CAAK;CAAK;CAAI;CAAK;CAAK;CAAI;CAAI;CACtE;CAAK;CAAK;CAAK;CAAI;CAAK;CAAK;CAAK;CAAI;CAAI;CAAK;CAAI;CAAK;CAAK;CAAK;CAAK;CACvE;CAAK;CAAK;CAAI;CAAI;CAAK;CACvB,CAAC;AAEF,MAAM,YAAa,KAAK,KAAK,GAAG,MAAQ;AAExC,MAAM,MAAM;AACZ,MAAM,MAAM;AAEZ,eAAsB,mBACrB,SACA,QACA,MACA,YAAoB,MACF;CAClB,MAAM,mBAAmB,KACxB,QACA,IAAI,aAAa,CAAC,OAAO,OAAO,EAChC,IAAI,aAAa,CAAC,OAAO,KAAK,EAC9B,MACA,GACA;CAED,MAAM,aAAa,MAAM,uBACxB;EAAE,KAAK;EAAO,GAAG,UAAU,OAAO,iBAAiB;EAAE,EACrD,SACA;AAED,QAAO,MAAM,IAAI,WAAW,QAAQ,CAClC,mBAAmB;EAAE;EAAK;EAAK,KAAK;EAAY,CAAC,CACjD,aAAa,CACb,kBAAkB,KAAK,GAAG,UAAU,CACpC,OAAO,OAAO,YAAY,CAAC,CAC3B,QAAQ,iBAAiB;;AAG5B,eAAsB,mBACrB,OACA,QACA,MACoB;AACpB,KAAI,CAAC,MAAO,QAAO;AACnB,KAAI;EACH,MAAM,EAAE,YAAY,MAAM,WACzB,OACA,OAAO,EAAE,UAAU;GAClB,MAAM,mBAAmB,KACxB,QACA,IAAI,aAAa,CAAC,OAAO,OAAO,EAChC,IAAI,aAAa,CAAC,OAAO,KAAK,EAC9B,MACA,GACA;AACD,OAAI,QAAQ,OAAW,QAAO;AAM9B,OAAI,QAJe,MAAM,uBACxB;IAAE,KAAK;IAAO,GAAG,UAAU,OAAO,iBAAiB;IAAE,EACrD,SACA,CACuB,QAAO;AAE/B,SAAM,IAAI,MAAM,gCAAgC;KAEjD;GACC,gBAAgB;GAChB,yBAAyB,CAAC,IAAI;GAC9B,6BAA6B,CAAC,KAAK,UAAU;GAC7C,CACD;AACD,SAAO;SACA;AACP,SAAO"}