From c609509ad187b714b801395dc62313ee5e0ef5ce Mon Sep 17 00:00:00 2001 From: Marsel Shaikhin Date: Tue, 8 Oct 2024 18:21:35 +0200 Subject: [PATCH 1/2] feat(#673): migrate to AuthJS --- package.json | 3 +- playground-authjs/server/api/auth/[...].ts | 10 +- pnpm-lock.yaml | 444 +++++++----------- src/runtime/composables/authjs/useAuth.ts | 13 +- .../server/services/authjs/nuxtAuthHandler.ts | 207 ++------ 5 files changed, 215 insertions(+), 462 deletions(-) diff --git a/package.json b/package.json index 7152c00f..56bd80ac 100644 --- a/package.json +++ b/package.json @@ -46,10 +46,11 @@ "ufo": "^1.5.4" }, "peerDependencies": { - "next-auth": "~4.21.1" + "@auth/core": "^0.35.2" }, "devDependencies": { "@antfu/eslint-config": "^2.25.0", + "@auth/core": "^0.35.2", "@nuxt/module-builder": "^0.8.3", "@nuxt/schema": "^3.12.4", "@nuxtjs/eslint-config-typescript": "^12.1.0", diff --git a/playground-authjs/server/api/auth/[...].ts b/playground-authjs/server/api/auth/[...].ts index d310edee..ede30f11 100644 --- a/playground-authjs/server/api/auth/[...].ts +++ b/playground-authjs/server/api/auth/[...].ts @@ -1,18 +1,16 @@ -import CredentialsProvider from 'next-auth/providers/credentials' -import GithubProvider from 'next-auth/providers/github' +import CredentialsProvider from '@auth/core/providers/credentials' +import GithubProvider from '@auth/core/providers/github' import { NuxtAuthHandler } from '#auth' export default NuxtAuthHandler({ // a) Never hardcode your secret in your code!! and b) use a secure secret, `test-123` is **not** secure!! secret: process.env.AUTH_SECRET ?? 'test-123', providers: [ - // @ts-expect-error You need to use .default here for it to work during SSR. May be fixed via Vite at some point - GithubProvider.default({ + GithubProvider({ clientId: process.env.GITHUB_CLIENT_ID ?? 'your-client-id', clientSecret: process.env.GITHUB_CLIENT_SECRET ?? 'your-client-secret' }), - // @ts-expect-error You need to use .default here for it to work during SSR. May be fixed via Vite at some point - CredentialsProvider.default({ + CredentialsProvider({ // The name to display on the sign in form (e.g. 'Sign in with...') name: 'Credentials', // The credentials is used to generate a suitable form on the sign in page. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0f80d620..ce6ca395 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,9 +20,6 @@ importers: knitwork: specifier: ^1.1.0 version: 1.1.0 - next-auth: - specifier: ~4.21.1 - version: 4.21.1(next@13.5.6(@babel/core@7.25.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0) nitropack: specifier: ^2.9.7 version: 2.9.7(encoding@0.1.13)(magicast@0.3.4) @@ -39,6 +36,9 @@ importers: '@antfu/eslint-config': specifier: ^2.25.0 version: 2.25.0(@vue/compiler-sfc@3.4.35)(eslint@8.57.0)(typescript@5.5.4)(vitest@1.6.0(@types/node@18.19.42)(terser@5.30.3)) + '@auth/core': + specifier: ^0.35.2 + version: 0.35.2 '@nuxt/module-builder': specifier: ^0.8.3 version: 0.8.3(@nuxt/kit@3.12.4(magicast@0.3.4)(rollup@4.19.2))(nuxi@3.12.0)(typescript@5.5.4)(vue-tsc@2.0.29(typescript@5.5.4)) @@ -80,7 +80,7 @@ importers: devDependencies: nuxt: specifier: ^3.12.4 - version: 3.12.4(@parcel/watcher@2.4.1)(@types/node@20.12.7)(encoding@0.1.13)(eslint@8.57.0)(ioredis@5.4.1)(magicast@0.3.4)(optionator@0.9.3)(rollup@4.19.2)(terser@5.30.3)(typescript@5.5.4)(vite@5.3.3(@types/node@18.19.42)(terser@5.30.3))(vue-tsc@2.0.29(typescript@5.5.4)) + version: 3.12.4(@parcel/watcher@2.4.1)(@types/node@20.12.7)(encoding@0.1.13)(eslint@8.57.0)(ioredis@5.4.1)(magicast@0.3.4)(optionator@0.9.3)(rollup@4.19.2)(terser@5.30.3)(typescript@5.5.4)(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3))(vue-tsc@2.0.29(typescript@5.5.4)) typescript: specifier: ^5.5.4 version: 5.5.4 @@ -252,6 +252,20 @@ packages: '@antfu/utils@0.7.10': resolution: {integrity: sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==} + '@auth/core@0.35.2': + resolution: {integrity: sha512-4PSrmSkZNMNQEHq86jARBYqls/9G2ECGMJmlazXxkRpZWgtKMUBXF1HUPz82cxy3qFXZ9/HPEiGIEGtIvu4YGQ==} + peerDependencies: + '@simplewebauthn/browser': ^9.0.1 + '@simplewebauthn/server': ^9.0.2 + nodemailer: ^6.8.0 + peerDependenciesMeta: + '@simplewebauthn/browser': + optional: true + '@simplewebauthn/server': + optional: true + nodemailer: + optional: true + '@babel/code-frame@7.24.2': resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} engines: {node: '>=6.9.0'} @@ -476,10 +490,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.23.9': - resolution: {integrity: sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==} - engines: {node: '>=6.9.0'} - '@babel/standalone@7.24.4': resolution: {integrity: sha512-V4uqWeedadiuiCx5P5OHYJZ1PehdMpcBccNCEptKFGPiZIY3FI5f2ClxUl4r5wZ5U+ohcQ+4KW6jX2K6xXzq4Q==} engines: {node: '>=6.9.0'} @@ -1209,63 +1219,6 @@ packages: resolution: {integrity: sha512-2KYkyluThg1AKfd0JWI7FzpS4A/fzVVGYIf6AM4ydWyNj8eI/86GQVLeRgDoH7CNOxt243R5tutWlmHpVq0/Ew==} engines: {node: '>=18.0.0'} - '@next/env@13.5.6': - resolution: {integrity: sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw==} - - '@next/swc-darwin-arm64@13.5.6': - resolution: {integrity: sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@next/swc-darwin-x64@13.5.6': - resolution: {integrity: sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@next/swc-linux-arm64-gnu@13.5.6': - resolution: {integrity: sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-arm64-musl@13.5.6': - resolution: {integrity: sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - - '@next/swc-linux-x64-gnu@13.5.6': - resolution: {integrity: sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-linux-x64-musl@13.5.6': - resolution: {integrity: sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - - '@next/swc-win32-arm64-msvc@13.5.6': - resolution: {integrity: sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@next/swc-win32-ia32-msvc@13.5.6': - resolution: {integrity: sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - - '@next/swc-win32-x64-msvc@13.5.6': - resolution: {integrity: sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -1794,13 +1747,13 @@ packages: peerDependencies: eslint: '>=8.40.0' - '@swc/helpers@0.5.2': - resolution: {integrity: sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==} - '@trysound/sax@0.2.0': resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} + '@types/cookie@0.6.0': + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + '@types/eslint@8.56.11': resolution: {integrity: sha512-sVBpJMf7UPo/wGecYOpk2aQya2VUGeHhe38WG7/mN5FufNSubf5VT9Uh9Uyp8/eLJpu1/tuhJ/qTo4mhSB4V4Q==} @@ -2480,10 +2433,6 @@ packages: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} - busboy@1.6.0: - resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} - engines: {node: '>=10.16.0'} - c12@1.11.1: resolution: {integrity: sha512-KDU0TvSvVdaYcQKQ6iPHATGz/7p/KiVjPg4vQrB6Jg/wX9R0yl5RZxWm9IoZqaIHD2+6PZd81+KMGwRr/lRIUg==} peerDependencies: @@ -2575,9 +2524,6 @@ packages: clear@0.1.0: resolution: {integrity: sha512-qMjRnoL+JDPJHeLePZJuao6+8orzHMGP04A8CdwCNsKhRbOnKRjefxONR7bwILT3MHecxKBjHkKL/tkZ8r4Uzw==} - client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - clipboardy@4.0.0: resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==} engines: {node: '>=18'} @@ -2664,8 +2610,8 @@ packages: cookie-es@1.1.0: resolution: {integrity: sha512-L2rLOcK0wzWSfSDA33YR+PUHDG10a8px7rUHKWbGLP4YfbsMed2KFUw5fczvDPbT98DDe3LEzviswl810apTEw==} - cookie@0.5.0: - resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + cookie@0.6.0: + resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} copy-anything@3.0.5: @@ -3554,9 +3500,6 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} - glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - glob@10.3.10: resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} engines: {node: '>=16 || 14 >=14.17'} @@ -3946,8 +3889,8 @@ packages: resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} hasBin: true - jose@4.15.5: - resolution: {integrity: sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==} + jose@5.9.3: + resolution: {integrity: sha512-egLIoYSpcd+QUF+UHgobt5YzI2Pkw/H39ou9suW687MY6PmCwPmkNV/4TNjn1p2tX5xO3j0d0sq5hiYE24bSlg==} js-beautify@1.15.1: resolution: {integrity: sha512-ESjNzSlt/sWE8sciZH8kBF8BPlwXPwhR6pWKAw8bw4Bwj+iZcnKW6ONWUutJ7eObuBZQpiIb8S7OYspWrKt7rA==} @@ -4330,32 +4273,6 @@ packages: natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - next-auth@4.21.1: - resolution: {integrity: sha512-NYkU4jAPSVxWhCblE8dDFAnKM7kOoO/QEobQ0RoEVP9Wox99A3PKHwOAsWhSg8ahJG/iKIWk2Bo1xHvsS4R39Q==} - peerDependencies: - next: ^12.2.5 || ^13 - nodemailer: ^6.6.5 - react: ^17.0.2 || ^18 - react-dom: ^17.0.2 || ^18 - peerDependenciesMeta: - nodemailer: - optional: true - - next@13.5.6: - resolution: {integrity: sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==} - engines: {node: '>=16.14.0'} - hasBin: true - peerDependencies: - '@opentelemetry/api': ^1.1.0 - react: ^18.2.0 - react-dom: ^18.2.0 - sass: ^1.3.0 - peerDependenciesMeta: - '@opentelemetry/api': - optional: true - sass: - optional: true - nitropack@2.9.7: resolution: {integrity: sha512-aKXvtNrWkOCMsQbsk4A0qQdBjrJ1ZcvwlTQevI/LAgLWLYc5L7Q/YiYxGLal4ITyNSlzir1Cm1D2ZxnYhmpMEw==} engines: {node: ^16.11.0 || >=17.0.0} @@ -4457,17 +4374,13 @@ packages: engines: {node: ^14.16.0 || >=16.10.0} hasBin: true - oauth@0.9.15: - resolution: {integrity: sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==} + oauth4webapi@2.17.0: + resolution: {integrity: sha512-lbC0Z7uzAFNFyzEYRIC+pkSVvDHJTbEW+dYlSBAlCYDe6RxUkJ26bClhk8ocBZip1wfI9uKTe0fm4Ib4RHn6uQ==} object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - object-hash@2.2.0: - resolution: {integrity: sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==} - engines: {node: '>= 6'} - object-inspect@1.13.1: resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} @@ -4496,10 +4409,6 @@ packages: ohash@1.1.3: resolution: {integrity: sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==} - oidc-token-hash@5.0.3: - resolution: {integrity: sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==} - engines: {node: ^10.13.0 || >=12.0.0} - on-finished@2.4.1: resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} engines: {node: '>= 0.8'} @@ -4523,9 +4432,6 @@ packages: resolution: {integrity: sha512-c/hfooPx+RBIOPM09GSxABOZhYPblDoyaGhqBkD/59vtpN21jEuWKDlM0KYTvqJVlSYjKs0tBcIdeXKChlSPtw==} hasBin: true - openid-client@5.6.4: - resolution: {integrity: sha512-T1h3B10BRPKfcObdBklX639tVz+xh34O7GjofqrqiAQdm7eHsQ00ih18x6wuJ/E6FxdtS2u3FmUGPDeEcMwzNA==} - optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} @@ -4853,10 +4759,6 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.31: - resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.4.38: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} @@ -4865,11 +4767,14 @@ packages: resolution: {integrity: sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==} engines: {node: ^10 || ^12 || >=14} - preact-render-to-string@5.2.6: - resolution: {integrity: sha512-JyhErpYOvBV1hEPwIxc/fHWXPfnEGdRKxc8gFdAZ7XV4tlzyzG847XAyEZqoDnynP88akM4eaHcSOzNcLWFguw==} + preact-render-to-string@5.2.3: + resolution: {integrity: sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==} peerDependencies: preact: '>=10' + preact@10.11.3: + resolution: {integrity: sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==} + preact@10.19.4: resolution: {integrity: sha512-dwaX5jAh0Ga8uENBX1hSOujmKWgx9RtL80KaKUFLc6jb4vCEAc3EeZ0rnQO/FO4VgjfPMfoLFWnNG8bHuZ9VLw==} @@ -4978,9 +4883,6 @@ packages: resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - regenerator-runtime@0.14.1: - resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} - regexp-ast-analysis@0.7.1: resolution: {integrity: sha512-sZuz1dYW/ZsfG17WSAG7eS85r5a0dDsvg+7BiiYR5o6lKCAtUrEwdmRmaGF6rwVj3LcmAeYkOWKEPlbPzN3Y3A==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -5271,10 +5173,6 @@ packages: std-env@3.7.0: resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} - streamsearch@1.1.0: - resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} - engines: {node: '>=10.0.0'} - streamx@2.16.1: resolution: {integrity: sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==} @@ -5336,19 +5234,6 @@ packages: strip-literal@2.1.0: resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} - styled-jsx@5.1.1: - resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - stylehacks@7.0.2: resolution: {integrity: sha512-HdkWZS9b4gbgYTdMg4gJLmm7biAUug1qTqXjS+u8X+/pUd+9Px1E+520GnOW3rST9MNsVOVpsJG+mPHNosxjOQ==} engines: {node: ^18.12.0 || ^20.9.0 || >=22.0} @@ -5688,10 +5573,6 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -5966,10 +5847,6 @@ packages: typescript: optional: true - watchpack@2.4.0: - resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} - engines: {node: '>=10.13.0'} - webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -6248,6 +6125,16 @@ snapshots: '@antfu/utils@0.7.10': {} + '@auth/core@0.35.2': + dependencies: + '@panva/hkdf': 1.1.1 + '@types/cookie': 0.6.0 + cookie: 0.6.0 + jose: 5.9.3 + oauth4webapi: 2.17.0 + preact: 10.11.3 + preact-render-to-string: 5.2.3(preact@10.11.3) + '@babel/code-frame@7.24.2': dependencies: '@babel/highlight': 7.24.2 @@ -6538,10 +6425,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/runtime@7.23.9': - dependencies: - regenerator-runtime: 0.14.1 - '@babel/standalone@7.24.4': {} '@babel/template@7.24.0': @@ -7049,35 +6932,6 @@ snapshots: '@netlify/node-cookies': 0.1.0 urlpattern-polyfill: 8.0.2 - '@next/env@13.5.6': {} - - '@next/swc-darwin-arm64@13.5.6': - optional: true - - '@next/swc-darwin-x64@13.5.6': - optional: true - - '@next/swc-linux-arm64-gnu@13.5.6': - optional: true - - '@next/swc-linux-arm64-musl@13.5.6': - optional: true - - '@next/swc-linux-x64-gnu@13.5.6': - optional: true - - '@next/swc-linux-x64-musl@13.5.6': - optional: true - - '@next/swc-win32-arm64-msvc@13.5.6': - optional: true - - '@next/swc-win32-ia32-msvc@13.5.6': - optional: true - - '@next/swc-win32-x64-msvc@13.5.6': - optional: true - '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -7114,6 +6968,17 @@ snapshots: - rollup - supports-color + '@nuxt/devtools-kit@1.3.9(magicast@0.3.4)(rollup@4.19.2)(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3))': + dependencies: + '@nuxt/kit': 3.12.4(magicast@0.3.4)(rollup@4.19.2) + '@nuxt/schema': 3.12.4(rollup@4.19.2) + execa: 7.2.0 + vite: 5.3.5(@types/node@20.12.7)(terser@5.30.3) + transitivePeerDependencies: + - magicast + - rollup + - supports-color + '@nuxt/devtools-wizard@1.3.9': dependencies: consola: 3.2.3 @@ -7219,6 +7084,52 @@ snapshots: - supports-color - utf-8-validate + '@nuxt/devtools@1.3.9(rollup@4.19.2)(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3))': + dependencies: + '@antfu/utils': 0.7.10 + '@nuxt/devtools-kit': 1.3.9(magicast@0.3.4)(rollup@4.19.2)(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3)) + '@nuxt/devtools-wizard': 1.3.9 + '@nuxt/kit': 3.12.4(magicast@0.3.4)(rollup@4.19.2) + '@vue/devtools-core': 7.3.3(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3)) + '@vue/devtools-kit': 7.3.3 + birpc: 0.2.17 + consola: 3.2.3 + cronstrue: 2.50.0 + destr: 2.0.3 + error-stack-parser-es: 0.1.5 + execa: 7.2.0 + fast-glob: 3.3.2 + fast-npm-meta: 0.1.1 + flatted: 3.3.1 + get-port-please: 3.1.2 + hookable: 5.5.3 + image-meta: 0.2.1 + is-installed-globally: 1.0.0 + launch-editor: 2.8.0 + local-pkg: 0.5.0 + magicast: 0.3.4 + nypm: 0.3.9 + ohash: 1.1.3 + pathe: 1.1.2 + perfect-debounce: 1.0.0 + pkg-types: 1.1.3 + rc9: 2.1.2 + scule: 1.3.0 + semver: 7.6.3 + simple-git: 3.25.0 + sirv: 2.0.4 + unimport: 3.9.1(rollup@4.19.2) + vite: 5.3.5(@types/node@20.12.7)(terser@5.30.3) + vite-plugin-inspect: 0.8.5(@nuxt/kit@3.12.4(magicast@0.3.4)(rollup@4.19.2))(rollup@4.19.2)(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3)) + vite-plugin-vue-inspector: 5.1.3(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3)) + which: 3.0.1 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - rollup + - supports-color + - utf-8-validate + '@nuxt/kit@3.12.4(magicast@0.3.4)(rollup@4.19.2)': dependencies: '@nuxt/schema': 3.12.4(rollup@4.19.2) @@ -7927,12 +7838,10 @@ snapshots: - supports-color - typescript - '@swc/helpers@0.5.2': - dependencies: - tslib: 2.6.3 - '@trysound/sax@0.2.0': {} + '@types/cookie@0.6.0': {} + '@types/eslint@8.56.11': dependencies: '@types/estree': 1.0.5 @@ -8477,6 +8386,17 @@ snapshots: transitivePeerDependencies: - vite + '@vue/devtools-core@7.3.3(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3))': + dependencies: + '@vue/devtools-kit': 7.3.5 + '@vue/devtools-shared': 7.3.7 + mitt: 3.0.1 + nanoid: 3.3.7 + pathe: 1.1.2 + vite-hot-client: 0.2.3(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3)) + transitivePeerDependencies: + - vite + '@vue/devtools-kit@7.3.3': dependencies: '@vue/devtools-shared': 7.3.7 @@ -8869,10 +8789,6 @@ snapshots: dependencies: run-applescript: 7.0.0 - busboy@1.6.0: - dependencies: - streamsearch: 1.1.0 - c12@1.11.1(magicast@0.3.4): dependencies: chokidar: 3.6.0 @@ -8983,8 +8899,6 @@ snapshots: clear@0.1.0: {} - client-only@0.0.1: {} - clipboardy@4.0.0: dependencies: execa: 8.0.1 @@ -9056,7 +8970,7 @@ snapshots: cookie-es@1.1.0: {} - cookie@0.5.0: {} + cookie@0.6.0: {} copy-anything@3.0.5: dependencies: @@ -10181,8 +10095,6 @@ snapshots: dependencies: is-glob: 4.0.3 - glob-to-regexp@0.4.1: {} - glob@10.3.10: dependencies: foreground-child: 3.1.1 @@ -10571,7 +10483,7 @@ snapshots: jiti@1.21.6: {} - jose@4.15.5: {} + jose@5.9.3: {} js-beautify@1.15.1: dependencies: @@ -10751,6 +10663,7 @@ snapshots: loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 + optional: true loupe@2.3.7: dependencies: @@ -10941,46 +10854,6 @@ snapshots: natural-compare@1.4.0: {} - next-auth@4.21.1(next@13.5.6(@babel/core@7.25.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react-dom@18.2.0(react@18.2.0))(react@18.2.0): - dependencies: - '@babel/runtime': 7.23.9 - '@panva/hkdf': 1.1.1 - cookie: 0.5.0 - jose: 4.15.5 - next: 13.5.6(@babel/core@7.25.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) - oauth: 0.9.15 - openid-client: 5.6.4 - preact: 10.19.4 - preact-render-to-string: 5.2.6(preact@10.19.4) - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - uuid: 8.3.2 - - next@13.5.6(@babel/core@7.25.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): - dependencies: - '@next/env': 13.5.6 - '@swc/helpers': 0.5.2 - busboy: 1.6.0 - caniuse-lite: 1.0.30001646 - postcss: 8.4.31 - react: 18.2.0 - react-dom: 18.2.0(react@18.2.0) - styled-jsx: 5.1.1(@babel/core@7.25.2)(react@18.2.0) - watchpack: 2.4.0 - optionalDependencies: - '@next/swc-darwin-arm64': 13.5.6 - '@next/swc-darwin-x64': 13.5.6 - '@next/swc-linux-arm64-gnu': 13.5.6 - '@next/swc-linux-arm64-musl': 13.5.6 - '@next/swc-linux-x64-gnu': 13.5.6 - '@next/swc-linux-x64-musl': 13.5.6 - '@next/swc-win32-arm64-msvc': 13.5.6 - '@next/swc-win32-ia32-msvc': 13.5.6 - '@next/swc-win32-x64-msvc': 13.5.6 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - nitropack@2.9.7(encoding@0.1.13)(magicast@0.3.4): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 @@ -11340,10 +11213,10 @@ snapshots: - vue-tsc - xml2js - nuxt@3.12.4(@parcel/watcher@2.4.1)(@types/node@20.12.7)(encoding@0.1.13)(eslint@8.57.0)(ioredis@5.4.1)(magicast@0.3.4)(optionator@0.9.3)(rollup@4.19.2)(terser@5.30.3)(typescript@5.5.4)(vite@5.3.3(@types/node@18.19.42)(terser@5.30.3))(vue-tsc@2.0.29(typescript@5.5.4)): + nuxt@3.12.4(@parcel/watcher@2.4.1)(@types/node@20.12.7)(encoding@0.1.13)(eslint@8.57.0)(ioredis@5.4.1)(magicast@0.3.4)(optionator@0.9.3)(rollup@4.19.2)(terser@5.30.3)(typescript@5.5.4)(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3))(vue-tsc@2.0.29(typescript@5.5.4)): dependencies: '@nuxt/devalue': 2.0.2 - '@nuxt/devtools': 1.3.9(rollup@4.19.2)(vite@5.3.3(@types/node@18.19.42)(terser@5.30.3)) + '@nuxt/devtools': 1.3.9(rollup@4.19.2)(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3)) '@nuxt/kit': 3.12.4(magicast@0.3.4)(rollup@4.19.2) '@nuxt/schema': 3.12.4(rollup@4.19.2) '@nuxt/telemetry': 2.5.4(magicast@0.3.4)(rollup@4.19.2) @@ -11463,12 +11336,10 @@ snapshots: pkg-types: 1.1.3 ufo: 1.5.4 - oauth@0.9.15: {} + oauth4webapi@2.17.0: {} object-assign@4.1.1: {} - object-hash@2.2.0: {} - object-inspect@1.13.1: {} object-keys@1.1.1: {} @@ -11508,8 +11379,6 @@ snapshots: ohash@1.1.3: {} - oidc-token-hash@5.0.3: {} - on-finished@2.4.1: dependencies: ee-first: 1.1.1 @@ -11544,13 +11413,6 @@ snapshots: undici: 5.28.4 yargs-parser: 21.1.1 - openid-client@5.6.4: - dependencies: - jose: 4.15.5 - lru-cache: 6.0.0 - object-hash: 2.2.0 - oidc-token-hash: 5.0.3 - optionator@0.9.3: dependencies: '@aashutoshrathi/word-wrap': 1.2.6 @@ -11859,12 +11721,6 @@ snapshots: postcss-value-parser@4.2.0: {} - postcss@8.4.31: - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.1 - source-map-js: 1.2.0 - postcss@8.4.38: dependencies: nanoid: 3.3.7 @@ -11877,11 +11733,13 @@ snapshots: picocolors: 1.0.1 source-map-js: 1.2.0 - preact-render-to-string@5.2.6(preact@10.19.4): + preact-render-to-string@5.2.3(preact@10.11.3): dependencies: - preact: 10.19.4 + preact: 10.11.3 pretty-format: 3.8.0 + preact@10.11.3: {} + preact@10.19.4: {} prelude-ls@1.2.1: {} @@ -11933,12 +11791,14 @@ snapshots: loose-envify: 1.4.0 react: 18.2.0 scheduler: 0.23.2 + optional: true react-is@18.3.1: {} react@18.2.0: dependencies: loose-envify: 1.4.0 + optional: true read-pkg-up@7.0.1: dependencies: @@ -11995,8 +11855,6 @@ snapshots: dependencies: '@eslint-community/regexpp': 4.10.0 - regenerator-runtime@0.14.1: {} - regexp-ast-analysis@0.7.1: dependencies: '@eslint-community/regexpp': 4.10.0 @@ -12146,6 +12004,7 @@ snapshots: scheduler@0.23.2: dependencies: loose-envify: 1.4.0 + optional: true scslre@0.3.0: dependencies: @@ -12324,8 +12183,6 @@ snapshots: std-env@3.7.0: {} - streamsearch@1.1.0: {} - streamx@2.16.1: dependencies: fast-fifo: 1.3.2 @@ -12399,13 +12256,6 @@ snapshots: dependencies: js-tokens: 9.0.0 - styled-jsx@5.1.1(@babel/core@7.25.2)(react@18.2.0): - dependencies: - client-only: 0.0.1 - react: 18.2.0 - optionalDependencies: - '@babel/core': 7.25.2 - stylehacks@7.0.2(postcss@8.4.40): dependencies: browserslist: 4.23.3 @@ -12780,8 +12630,6 @@ snapshots: util-deprecate@1.0.2: {} - uuid@8.3.2: {} - validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 @@ -12795,6 +12643,10 @@ snapshots: dependencies: vite: 5.3.5(@types/node@18.19.45)(terser@5.30.3) + vite-hot-client@0.2.3(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3)): + dependencies: + vite: 5.3.5(@types/node@20.12.7)(terser@5.30.3) + vite-node@1.6.0(@types/node@18.19.42)(terser@5.30.3): dependencies: cac: 6.7.14 @@ -12986,6 +12838,24 @@ snapshots: - rollup - supports-color + vite-plugin-inspect@0.8.5(@nuxt/kit@3.12.4(magicast@0.3.4)(rollup@4.19.2))(rollup@4.19.2)(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3)): + dependencies: + '@antfu/utils': 0.7.10 + '@rollup/pluginutils': 5.1.0(rollup@4.19.2) + debug: 4.3.6 + error-stack-parser-es: 0.1.5 + fs-extra: 11.2.0 + open: 10.1.0 + perfect-debounce: 1.0.0 + picocolors: 1.0.1 + sirv: 2.0.4 + vite: 5.3.5(@types/node@20.12.7)(terser@5.30.3) + optionalDependencies: + '@nuxt/kit': 3.12.4(magicast@0.3.4)(rollup@4.19.2) + transitivePeerDependencies: + - rollup + - supports-color + vite-plugin-vue-inspector@5.1.3(vite@5.3.3(@types/node@18.19.42)(terser@5.30.3)): dependencies: '@babel/core': 7.25.2 @@ -13016,6 +12886,21 @@ snapshots: transitivePeerDependencies: - supports-color + vite-plugin-vue-inspector@5.1.3(vite@5.3.5(@types/node@20.12.7)(terser@5.30.3)): + dependencies: + '@babel/core': 7.25.2 + '@babel/plugin-proposal-decorators': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-import-attributes': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.25.2) + '@babel/plugin-transform-typescript': 7.25.2(@babel/core@7.25.2) + '@vue/babel-plugin-jsx': 1.2.2(@babel/core@7.25.2) + '@vue/compiler-dom': 3.4.35 + kolorist: 1.8.0 + magic-string: 0.30.11 + vite: 5.3.5(@types/node@20.12.7)(terser@5.30.3) + transitivePeerDependencies: + - supports-color + vite@5.2.9(@types/node@18.19.42)(terser@5.30.3): dependencies: esbuild: 0.20.2 @@ -13307,11 +13192,6 @@ snapshots: optionalDependencies: typescript: 5.5.4 - watchpack@2.4.0: - dependencies: - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - webidl-conversions@3.0.1: {} webpack-sources@3.2.3: {} diff --git a/src/runtime/composables/authjs/useAuth.ts b/src/runtime/composables/authjs/useAuth.ts index 78ceb585..23e40ad6 100644 --- a/src/runtime/composables/authjs/useAuth.ts +++ b/src/runtime/composables/authjs/useAuth.ts @@ -1,4 +1,4 @@ -import type { AppProvider, BuiltInProviderType } from 'next-auth/providers/index' +import type { AppProvider, BuiltInProviderType } from '@auth/core/providers/index' import { defu } from 'defu' import { type Ref, readonly } from 'vue' import { appendHeader } from 'h3' @@ -112,8 +112,12 @@ const signIn: SignInFunc = async (provider, op const csrfToken = await callWithNuxt(nuxt, getCsrfToken) - const headers: { 'Content-Type': string, 'cookie'?: string | undefined } = { + const headers: { 'Content-Type': string, 'X-Auth-Return-Redirect': string, 'cookie'?: string | undefined } = { 'Content-Type': 'application/x-www-form-urlencoded', + // This header is set to force AuthJS to return JSON + // https://github.com/nextauthjs/next-auth/blob/b86f7bb721e2fa4e9c3251b029095b0f50d46198/packages/next-auth/src/react.tsx#L270-L285 + // https://github.com/nextauthjs/next-auth/blob/b86f7bb721e2fa4e9c3251b029095b0f50d46198/packages/core/src/index.ts#L160 + 'X-Auth-Return-Redirect': '1', ...(await getRequestCookies(nuxt)) } @@ -122,7 +126,6 @@ const signIn: SignInFunc = async (provider, op ...options, csrfToken, callbackUrl, - json: true }) const fetchSignIn = () => _fetch<{ url: string }>(nuxt, `/${action}/${provider}`, { @@ -244,13 +247,13 @@ const signOut: SignOutFunc = async (options) => { const signoutData = await _fetch<{ url: string }>(nuxt, '/signout', { method: 'POST', headers: { - 'Content-Type': 'application/x-www-form-urlencoded' + 'Content-Type': 'application/x-www-form-urlencoded', + 'X-Auth-Return-Redirect': '1', }, onRequest: ({ options }) => { options.body = new URLSearchParams({ csrfToken: csrfToken as string, callbackUrl: callbackUrl || callbackUrlFallback, - json: 'true' }) } }).catch(error => error.data) diff --git a/src/runtime/server/services/authjs/nuxtAuthHandler.ts b/src/runtime/server/services/authjs/nuxtAuthHandler.ts index ee6baa18..56a78704 100644 --- a/src/runtime/server/services/authjs/nuxtAuthHandler.ts +++ b/src/runtime/server/services/authjs/nuxtAuthHandler.ts @@ -1,13 +1,10 @@ -import type { IncomingHttpHeaders } from 'node:http' -import { createError, eventHandler, getHeaders, getQuery, getRequestHost, getRequestProtocol, getResponseHeader, isMethod, parseCookies, readBody, sendRedirect, setCookie, setResponseHeader } from 'h3' +import { createError, eventHandler, getHeaders, getRequestHost, getRequestProtocol, getRequestWebStream, sendWebResponse } from 'h3' import type { H3Event } from 'h3' -import type { CookieSerializeOptions } from 'cookie-es' -import { AuthHandler } from 'next-auth/core' -import { getToken as authjsGetToken } from 'next-auth/jwt' -import type { RequestInternal, ResponseInternal } from 'next-auth/core' -import type { AuthAction, AuthOptions, Session } from 'next-auth' -import type { GetTokenParams } from 'next-auth/jwt' +import { Auth as AuthHandler, raw } from '@auth/core' +import { getToken as authjsGetToken } from '@auth/core/jwt' +import type { AuthConfig, ResponseInternal, Session } from '@auth/core/types' +import type { GetTokenParams } from '@auth/core/jwt' import { defu } from 'defu' import { joinURL } from 'ufo' @@ -18,11 +15,12 @@ import { useTypedBackendConfig } from '../../../helpers' import { useRuntimeConfig } from '#imports' -let preparedAuthjsHandler: ((req: RequestInternal) => Promise) | undefined -let usedSecret: string | undefined +let preparedAuthjsHandler: ((req: Request) => Promise) | undefined +let preparedAuthjsHandlerRaw: ((req: Request) => Promise) | undefined +let usedSecret: string | string[] | undefined /** Setup the nuxt (next) auth event handler, based on the passed in options */ -export function NuxtAuthHandler(nuxtAuthOptions?: AuthOptions) { +export function NuxtAuthHandler(nuxtAuthOptions?: AuthConfig) { const isProduction = process.env.NODE_ENV === 'production' const trustHostUserPreference = useTypedBackendConfig(useRuntimeConfig(), 'authjs').trustHost @@ -46,10 +44,12 @@ export function NuxtAuthHandler(nuxtAuthOptions?: AuthOptions) { trustHost: true, // AuthJS uses `/auth` as default, but we rely on `/api/auth` (same as in previous `next-auth`) - basePath: '/api/auth' + basePath: '/api/auth', + }) - // Uncomment to enable framework-author specific functionality - // raw: raw as typeof raw + const optionsRaw = defu(options, { + // Enable framework-author specific functionality + raw: raw as typeof raw }) // Save handler so that it can be used in other places @@ -57,45 +57,17 @@ export function NuxtAuthHandler(nuxtAuthOptions?: AuthOptions) { console.error('You setup the auth handler for a second time - this is likely undesired. Make sure that you only call `NuxtAuthHandler( ... )` once') } - preparedAuthjsHandler = (req: RequestInternal) => AuthHandler({ req, options }) + preparedAuthjsHandler = (req: Request) => AuthHandler(req, options) + preparedAuthjsHandlerRaw = (req: Request) => AuthHandler(req, optionsRaw) return eventHandler(async (event: H3Event) => { - const { res } = event.node - - // 1.1. Assemble and perform request to the NextAuth.js auth handler - const nextRequest = await createRequestForAuthjs(event, trustHostUserPreference) - - // 1.2. Call Authjs - // Safety: `preparedAuthjsHandler` was assigned earlier and never re-assigned - const nextResult = await preparedAuthjsHandler!(nextRequest) - - // 2. Set response status, headers, cookies - if (nextResult.status) { - res.statusCode = nextResult.status - } - nextResult.cookies?.forEach(cookie => setCookieDeduped(event, cookie.name, cookie.value, cookie.options)) - nextResult.headers?.forEach(header => appendHeaderDeduped(event, header.key, header.value)) - - // 3. Return either: - // 3.1. the body directly if no redirect is set: - if (!nextResult.redirect) { - return nextResult.body - } - // 3.2 a json-object with a redirect url if `json: true` is set by client: - // ``` - // // quote from https://github.com/nextauthjs/next-auth/blob/261968b9bbf8f57dd34651f60580d078f0c8a2ef/packages/next-auth/src/react/index.tsx#L3-L7 - // On signIn() and signOut() we pass 'json: true' to request a response in JSON - // instead of HTTP as redirect URLs on other domains are not returned to - // requests made using the fetch API in the browser, and we need to ask the API - // to return the response as a JSON object (the end point still defaults to - // returning an HTTP response with a redirect for non-JavaScript clients). - // ``` - if (nextRequest.body?.json) { - return { url: nextResult.redirect } - } + // 1. Assemble request to the Auth.js handler + const authjsRequest = await createRequestForAuthjs(event, trustHostUserPreference) - // 3.3 via a redirect: - return await sendRedirect(event, nextResult.redirect) + // 2. Call Authjs + // Safety: `preparedAuthjsHandler` was assigned earlier and never re-assigned. + const authjsResponse = await preparedAuthjsHandler!(authjsRequest) + return sendWebResponse(event, authjsResponse) }) } @@ -112,11 +84,11 @@ export async function getServerSession(event: H3Event) { const sessionUrlPath = joinURL(authBasePath, '/session') const headers = getHeaders(event) as HeadersInit - if (!preparedAuthjsHandler) { + if (!preparedAuthjsHandlerRaw) { // Edge-case: If no auth-endpoint was called yet, `preparedAuthHandler`-initialization was also not attempted as Nuxt lazily loads endpoints in production-mode. // This call gives it a chance to load + initialize the variable. If it fails we still throw. This edge-case has happened to user matijao#7025 on discord. await $fetch(sessionUrlPath, { headers }).catch(error => error.data) - if (!preparedAuthjsHandler) { + if (!preparedAuthjsHandlerRaw) { throw createError({ statusCode: 500, statusMessage: 'Tried to get server session without setting up an endpoint to handle authentication (see https://github.com/sidebase/nuxt-auth#quick-start)' }) } } @@ -126,20 +98,13 @@ export async function getServerSession(event: H3Event) { const sessionUrl = new URL(sessionUrlPath, sessionUrlBase) // Create a virtual Request to check the session - const authjsRequest: RequestInternal = { - action: 'session', + const authjsRequest = new Request(sessionUrl, { method: 'GET', - headers, - body: undefined, - cookies: parseCookies(event), - providerId: undefined, - error: undefined, - host: sessionUrl.origin, - query: Object.fromEntries(sessionUrl.searchParams) - } + headers: event.headers + }) - // Invoke Auth.js - const authjsResponse = await preparedAuthjsHandler(authjsRequest) + // Invoke Auth.js in `raw` mode + const authjsResponse = await preparedAuthjsHandlerRaw(authjsRequest) // Get the body of response const session = authjsResponse.body @@ -163,10 +128,8 @@ export async function getServerSession(event: H3Event) { */ export function getToken({ event, secureCookie, secret, ...rest }: Omit, 'req'> & { event: H3Event }) { return authjsGetToken({ - // @ts-expect-error As our request is not a real next-auth request, we pass down only what's required for the method, as per code from https://github.com/nextauthjs/next-auth/blob/8387c78e3fef13350d8a8c6102caeeb05c70a650/packages/next-auth/src/jwt/index.ts#L68 req: { - cookies: parseCookies(event), - headers: getHeaders(event) as IncomingHttpHeaders + headers: event.headers }, // see https://github.com/nextauthjs/next-auth/blob/8387c78e3fef13350d8a8c6102caeeb05c70a650/packages/next-auth/src/jwt/index.ts#L73 secureCookie: secureCookie ?? getServerOrigin(event).startsWith('https://'), @@ -181,39 +144,17 @@ export function getToken({ event, secureCookie, secre * * @param event H3Event to transform into `RequestInternal` */ -async function createRequestForAuthjs(event: H3Event, trustHostUserPreference: boolean): Promise { - const nextRequest: Omit = { - host: getRequestURLFromH3Event(event, trustHostUserPreference).origin, - body: undefined, - cookies: parseCookies(event), - query: undefined, - headers: getHeaders(event), +async function createRequestForAuthjs(event: H3Event, trustHostUserPreference: boolean): Promise { + // Adapted from `h3` + const webRequest = event.web?.request || new Request(getRequestURLFromH3Event(event, trustHostUserPreference), { + // @ts-expect-error Undici option + duplex: 'half', method: event.method, - providerId: undefined, - error: undefined - } - - // Figure out what action, providerId (optional) and error (optional) of the NextAuth.js lib is targeted - const query = getQuery(event) - const { action, providerId } = parseActionAndProvider(event) - const error = query.error - if (Array.isArray(error)) { - throw createError({ statusCode: 400, statusMessage: 'Error query parameter can only appear once' }) - } - - // Parse a body if the request method is supported, use `undefined` otherwise - const body = isMethod(event, ['PATCH', 'POST', 'PUT', 'DELETE']) - ? await readBody(event) - : undefined + headers: event.headers, + body: getRequestWebStream(event) + }) - return { - ...nextRequest, - body, - query, - action, - providerId, - error: error ? String(error) : undefined - } + return webRequest } /** @@ -260,73 +201,3 @@ function getRequestBaseFromH3Event(event: H3Event, trustHost: boolean): string { return origin } } - -/** Actions supported by auth handler */ -const SUPPORTED_ACTIONS: AuthAction[] = ['providers', 'session', 'csrf', 'signin', 'signout', 'callback', 'verify-request', 'error', '_log'] - -/** - * Get action and optional provider from a request. - * - * E.g. with a request like `/api/signin/github` get the action `signin` with the provider `github` - */ -function parseActionAndProvider({ context }: H3Event): { action: AuthAction, providerId: string | undefined } { - const params: string[] | undefined = context.params?._?.split('/') - - if (!params || ![1, 2].includes(params.length)) { - throw createError({ statusCode: 400, statusMessage: `Invalid path used for auth-endpoint. Supply either one path parameter (e.g., \`/api/auth/session\`) or two (e.g., \`/api/auth/signin/github\` after the base path (in previous examples base path was: \`/api/auth/\`. Received \`${params}\`` }) - } - - const [unvalidatedAction, providerId] = params - - // Get TS to correctly infer the type of `unvalidatedAction` - const action = SUPPORTED_ACTIONS.find(action => action === unvalidatedAction) - if (!action) { - throw createError({ statusCode: 400, statusMessage: `Called endpoint with unsupported action ${unvalidatedAction}. Only the following actions are supported: ${SUPPORTED_ACTIONS.join(', ')}` }) - } - - return { action, providerId } -} - -/** Adapted from `h3` to fix https://github.com/sidebase/nuxt-auth/issues/523 */ -function appendHeaderDeduped(event: H3Event, name: string, value: string) { - let current = getResponseHeader(event, name) - if (!current) { - setResponseHeader(event, name, value) - return - } - - if (!Array.isArray(current)) { - current = [current.toString()] - } - - // Check existence of a header value and avoid adding it again - if (current.includes(value)) { - return - } - - current.push(value) - setResponseHeader(event, name, current) -} - -/** - * Adds a cookie, overriding its previous value. - * Related to https://github.com/sidebase/nuxt-auth/issues/523 - */ -function setCookieDeduped(event: H3Event, name: string, value: string, serializeOptions: CookieSerializeOptions) { - // Deduplicate by removing the same name cookie - let setCookiesHeader = getResponseHeader(event, 'set-cookie') - if (setCookiesHeader) { - if (!Array.isArray(setCookiesHeader)) { - setCookiesHeader = [setCookiesHeader.toString()] - } - - // Safety: `cookie-es` builds up the cookie by using `name + '=' + encodedValue` - // https://github.com/unjs/cookie-es/blob/a3495860248b98e7015c9a3ade8c6c47ad3403df/src/index.ts#L102 - const filterBy = `${name}=` - setCookiesHeader = setCookiesHeader.filter(cookie => !cookie.startsWith(filterBy)) - - setResponseHeader(event, 'set-cookie', setCookiesHeader) - } - - setCookie(event, name, value, serializeOptions) -} From 10e4a21f1b4b7d81c4ffcd2e937cb6477de40704 Mon Sep 17 00:00:00 2001 From: Marsel Shaikhin Date: Tue, 8 Oct 2024 18:24:24 +0200 Subject: [PATCH 2/2] chore: fix type import --- src/runtime/composables/authjs/useAuthState.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/runtime/composables/authjs/useAuthState.ts b/src/runtime/composables/authjs/useAuthState.ts index 286853eb..03de7dd0 100644 --- a/src/runtime/composables/authjs/useAuthState.ts +++ b/src/runtime/composables/authjs/useAuthState.ts @@ -1,4 +1,4 @@ -import type { Session } from 'next-auth' +import type { Session } from '@auth/core/types' import type { CommonUseAuthStateReturn } from '../../types' import { makeCommonAuthState } from '../commonAuthState'