nuxt-auth-utils 0.5.34 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -15
- package/dist/module.d.mts +3 -3
- package/dist/module.json +4 -1
- package/dist/module.mjs +18 -31
- package/dist/runtime/app/composables/session.js +3 -2
- package/dist/runtime/server/api/session.delete.d.ts +1 -1
- package/dist/runtime/server/api/session.delete.js +2 -2
- package/dist/runtime/server/api/session.get.d.ts +1 -1
- package/dist/runtime/server/api/session.get.js +2 -2
- package/dist/runtime/server/lib/atproto/bluesky.d.ts +3 -3
- package/dist/runtime/server/lib/atproto/bluesky.js +6 -6
- package/dist/runtime/server/lib/oauth/apple.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/apple.js +3 -4
- package/dist/runtime/server/lib/oauth/atlassian.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/atlassian.js +8 -8
- package/dist/runtime/server/lib/oauth/auth0.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/auth0.js +4 -4
- package/dist/runtime/server/lib/oauth/authentik.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/authentik.js +6 -6
- package/dist/runtime/server/lib/oauth/azureb2c.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/azureb2c.js +5 -5
- package/dist/runtime/server/lib/oauth/battledotnet.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/battledotnet.js +6 -6
- package/dist/runtime/server/lib/oauth/box.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/box.js +5 -5
- package/dist/runtime/server/lib/oauth/cloudflare.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/cloudflare.js +5 -5
- package/dist/runtime/server/lib/oauth/cognito.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/cognito.js +4 -4
- package/dist/runtime/server/lib/oauth/discord.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/discord.js +4 -4
- package/dist/runtime/server/lib/oauth/dropbox.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/dropbox.js +5 -5
- package/dist/runtime/server/lib/oauth/facebook.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/facebook.js +7 -7
- package/dist/runtime/server/lib/oauth/gitea.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/gitea.js +5 -5
- package/dist/runtime/server/lib/oauth/github.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/github.js +6 -6
- package/dist/runtime/server/lib/oauth/gitlab.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/gitlab.js +5 -5
- package/dist/runtime/server/lib/oauth/google.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/google.js +4 -4
- package/dist/runtime/server/lib/oauth/heroku.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/heroku.js +5 -5
- package/dist/runtime/server/lib/oauth/hubspot.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/hubspot.js +4 -4
- package/dist/runtime/server/lib/oauth/instagram.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/instagram.js +6 -6
- package/dist/runtime/server/lib/oauth/keycloak.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/keycloak.js +6 -6
- package/dist/runtime/server/lib/oauth/kick.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/kick.js +5 -5
- package/dist/runtime/server/lib/oauth/line.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/line.js +6 -6
- package/dist/runtime/server/lib/oauth/linear.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/linear.js +6 -6
- package/dist/runtime/server/lib/oauth/linkedin.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/linkedin.js +4 -4
- package/dist/runtime/server/lib/oauth/livechat.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/livechat.js +4 -4
- package/dist/runtime/server/lib/oauth/mastodon.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/mastodon.js +8 -9
- package/dist/runtime/server/lib/oauth/microsoft.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/microsoft.js +5 -5
- package/dist/runtime/server/lib/oauth/oidc.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/oidc.js +6 -6
- package/dist/runtime/server/lib/oauth/okta.d.ts +4 -4
- package/dist/runtime/server/lib/oauth/okta.js +8 -8
- package/dist/runtime/server/lib/oauth/ory.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/ory.js +6 -6
- package/dist/runtime/server/lib/oauth/osu.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/osu.js +4 -4
- package/dist/runtime/server/lib/oauth/paypal.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/paypal.js +5 -5
- package/dist/runtime/server/lib/oauth/polar.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/polar.js +5 -5
- package/dist/runtime/server/lib/oauth/riotgames.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/riotgames.js +5 -5
- package/dist/runtime/server/lib/oauth/roblox.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/roblox.js +4 -4
- package/dist/runtime/server/lib/oauth/salesforce.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/salesforce.js +5 -5
- package/dist/runtime/server/lib/oauth/seznam.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/seznam.js +4 -4
- package/dist/runtime/server/lib/oauth/shopifyCustomer.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/shopifyCustomer.js +7 -7
- package/dist/runtime/server/lib/oauth/slack.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/slack.js +5 -5
- package/dist/runtime/server/lib/oauth/spotify.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/spotify.js +4 -4
- package/dist/runtime/server/lib/oauth/steam.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/steam.js +7 -7
- package/dist/runtime/server/lib/oauth/strava.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/strava.js +5 -5
- package/dist/runtime/server/lib/oauth/tiktok.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/tiktok.js +5 -5
- package/dist/runtime/server/lib/oauth/twitch.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/twitch.js +5 -5
- package/dist/runtime/server/lib/oauth/vk.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/vk.js +5 -5
- package/dist/runtime/server/lib/oauth/wechat.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/wechat.js +7 -7
- package/dist/runtime/server/lib/oauth/workos.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/workos.js +3 -4
- package/dist/runtime/server/lib/oauth/x.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/x.js +4 -4
- package/dist/runtime/server/lib/oauth/xsuaa.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/xsuaa.js +4 -4
- package/dist/runtime/server/lib/oauth/yandex.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/yandex.js +4 -4
- package/dist/runtime/server/lib/oauth/zendesk.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/zendesk.js +4 -4
- package/dist/runtime/server/lib/oauth/zitadel.d.ts +1 -1
- package/dist/runtime/server/lib/oauth/zitadel.js +6 -6
- package/dist/runtime/server/lib/utils.d.ts +8 -8
- package/dist/runtime/server/lib/utils.js +5 -7
- package/dist/runtime/server/lib/webauthn/authenticate.d.ts +1 -1
- package/dist/runtime/server/lib/webauthn/authenticate.js +7 -8
- package/dist/runtime/server/lib/webauthn/register.d.ts +2 -2
- package/dist/runtime/server/lib/webauthn/register.js +9 -10
- package/dist/runtime/server/plugins/oauth-hash.d.ts +2 -0
- package/dist/runtime/server/plugins/oauth-hash.js +8 -0
- package/dist/runtime/server/routes/atproto/client-metadata.json.get.d.ts +1 -1
- package/dist/runtime/server/routes/atproto/client-metadata.json.get.js +5 -5
- package/dist/runtime/server/utils/atproto.d.ts +2 -2
- package/dist/runtime/server/utils/atproto.js +2 -3
- package/dist/runtime/server/utils/password.js +1 -1
- package/dist/runtime/server/utils/session.d.ts +29 -16
- package/dist/runtime/server/utils/session.js +72 -29
- package/dist/runtime/types/event.d.ts +27 -3
- package/dist/runtime/types/index.d.ts +1 -1
- package/dist/runtime/types/oauth-config.d.ts +3 -3
- package/dist/runtime/types/webauthn.d.ts +14 -17
- package/package.json +10 -6
- package/dist/runtime/server/plugins/oauth.d.ts +0 -2
- package/dist/runtime/server/plugins/oauth.js +0 -16
- package/dist/runtime/server/plugins/ws.d.ts +0 -2
- package/dist/runtime/server/plugins/ws.js +0 -7
package/README.md
CHANGED
|
@@ -29,6 +29,8 @@ It has few dependencies (only from [UnJS](https://github.com/unjs)), run on mult
|
|
|
29
29
|
|
|
30
30
|
## Requirements
|
|
31
31
|
|
|
32
|
+
This module requires Nuxt 4.6 or later. If you upgrade from v0.5, read [Migrate from v0.5](#migrate-from-v05).
|
|
33
|
+
|
|
32
34
|
This module only works with a Nuxt server running as it uses server API routes (`nuxt build`).
|
|
33
35
|
|
|
34
36
|
This means that you cannot use this module with `nuxt generate`.
|
|
@@ -43,14 +45,19 @@ You can anyway use [Hybrid Rendering](#hybrid-rendering) to pre-render pages of
|
|
|
43
45
|
npx nuxi@latest module add auth-utils
|
|
44
46
|
```
|
|
45
47
|
|
|
46
|
-
2.
|
|
48
|
+
2. Set the `NUXT_APP_SECRET` env variable in production, with at least 32 characters.
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# Generate a secret
|
|
52
|
+
openssl rand -base64 32
|
|
53
|
+
```
|
|
47
54
|
|
|
48
55
|
```bash
|
|
49
56
|
# .env
|
|
50
|
-
|
|
57
|
+
NUXT_APP_SECRET=<the-generated-secret>
|
|
51
58
|
```
|
|
52
59
|
|
|
53
|
-
Nuxt Auth Utils
|
|
60
|
+
Nuxt Auth Utils seals the session cookie with a secret that it derives from the [Nuxt `appSecret`](https://nuxt.com/blog/v4-6). In development, Nuxt generates an `appSecret` for you if none is set. Builds never generate one, so you must set `NUXT_APP_SECRET` in production.
|
|
54
61
|
|
|
55
62
|
3. That's it! You can now add authentication to your Nuxt app ✨
|
|
56
63
|
|
|
@@ -122,6 +129,19 @@ interface UserSessionComposable {
|
|
|
122
129
|
|
|
123
130
|
The following helpers are auto-imported in your `server/` directory.
|
|
124
131
|
|
|
132
|
+
They accept the event of a handler defined with `defineEventHandler` from `nuxt/server`. On Nuxt 4, they also accept the event of a handler defined with the auto-imported `defineEventHandler` from h3.
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
// server/api/me.get.ts
|
|
136
|
+
import { defineEventHandler } from 'nuxt/server'
|
|
137
|
+
|
|
138
|
+
export default defineEventHandler(async (event) => {
|
|
139
|
+
const { user } = await requireUserSession(event)
|
|
140
|
+
|
|
141
|
+
return user
|
|
142
|
+
})
|
|
143
|
+
```
|
|
144
|
+
|
|
125
145
|
### Session Management
|
|
126
146
|
|
|
127
147
|
```ts
|
|
@@ -152,6 +172,9 @@ await clearUserSession(event)
|
|
|
152
172
|
|
|
153
173
|
// Require a user session (send back 401 if no `user` key in session)
|
|
154
174
|
const session = await requireUserSession(event)
|
|
175
|
+
|
|
176
|
+
// Customize the error status and message
|
|
177
|
+
const session = await requireUserSession(event, { status: 403, message: 'Forbidden' })
|
|
155
178
|
```
|
|
156
179
|
|
|
157
180
|
You can define the type for your user session by creating a type declaration file (for example, `auth.d.ts`) in your project to augment the `UserSession` type:
|
|
@@ -271,6 +294,8 @@ You can add your favorite provider by creating a new file in [src/runtime/server
|
|
|
271
294
|
Example: `~/server/routes/auth/github.get.ts`
|
|
272
295
|
|
|
273
296
|
```ts
|
|
297
|
+
import { sendRedirect } from 'nuxt/server'
|
|
298
|
+
|
|
274
299
|
export default defineOAuthGitHubEventHandler({
|
|
275
300
|
config: {
|
|
276
301
|
emailRequired: true
|
|
@@ -291,6 +316,8 @@ export default defineOAuthGitHubEventHandler({
|
|
|
291
316
|
})
|
|
292
317
|
```
|
|
293
318
|
|
|
319
|
+
The `event` given to `onSuccess` and `onError` is a `RequestEvent` from `nuxt/server`. Import the helpers you use from `nuxt/server`, for example `sendRedirect`. On Nuxt 4, the auto-imported h3 helpers also work, but TypeScript reports a type error.
|
|
320
|
+
|
|
294
321
|
Make sure to set the callback URL in your OAuth app settings as `<your-domain>/auth/github`.
|
|
295
322
|
|
|
296
323
|
If the redirect URL mismatch in production, this means that the module cannot guess the right redirect URL. You can set the `NUXT_OAUTH_<PROVIDER>_REDIRECT_URL` env variable to overwrite the default one.
|
|
@@ -450,7 +477,7 @@ export default defineWebAuthnRegisterEventHandler({
|
|
|
450
477
|
// And verify that the email is the same as the one in session
|
|
451
478
|
const session = await getUserSession(event)
|
|
452
479
|
if (session.user?.email && session.user.email !== userBody.userName) {
|
|
453
|
-
throw createError({
|
|
480
|
+
throw createError({ status: 400, message: 'Email not matching current session' })
|
|
454
481
|
}
|
|
455
482
|
|
|
456
483
|
// If he registers a new account with credentials
|
|
@@ -495,7 +522,7 @@ export default defineWebAuthnAuthenticateEventHandler({
|
|
|
495
522
|
const credentials = await useDatabase().sql`...`
|
|
496
523
|
// If no credentials are found, the authentication cannot be completed
|
|
497
524
|
if (!credentials.length)
|
|
498
|
-
throw createError({
|
|
525
|
+
throw createError({ status: 400, message: 'User not found' })
|
|
499
526
|
|
|
500
527
|
// If user is found, only allow credentials that are registered
|
|
501
528
|
// The browser will automatically try to use the credential that it knows about
|
|
@@ -509,7 +536,7 @@ export default defineWebAuthnAuthenticateEventHandler({
|
|
|
509
536
|
|
|
510
537
|
// If the credential is not found, there is no account to log in to
|
|
511
538
|
if (!credential)
|
|
512
|
-
throw createError({
|
|
539
|
+
throw createError({ status: 400, message: 'Credential not found' })
|
|
513
540
|
|
|
514
541
|
return credential
|
|
515
542
|
},
|
|
@@ -549,7 +576,7 @@ export default defineWebAuthnAuthenticateEventHandler({
|
|
|
549
576
|
> await useStorage().removeItem(`attempt:${attemptId}`)
|
|
550
577
|
>
|
|
551
578
|
> if (!challenge)
|
|
552
|
-
> throw createError({
|
|
579
|
+
> throw createError({ status: 400, message: 'Challenge expired' })
|
|
553
580
|
>
|
|
554
581
|
> return challenge
|
|
555
582
|
> },
|
|
@@ -607,7 +634,8 @@ We leverage hooks to let you extend the session data with your own data or log w
|
|
|
607
634
|
|
|
608
635
|
```ts
|
|
609
636
|
// server/plugins/session.ts
|
|
610
|
-
|
|
637
|
+
// A server plugin is a function, so this file runs on Nuxt 4 (Nitro 2) and Nuxt 5 (Nitro 3)
|
|
638
|
+
export default () => {
|
|
611
639
|
// Called when the session is fetched during SSR for the Vue composable (/api/_auth/session)
|
|
612
640
|
// Or when we call useUserSession().fetch()
|
|
613
641
|
sessionHooks.hook('fetch', async (session, event) => {
|
|
@@ -620,7 +648,7 @@ export default defineNitroPlugin(() => {
|
|
|
620
648
|
sessionHooks.hook('clear', async (session, event) => {
|
|
621
649
|
// Log that user logged out
|
|
622
650
|
})
|
|
623
|
-
}
|
|
651
|
+
}
|
|
624
652
|
```
|
|
625
653
|
|
|
626
654
|
## Server-Side Rendering
|
|
@@ -728,10 +756,13 @@ export default defineNuxtConfig({
|
|
|
728
756
|
})
|
|
729
757
|
```
|
|
730
758
|
|
|
731
|
-
You can use the `requireUserSession` function in the `upgrade` function to check if the user is authenticated before upgrading the WebSocket connection.
|
|
759
|
+
You can use the `requireUserSession` function in the `upgrade` function to check if the user is authenticated before upgrading the WebSocket connection. In WebSocket handlers, the session is read-only: `setUserSession`, `replaceUserSession` and `clearUserSession` throw an error when given a WebSocket peer or upgrade request.
|
|
732
760
|
|
|
733
761
|
```ts
|
|
734
762
|
// server/routes/ws.ts
|
|
763
|
+
// `defineWebSocketHandler` is not auto-imported on Nuxt 5, `h3` works on Nuxt 4 and Nuxt 5
|
|
764
|
+
import { defineWebSocketHandler } from 'h3'
|
|
765
|
+
|
|
735
766
|
export default defineWebSocketHandler({
|
|
736
767
|
async upgrade(request) {
|
|
737
768
|
// Make sure the user is authenticated before upgrading the WebSocket connection
|
|
@@ -773,7 +804,7 @@ onMounted(open)
|
|
|
773
804
|
|
|
774
805
|
## Configuration
|
|
775
806
|
|
|
776
|
-
|
|
807
|
+
Nuxt Auth Utils stores the user session with `useSession` from `nuxt/server`. It uses `runtimeConfig.session` for the default options.
|
|
777
808
|
|
|
778
809
|
You can overwrite the options in your `nuxt.config.ts`:
|
|
779
810
|
|
|
@@ -792,14 +823,21 @@ Our defaults are:
|
|
|
792
823
|
|
|
793
824
|
```ts
|
|
794
825
|
{
|
|
795
|
-
name: 'nuxt-session',
|
|
796
|
-
password: process.env.NUXT_SESSION_PASSWORD || '',
|
|
826
|
+
name: 'nuxt-auth-session',
|
|
797
827
|
cookie: {
|
|
798
828
|
sameSite: 'lax'
|
|
799
829
|
}
|
|
800
830
|
}
|
|
801
831
|
```
|
|
802
832
|
|
|
833
|
+
The available options are:
|
|
834
|
+
|
|
835
|
+
- `name`: the name of the session cookie.
|
|
836
|
+
- `maxAge`: the lifetime of the cookie and of the sealed session, in seconds.
|
|
837
|
+
- `cookie`: the cookie options, merged over `httpOnly: true`, `secure: true`, `sameSite: 'lax'`, and `path: '/'`.
|
|
838
|
+
|
|
839
|
+
The session is sealed with a secret that Nuxt derives from `appSecret`. The module ignores `runtimeConfig.session.password`.
|
|
840
|
+
|
|
803
841
|
You can also overwrite the session config by passing it as 3rd argument of the `setUserSession` and `replaceUserSession` functions:
|
|
804
842
|
|
|
805
843
|
```ts
|
|
@@ -808,11 +846,41 @@ await setUserSession(event, { ... } , {
|
|
|
808
846
|
})
|
|
809
847
|
```
|
|
810
848
|
|
|
811
|
-
|
|
849
|
+
## Migrate from v0.5
|
|
850
|
+
|
|
851
|
+
Nuxt Auth Utils v0.6 moves to `nuxt/server`, the server API of Nuxt 4.6. The same server code runs on Nuxt 4 and Nuxt 5. This release has breaking changes.
|
|
852
|
+
|
|
853
|
+
> [!WARNING]
|
|
854
|
+
> All users are logged out once after the upgrade. The session cookie has a new name and a new format.
|
|
855
|
+
|
|
856
|
+
To migrate your app, follow these steps:
|
|
857
|
+
|
|
858
|
+
1. Upgrade Nuxt to 4.6 or later.
|
|
859
|
+
2. Generate a secret with `openssl rand -base64 32`.
|
|
860
|
+
3. Set the secret as `NUXT_APP_SECRET` in your production environment.
|
|
861
|
+
4. On Cloudflare Workers, set `compatibility_date` to `2025-04-01` or later, or add the `nodejs_compat_populate_process_env` compatibility flag. Otherwise the module can't read `NUXT_APP_SECRET` and the `NUXT_OAUTH_*` variables from your Worker variables and secrets.
|
|
862
|
+
5. Remove `NUXT_SESSION_PASSWORD` from your environment and from your `.env` file. The module logs a warning while it is set.
|
|
863
|
+
6. Change `statusCode` to `status` in `createError()` calls.
|
|
864
|
+
7. In `onSuccess` and `onError` callbacks, import helpers such as `sendRedirect` from `nuxt/server`.
|
|
865
|
+
|
|
866
|
+
The other changes in v0.6 are:
|
|
867
|
+
|
|
868
|
+
- The session cookie is `nuxt-auth-session`. It was `nuxt-session`, which is now the default name of `useSession` from `nuxt/server`.
|
|
869
|
+
- The session can't be read from the `x-nuxt-session-session` request header anymore.
|
|
870
|
+
- The `sessionHeader`, `seal`, `crypto`, `generateId`, and `password` session options are removed.
|
|
871
|
+
- The `event` in the OAuth and WebAuthn callbacks is a `RequestEvent` from `nuxt/server`, and `error` is a `NuxtError`.
|
|
872
|
+
- In WebSocket handlers, `setUserSession`, `replaceUserSession` and `clearUserSession` throw an error, as the session cookie can't be sent back to the client.
|
|
873
|
+
- `requireUserSession` accepts a `status` option. The `statusCode` option still works, but it's deprecated.
|
|
874
|
+
- Nuxt throws a 500 error if a session cookie is larger than 4096 bytes.
|
|
875
|
+
- The session `maxAge` counts from the last write: each `setUserSession` call extends the cookie. In v0.5, it counted from when the session was created.
|
|
876
|
+
- The session can't be named `nuxt-session`, the cookie of `useSession()` from `nuxt/server`. The module warns and uses `nuxt-auth-session` instead.
|
|
877
|
+
- WebAuthn requires SimpleWebAuthn v13, with `@simplewebauthn/server` 13.3.2 or later. Import its JSON types from `@simplewebauthn/server` or `@simplewebauthn/browser` instead of `@simplewebauthn/types`.
|
|
812
878
|
|
|
813
879
|
## Shared session between microservices and subdomains
|
|
814
880
|
|
|
815
|
-
To share a session between multiple applications, use the same `
|
|
881
|
+
To share a session between multiple applications, use the same `NUXT_APP_SECRET` and session `name` in each of them.
|
|
882
|
+
|
|
883
|
+
Any application with the same `NUXT_APP_SECRET` can also derive the other keys Nuxt derives from it, so share it only between applications you trust equally.
|
|
816
884
|
|
|
817
885
|
If the applications run on different subdomains, also set the session cookie `domain` to the parent domain in each `nuxt.config.ts`:
|
|
818
886
|
|
|
@@ -847,6 +915,12 @@ pnpm run dev:prepare
|
|
|
847
915
|
# Develop with the playground
|
|
848
916
|
pnpm run dev
|
|
849
917
|
|
|
918
|
+
# Develop with the playground on the Nuxt 5 nightly (Nitro 3), run `pnpm install` to go back to the lockfile
|
|
919
|
+
pnpm run dev:v5
|
|
920
|
+
|
|
921
|
+
# Run the tests on the Nuxt 5 nightly
|
|
922
|
+
pnpm run install:nuxt5 && pnpm run dev:prepare && pnpm run test
|
|
923
|
+
|
|
850
924
|
# Build the playground
|
|
851
925
|
pnpm run dev:build
|
|
852
926
|
|
package/dist/module.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ScryptConfig } from '@adonisjs/hash/types';
|
|
2
|
-
import { SessionConfig } from '
|
|
2
|
+
import { SessionConfig } from 'nuxt/server';
|
|
3
3
|
|
|
4
4
|
interface ModuleOptions {
|
|
5
5
|
/**
|
|
@@ -33,9 +33,9 @@ declare module 'nuxt/schema' {
|
|
|
33
33
|
scrypt: ScryptConfig;
|
|
34
34
|
};
|
|
35
35
|
/**
|
|
36
|
-
* Session configuration
|
|
36
|
+
* Session configuration, the session is sealed with a secret derived from `appSecret` (`NUXT_APP_SECRET`)
|
|
37
37
|
*/
|
|
38
|
-
session: SessionConfig
|
|
38
|
+
session: Omit<SessionConfig, 'password'>;
|
|
39
39
|
}
|
|
40
40
|
interface PublicRuntimeConfig {
|
|
41
41
|
auth: {
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { defineNuxtModule, createResolver, addComponentsDir, addImports, addPlugin, addServerPlugin, addServerImportsDir, logger, addServerHandler } from '@nuxt/kit';
|
|
1
|
+
import { defineNuxtModule, createResolver, addComponentsDir, addImports, addPlugin, addServerPlugin, addServerImportsDir, logger, addServerHandler, getNitroVersion } from '@nuxt/kit';
|
|
2
2
|
import { defu } from 'defu';
|
|
3
|
-
import { readFile, writeFile } from 'node:fs/promises';
|
|
4
|
-
import { join } from 'pathe';
|
|
5
|
-
import { randomUUID } from 'uncrypto';
|
|
6
3
|
import { atprotoProviders, atprotoProviderDefaultClientMetadata, getClientMetadataFilename } from '../dist/runtime/utils/atproto.js';
|
|
7
4
|
|
|
8
5
|
const module$1 = defineNuxtModule({
|
|
9
6
|
meta: {
|
|
10
7
|
name: "auth-utils",
|
|
11
|
-
configKey: "auth"
|
|
8
|
+
configKey: "auth",
|
|
9
|
+
compatibility: {
|
|
10
|
+
nuxt: ">=4.6.0"
|
|
11
|
+
}
|
|
12
12
|
},
|
|
13
13
|
// Default configuration options of the Nuxt module
|
|
14
14
|
defaults: {
|
|
@@ -36,11 +36,8 @@ const module$1 = defineNuxtModule({
|
|
|
36
36
|
addPlugin(resolver.resolve("./runtime/app/plugins/session.server"));
|
|
37
37
|
addPlugin(resolver.resolve("./runtime/app/plugins/session.client"));
|
|
38
38
|
}
|
|
39
|
-
addServerPlugin(resolver.resolve("./runtime/server/plugins/oauth"));
|
|
39
|
+
addServerPlugin(resolver.resolve("./runtime/server/plugins/oauth-hash"));
|
|
40
40
|
addServerImportsDir(resolver.resolve("./runtime/server/lib/oauth"));
|
|
41
|
-
if (nuxt.options.nitro?.experimental?.websocket) {
|
|
42
|
-
addServerPlugin(resolver.resolve("./runtime/server/plugins/ws"));
|
|
43
|
-
}
|
|
44
41
|
if (options.webAuthn) {
|
|
45
42
|
const missingDeps = [];
|
|
46
43
|
const peerDeps = ["@simplewebauthn/server", "@simplewebauthn/browser"];
|
|
@@ -68,16 +65,22 @@ const module$1 = defineNuxtModule({
|
|
|
68
65
|
route: "/api/_auth/session",
|
|
69
66
|
method: "get"
|
|
70
67
|
});
|
|
71
|
-
nuxt
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
if (getNitroVersion(nuxt) === 2) {
|
|
69
|
+
const nitroOptions = nuxt.options.nitro;
|
|
70
|
+
nitroOptions.unenv ||= {};
|
|
71
|
+
nitroOptions.unenv.external ||= [];
|
|
72
|
+
if (!nitroOptions.unenv.external.includes("node:crypto")) {
|
|
73
|
+
nitroOptions.unenv.external.push("node:crypto");
|
|
74
|
+
}
|
|
75
75
|
}
|
|
76
76
|
const runtimeConfig = nuxt.options.runtimeConfig;
|
|
77
77
|
const envSessionPassword = `${runtimeConfig.nitro?.envPrefix || "NUXT_"}SESSION_PASSWORD`;
|
|
78
|
+
if (process.env[envSessionPassword] || runtimeConfig.session?.password) {
|
|
79
|
+
logger.withTag("nuxt-auth-utils").warn(`\`${envSessionPassword}\` (\`runtimeConfig.session.password\`) is not used anymore. Set \`NUXT_APP_SECRET\` instead, for example with \`openssl rand -base64 32\`. Sessions are now sealed with a secret derived from \`appSecret\`, so users are logged out once.`);
|
|
80
|
+
}
|
|
78
81
|
runtimeConfig.session = defu(runtimeConfig.session, {
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
// Declared so `NUXT_SESSION_NAME` can override it at runtime
|
|
83
|
+
name: "nuxt-auth-session",
|
|
81
84
|
cookie: {
|
|
82
85
|
sameSite: "lax"
|
|
83
86
|
}
|
|
@@ -85,22 +88,6 @@ const module$1 = defineNuxtModule({
|
|
|
85
88
|
runtimeConfig.hash = defu(runtimeConfig.hash, {
|
|
86
89
|
scrypt: options.hash?.scrypt
|
|
87
90
|
});
|
|
88
|
-
if (nuxt.options.dev && !process.env[envSessionPassword]) {
|
|
89
|
-
if (nuxt.options.runtimeConfig.session.password) {
|
|
90
|
-
process.env[envSessionPassword] = nuxt.options.runtimeConfig.session.password;
|
|
91
|
-
} else {
|
|
92
|
-
const password = process.env[envSessionPassword] = randomUUID().replace(/-/g, "");
|
|
93
|
-
const envPath = join(nuxt.options.rootDir, ".env");
|
|
94
|
-
const envContent = await readFile(envPath, "utf-8").catch(() => "");
|
|
95
|
-
if (!envContent.includes(envSessionPassword)) {
|
|
96
|
-
await writeFile(
|
|
97
|
-
envPath,
|
|
98
|
-
`${envContent ? envContent + "\n" : envContent}${envSessionPassword}=${password}`,
|
|
99
|
-
"utf-8"
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
91
|
runtimeConfig.public.auth = defu(runtimeConfig.public.auth, {
|
|
105
92
|
loadStrategy: options.loadStrategy ?? "server-first"
|
|
106
93
|
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { appendResponseHeader } from "h3";
|
|
2
1
|
import { useState, computed, useRequestFetch, useRequestEvent } from "#imports";
|
|
3
2
|
export function useUserSession() {
|
|
4
3
|
const serverEvent = import.meta.server ? useRequestEvent() : null;
|
|
@@ -10,8 +9,10 @@ export function useUserSession() {
|
|
|
10
9
|
method: "DELETE",
|
|
11
10
|
onResponse({ response: { headers } }) {
|
|
12
11
|
if (import.meta.server && serverEvent) {
|
|
12
|
+
const res = serverEvent.res;
|
|
13
13
|
for (const setCookie of headers.getSetCookie()) {
|
|
14
|
-
|
|
14
|
+
if (res.headers) res.headers.append("set-cookie", setCookie);
|
|
15
|
+
else res.appendHeader?.("set-cookie", setCookie);
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineEventHandler } from "nuxt/server";
|
|
2
2
|
import { clearUserSession } from "../utils/session.js";
|
|
3
|
-
export default
|
|
3
|
+
export default defineEventHandler(async (event) => {
|
|
4
4
|
await clearUserSession(event);
|
|
5
5
|
return { loggedOut: true };
|
|
6
6
|
});
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("
|
|
1
|
+
declare const _default: import("nuxt/server").EventHandler<Promise<UserSession>>;
|
|
2
2
|
export default _default;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineEventHandler } from "nuxt/server";
|
|
2
2
|
import { getUserSession, sessionHooks } from "../utils/session.js";
|
|
3
|
-
export default
|
|
3
|
+
export default defineEventHandler(async (event) => {
|
|
4
4
|
const session = await getUserSession(event);
|
|
5
5
|
if (Object.keys(session).length > 0) {
|
|
6
6
|
await sessionHooks.callHookParallel("fetch", session, event);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RequestEvent } from 'nuxt/server';
|
|
2
2
|
import type { NodeSavedSession, NodeSavedSessionStore, NodeSavedState, NodeSavedStateStore } from '@atproto/oauth-client-node';
|
|
3
3
|
import type { AppBskyActorDefs } from '@atproto/api';
|
|
4
4
|
import type { OAuthConfig } from '#auth-utils';
|
|
@@ -22,11 +22,11 @@ type BlueSkyTokens = NodeSavedSession['tokenSet'];
|
|
|
22
22
|
export declare function defineOAuthBlueskyEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthBlueskyConfig, {
|
|
23
23
|
user: BlueSkyUser;
|
|
24
24
|
tokens: BlueSkyTokens;
|
|
25
|
-
}>): import("
|
|
25
|
+
}>): import("nuxt/server").EventHandler<Promise<any>>;
|
|
26
26
|
export declare class StateStore implements NodeSavedStateStore {
|
|
27
27
|
private event;
|
|
28
28
|
private readonly stateKey;
|
|
29
|
-
constructor(event:
|
|
29
|
+
constructor(event: RequestEvent);
|
|
30
30
|
get(): Promise<NodeSavedState | undefined>;
|
|
31
31
|
set(key: string, val: NodeSavedState): Promise<void>;
|
|
32
32
|
del(): Promise<void>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { createError,
|
|
1
|
+
import { defineEventHandler, createError, deleteCookie, getCookie, getQuery, sendRedirect, setCookie } from "nuxt/server";
|
|
2
2
|
import { NodeOAuthClient, OAuthCallbackError, OAuthResolverError, OAuthResponseError } from "@atproto/oauth-client-node";
|
|
3
3
|
import { Agent } from "@atproto/api";
|
|
4
4
|
import { getAtprotoClientMetadata } from "../../utils/atproto.js";
|
|
5
5
|
export function defineOAuthBlueskyEventHandler({ config, onSuccess, onError }) {
|
|
6
|
-
return
|
|
6
|
+
return defineEventHandler(async (event) => {
|
|
7
7
|
const clientMetadata = getAtprotoClientMetadata(event, "bluesky", config);
|
|
8
8
|
const scopes = clientMetadata.scope?.split(" ") ?? [];
|
|
9
9
|
const sessionStore = new SessionStore();
|
|
@@ -18,7 +18,7 @@ export function defineOAuthBlueskyEventHandler({ config, onSuccess, onError }) {
|
|
|
18
18
|
try {
|
|
19
19
|
const handle = query.handle?.toString();
|
|
20
20
|
if (!handle) throw createError({
|
|
21
|
-
|
|
21
|
+
status: 400,
|
|
22
22
|
message: "Query parameter `handle` empty or missing. Please provide a valid Bluesky handle."
|
|
23
23
|
});
|
|
24
24
|
const url = await client.authorize(handle, { scope: clientMetadata.scope });
|
|
@@ -28,13 +28,13 @@ export function defineOAuthBlueskyEventHandler({ config, onSuccess, onError }) {
|
|
|
28
28
|
switch (true) {
|
|
29
29
|
case err instanceof OAuthResponseError:
|
|
30
30
|
return createError({
|
|
31
|
-
|
|
31
|
+
status: 500,
|
|
32
32
|
message: `Bluesky login failed: ${err.errorDescription || "Unknown error"}`,
|
|
33
33
|
data: err.payload
|
|
34
34
|
});
|
|
35
35
|
case err instanceof OAuthResolverError:
|
|
36
36
|
return createError({
|
|
37
|
-
|
|
37
|
+
status: 400,
|
|
38
38
|
message: `Bluesky login failed: ${err.message || "Unknown error"}`
|
|
39
39
|
});
|
|
40
40
|
default:
|
|
@@ -57,7 +57,7 @@ export function defineOAuthBlueskyEventHandler({ config, onSuccess, onError }) {
|
|
|
57
57
|
} catch (err) {
|
|
58
58
|
if (!(err instanceof OAuthCallbackError)) throw err;
|
|
59
59
|
const error = createError({
|
|
60
|
-
|
|
60
|
+
status: 500,
|
|
61
61
|
message: `Bluesky login failed: ${err.message || "Unknown error"}`
|
|
62
62
|
});
|
|
63
63
|
if (!onError) throw error;
|
|
@@ -74,4 +74,4 @@ export declare function defineOAuthAppleEventHandler({ config, onSuccess, onErro
|
|
|
74
74
|
user: OAuthAppleUser;
|
|
75
75
|
payload: OAuthAppleTokens;
|
|
76
76
|
tokens: any;
|
|
77
|
-
}>): import("
|
|
77
|
+
}>): import("nuxt/server").EventHandler<Promise<any>>;
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineEventHandler, getRequestHeader, readBody, sendRedirect, useRuntimeConfig } from "nuxt/server";
|
|
2
2
|
import { withQuery } from "ufo";
|
|
3
3
|
import { defu } from "defu";
|
|
4
4
|
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, handleInvalidState, handleState, requestAccessToken, signJwt, verifyJwt } from "../utils.js";
|
|
5
|
-
import { useRuntimeConfig } from "#imports";
|
|
6
5
|
export function defineOAuthAppleEventHandler({
|
|
7
6
|
config,
|
|
8
7
|
onSuccess,
|
|
9
8
|
onError
|
|
10
9
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
10
|
}) {
|
|
12
|
-
return
|
|
13
|
-
config = defu(config, useRuntimeConfig(
|
|
11
|
+
return defineEventHandler(async (event) => {
|
|
12
|
+
config = defu(config, useRuntimeConfig().oauth?.apple, {
|
|
14
13
|
authorizationURL: config?.authorizationURL || "https://appleid.apple.com/auth/authorize",
|
|
15
14
|
authorizationParams: {}
|
|
16
15
|
});
|
|
@@ -91,5 +91,5 @@ export interface OAuthAtlassianConfig {
|
|
|
91
91
|
export declare function defineOAuthAtlassianEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthAtlassianConfig, {
|
|
92
92
|
user: AtlassianUser;
|
|
93
93
|
tokens: AtlassianTokens;
|
|
94
|
-
}>): import("
|
|
94
|
+
}>): import("nuxt/server").EventHandler<Promise<any>>;
|
|
95
95
|
export {};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineEventHandler, createError, getQuery, sendRedirect, useRuntimeConfig } from "nuxt/server";
|
|
2
|
+
import { $fetch } from "ofetch";
|
|
2
3
|
import { withQuery } from "ufo";
|
|
3
4
|
import { defu } from "defu";
|
|
4
5
|
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, handleInvalidState, handleState, requestAccessToken } from "../utils.js";
|
|
5
|
-
import { useRuntimeConfig, createError } from "#imports";
|
|
6
6
|
export function defineOAuthAtlassianEventHandler({
|
|
7
7
|
config,
|
|
8
8
|
onSuccess,
|
|
9
9
|
onError
|
|
10
10
|
}) {
|
|
11
|
-
return
|
|
11
|
+
return defineEventHandler(async (event) => {
|
|
12
12
|
config = defu(config, useRuntimeConfig().oauth?.atlassian, {
|
|
13
13
|
authorizationURL: "https://auth.atlassian.com/authorize",
|
|
14
14
|
tokenURL: "https://auth.atlassian.com/oauth/token",
|
|
@@ -45,7 +45,7 @@ export function defineOAuthAtlassianEventHandler({
|
|
|
45
45
|
}
|
|
46
46
|
if (query.error) {
|
|
47
47
|
const error = createError({
|
|
48
|
-
|
|
48
|
+
status: 401,
|
|
49
49
|
message: `Atlassian login failed: ${query.error || "Unknown error"}`,
|
|
50
50
|
data: query
|
|
51
51
|
});
|
|
@@ -78,8 +78,8 @@ export function defineOAuthAtlassianEventHandler({
|
|
|
78
78
|
});
|
|
79
79
|
if (user.account_status === "inactive") {
|
|
80
80
|
const error = createError({
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
status: 403,
|
|
82
|
+
message: "Atlassian account is inactive",
|
|
83
83
|
data: { accountStatus: user.account_status }
|
|
84
84
|
});
|
|
85
85
|
if (!onError) throw error;
|
|
@@ -87,8 +87,8 @@ export function defineOAuthAtlassianEventHandler({
|
|
|
87
87
|
}
|
|
88
88
|
if (!user.email_verified) {
|
|
89
89
|
const error = createError({
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
status: 400,
|
|
91
|
+
message: "Email address is not verified",
|
|
92
92
|
data: { email: user.email }
|
|
93
93
|
});
|
|
94
94
|
if (!onError) throw error;
|
|
@@ -57,4 +57,4 @@ export interface OAuthAuth0Config {
|
|
|
57
57
|
*/
|
|
58
58
|
redirectURL?: string;
|
|
59
59
|
}
|
|
60
|
-
export declare function defineOAuthAuth0EventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthAuth0Config>): import("
|
|
60
|
+
export declare function defineOAuthAuth0EventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthAuth0Config>): import("nuxt/server").EventHandler<Promise<any>>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineEventHandler, getQuery, sendRedirect, useRuntimeConfig } from "nuxt/server";
|
|
2
|
+
import { $fetch } from "ofetch";
|
|
2
3
|
import { withQuery } from "ufo";
|
|
3
4
|
import { defu } from "defu";
|
|
4
5
|
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, handleInvalidState, handleState, requestAccessToken } from "../utils.js";
|
|
5
|
-
import { useRuntimeConfig } from "#imports";
|
|
6
6
|
export function defineOAuthAuth0EventHandler({ config, onSuccess, onError }) {
|
|
7
|
-
return
|
|
8
|
-
config = defu(config, useRuntimeConfig(
|
|
7
|
+
return defineEventHandler(async (event) => {
|
|
8
|
+
config = defu(config, useRuntimeConfig().oauth?.auth0, {
|
|
9
9
|
authorizationParams: {}
|
|
10
10
|
});
|
|
11
11
|
if (!config.clientId || !config.clientSecret || !config.domain) {
|
|
@@ -27,4 +27,4 @@ export interface OAuthAuthentikConfig {
|
|
|
27
27
|
*/
|
|
28
28
|
scope?: string[];
|
|
29
29
|
}
|
|
30
|
-
export declare function defineOAuthAuthentikEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthAuthentikConfig>): import("
|
|
30
|
+
export declare function defineOAuthAuthentikEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthAuthentikConfig>): import("nuxt/server").EventHandler<Promise<any>>;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineEventHandler, createError, getQuery, sendRedirect, useRuntimeConfig } from "nuxt/server";
|
|
2
|
+
import { $fetch } from "ofetch";
|
|
2
3
|
import { withQuery } from "ufo";
|
|
3
4
|
import { defu } from "defu";
|
|
4
5
|
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, handleInvalidState, handleState, requestAccessToken } from "../utils.js";
|
|
5
|
-
import { useRuntimeConfig, createError } from "#imports";
|
|
6
6
|
export function defineOAuthAuthentikEventHandler({ config, onSuccess, onError }) {
|
|
7
|
-
return
|
|
8
|
-
config = defu(config, useRuntimeConfig(
|
|
7
|
+
return defineEventHandler(async (event) => {
|
|
8
|
+
config = defu(config, useRuntimeConfig().oauth?.authentik);
|
|
9
9
|
const query = getQuery(event);
|
|
10
10
|
if (query.error) {
|
|
11
11
|
const error = createError({
|
|
12
|
-
|
|
12
|
+
status: 401,
|
|
13
13
|
message: `Authentik login failed: ${query.error || "Unknown error"}`,
|
|
14
14
|
data: query
|
|
15
15
|
});
|
|
@@ -62,7 +62,7 @@ export function defineOAuthAuthentikEventHandler({ config, onSuccess, onError })
|
|
|
62
62
|
});
|
|
63
63
|
if (!user) {
|
|
64
64
|
const error = createError({
|
|
65
|
-
|
|
65
|
+
status: 500,
|
|
66
66
|
message: "Could not get Authentik user",
|
|
67
67
|
data: tokens
|
|
68
68
|
});
|
|
@@ -51,4 +51,4 @@ export interface OAuthAzureB2CConfig {
|
|
|
51
51
|
*/
|
|
52
52
|
redirectURL?: string;
|
|
53
53
|
}
|
|
54
|
-
export declare function defineOAuthAzureB2CEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthAzureB2CConfig>): import("
|
|
54
|
+
export declare function defineOAuthAzureB2CEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthAzureB2CConfig>): import("nuxt/server").EventHandler<Promise<any>>;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { defineEventHandler, createError, getQuery, sendRedirect, useRuntimeConfig } from "nuxt/server";
|
|
2
|
+
import { $fetch } from "ofetch";
|
|
2
3
|
import { withQuery } from "ufo";
|
|
3
4
|
import { defu } from "defu";
|
|
4
5
|
import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, requestAccessToken, handlePkceVerifier, handleState, handleInvalidState } from "../utils.js";
|
|
5
|
-
import { useRuntimeConfig, createError } from "#imports";
|
|
6
6
|
export function defineOAuthAzureB2CEventHandler({ config, onSuccess, onError }) {
|
|
7
|
-
return
|
|
8
|
-
config = defu(config, useRuntimeConfig(
|
|
7
|
+
return defineEventHandler(async (event) => {
|
|
8
|
+
config = defu(config, useRuntimeConfig().oauth?.azureb2c, {
|
|
9
9
|
authorizationParams: {}
|
|
10
10
|
});
|
|
11
11
|
const query = getQuery(event);
|
|
@@ -63,7 +63,7 @@ export function defineOAuthAzureB2CEventHandler({ config, onSuccess, onError })
|
|
|
63
63
|
});
|
|
64
64
|
if (user.error) {
|
|
65
65
|
const error = createError({
|
|
66
|
-
|
|
66
|
+
status: 401,
|
|
67
67
|
message: `azureb2c login failed: ${user.error || "Unknown error"}`,
|
|
68
68
|
data: user
|
|
69
69
|
});
|