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.
Files changed (139) hide show
  1. package/README.md +89 -15
  2. package/dist/module.d.mts +3 -3
  3. package/dist/module.json +4 -1
  4. package/dist/module.mjs +18 -31
  5. package/dist/runtime/app/composables/session.js +3 -2
  6. package/dist/runtime/server/api/session.delete.d.ts +1 -1
  7. package/dist/runtime/server/api/session.delete.js +2 -2
  8. package/dist/runtime/server/api/session.get.d.ts +1 -1
  9. package/dist/runtime/server/api/session.get.js +2 -2
  10. package/dist/runtime/server/lib/atproto/bluesky.d.ts +3 -3
  11. package/dist/runtime/server/lib/atproto/bluesky.js +6 -6
  12. package/dist/runtime/server/lib/oauth/apple.d.ts +1 -1
  13. package/dist/runtime/server/lib/oauth/apple.js +3 -4
  14. package/dist/runtime/server/lib/oauth/atlassian.d.ts +1 -1
  15. package/dist/runtime/server/lib/oauth/atlassian.js +8 -8
  16. package/dist/runtime/server/lib/oauth/auth0.d.ts +1 -1
  17. package/dist/runtime/server/lib/oauth/auth0.js +4 -4
  18. package/dist/runtime/server/lib/oauth/authentik.d.ts +1 -1
  19. package/dist/runtime/server/lib/oauth/authentik.js +6 -6
  20. package/dist/runtime/server/lib/oauth/azureb2c.d.ts +1 -1
  21. package/dist/runtime/server/lib/oauth/azureb2c.js +5 -5
  22. package/dist/runtime/server/lib/oauth/battledotnet.d.ts +1 -1
  23. package/dist/runtime/server/lib/oauth/battledotnet.js +6 -6
  24. package/dist/runtime/server/lib/oauth/box.d.ts +1 -1
  25. package/dist/runtime/server/lib/oauth/box.js +5 -5
  26. package/dist/runtime/server/lib/oauth/cloudflare.d.ts +1 -1
  27. package/dist/runtime/server/lib/oauth/cloudflare.js +5 -5
  28. package/dist/runtime/server/lib/oauth/cognito.d.ts +1 -1
  29. package/dist/runtime/server/lib/oauth/cognito.js +4 -4
  30. package/dist/runtime/server/lib/oauth/discord.d.ts +1 -1
  31. package/dist/runtime/server/lib/oauth/discord.js +4 -4
  32. package/dist/runtime/server/lib/oauth/dropbox.d.ts +1 -1
  33. package/dist/runtime/server/lib/oauth/dropbox.js +5 -5
  34. package/dist/runtime/server/lib/oauth/facebook.d.ts +1 -1
  35. package/dist/runtime/server/lib/oauth/facebook.js +7 -7
  36. package/dist/runtime/server/lib/oauth/gitea.d.ts +1 -1
  37. package/dist/runtime/server/lib/oauth/gitea.js +5 -5
  38. package/dist/runtime/server/lib/oauth/github.d.ts +1 -1
  39. package/dist/runtime/server/lib/oauth/github.js +6 -6
  40. package/dist/runtime/server/lib/oauth/gitlab.d.ts +1 -1
  41. package/dist/runtime/server/lib/oauth/gitlab.js +5 -5
  42. package/dist/runtime/server/lib/oauth/google.d.ts +1 -1
  43. package/dist/runtime/server/lib/oauth/google.js +4 -4
  44. package/dist/runtime/server/lib/oauth/heroku.d.ts +1 -1
  45. package/dist/runtime/server/lib/oauth/heroku.js +5 -5
  46. package/dist/runtime/server/lib/oauth/hubspot.d.ts +1 -1
  47. package/dist/runtime/server/lib/oauth/hubspot.js +4 -4
  48. package/dist/runtime/server/lib/oauth/instagram.d.ts +1 -1
  49. package/dist/runtime/server/lib/oauth/instagram.js +6 -6
  50. package/dist/runtime/server/lib/oauth/keycloak.d.ts +1 -1
  51. package/dist/runtime/server/lib/oauth/keycloak.js +6 -6
  52. package/dist/runtime/server/lib/oauth/kick.d.ts +1 -1
  53. package/dist/runtime/server/lib/oauth/kick.js +5 -5
  54. package/dist/runtime/server/lib/oauth/line.d.ts +1 -1
  55. package/dist/runtime/server/lib/oauth/line.js +6 -6
  56. package/dist/runtime/server/lib/oauth/linear.d.ts +1 -1
  57. package/dist/runtime/server/lib/oauth/linear.js +6 -6
  58. package/dist/runtime/server/lib/oauth/linkedin.d.ts +1 -1
  59. package/dist/runtime/server/lib/oauth/linkedin.js +4 -4
  60. package/dist/runtime/server/lib/oauth/livechat.d.ts +1 -1
  61. package/dist/runtime/server/lib/oauth/livechat.js +4 -4
  62. package/dist/runtime/server/lib/oauth/mastodon.d.ts +1 -1
  63. package/dist/runtime/server/lib/oauth/mastodon.js +8 -9
  64. package/dist/runtime/server/lib/oauth/microsoft.d.ts +1 -1
  65. package/dist/runtime/server/lib/oauth/microsoft.js +5 -5
  66. package/dist/runtime/server/lib/oauth/oidc.d.ts +1 -1
  67. package/dist/runtime/server/lib/oauth/oidc.js +6 -6
  68. package/dist/runtime/server/lib/oauth/okta.d.ts +4 -4
  69. package/dist/runtime/server/lib/oauth/okta.js +8 -8
  70. package/dist/runtime/server/lib/oauth/ory.d.ts +1 -1
  71. package/dist/runtime/server/lib/oauth/ory.js +6 -6
  72. package/dist/runtime/server/lib/oauth/osu.d.ts +1 -1
  73. package/dist/runtime/server/lib/oauth/osu.js +4 -4
  74. package/dist/runtime/server/lib/oauth/paypal.d.ts +1 -1
  75. package/dist/runtime/server/lib/oauth/paypal.js +5 -5
  76. package/dist/runtime/server/lib/oauth/polar.d.ts +1 -1
  77. package/dist/runtime/server/lib/oauth/polar.js +5 -5
  78. package/dist/runtime/server/lib/oauth/riotgames.d.ts +1 -1
  79. package/dist/runtime/server/lib/oauth/riotgames.js +5 -5
  80. package/dist/runtime/server/lib/oauth/roblox.d.ts +1 -1
  81. package/dist/runtime/server/lib/oauth/roblox.js +4 -4
  82. package/dist/runtime/server/lib/oauth/salesforce.d.ts +1 -1
  83. package/dist/runtime/server/lib/oauth/salesforce.js +5 -5
  84. package/dist/runtime/server/lib/oauth/seznam.d.ts +1 -1
  85. package/dist/runtime/server/lib/oauth/seznam.js +4 -4
  86. package/dist/runtime/server/lib/oauth/shopifyCustomer.d.ts +1 -1
  87. package/dist/runtime/server/lib/oauth/shopifyCustomer.js +7 -7
  88. package/dist/runtime/server/lib/oauth/slack.d.ts +1 -1
  89. package/dist/runtime/server/lib/oauth/slack.js +5 -5
  90. package/dist/runtime/server/lib/oauth/spotify.d.ts +1 -1
  91. package/dist/runtime/server/lib/oauth/spotify.js +4 -4
  92. package/dist/runtime/server/lib/oauth/steam.d.ts +1 -1
  93. package/dist/runtime/server/lib/oauth/steam.js +7 -7
  94. package/dist/runtime/server/lib/oauth/strava.d.ts +1 -1
  95. package/dist/runtime/server/lib/oauth/strava.js +5 -5
  96. package/dist/runtime/server/lib/oauth/tiktok.d.ts +1 -1
  97. package/dist/runtime/server/lib/oauth/tiktok.js +5 -5
  98. package/dist/runtime/server/lib/oauth/twitch.d.ts +1 -1
  99. package/dist/runtime/server/lib/oauth/twitch.js +5 -5
  100. package/dist/runtime/server/lib/oauth/vk.d.ts +1 -1
  101. package/dist/runtime/server/lib/oauth/vk.js +5 -5
  102. package/dist/runtime/server/lib/oauth/wechat.d.ts +1 -1
  103. package/dist/runtime/server/lib/oauth/wechat.js +7 -7
  104. package/dist/runtime/server/lib/oauth/workos.d.ts +1 -1
  105. package/dist/runtime/server/lib/oauth/workos.js +3 -4
  106. package/dist/runtime/server/lib/oauth/x.d.ts +1 -1
  107. package/dist/runtime/server/lib/oauth/x.js +4 -4
  108. package/dist/runtime/server/lib/oauth/xsuaa.d.ts +1 -1
  109. package/dist/runtime/server/lib/oauth/xsuaa.js +4 -4
  110. package/dist/runtime/server/lib/oauth/yandex.d.ts +1 -1
  111. package/dist/runtime/server/lib/oauth/yandex.js +4 -4
  112. package/dist/runtime/server/lib/oauth/zendesk.d.ts +1 -1
  113. package/dist/runtime/server/lib/oauth/zendesk.js +4 -4
  114. package/dist/runtime/server/lib/oauth/zitadel.d.ts +1 -1
  115. package/dist/runtime/server/lib/oauth/zitadel.js +6 -6
  116. package/dist/runtime/server/lib/utils.d.ts +8 -8
  117. package/dist/runtime/server/lib/utils.js +5 -7
  118. package/dist/runtime/server/lib/webauthn/authenticate.d.ts +1 -1
  119. package/dist/runtime/server/lib/webauthn/authenticate.js +7 -8
  120. package/dist/runtime/server/lib/webauthn/register.d.ts +2 -2
  121. package/dist/runtime/server/lib/webauthn/register.js +9 -10
  122. package/dist/runtime/server/plugins/oauth-hash.d.ts +2 -0
  123. package/dist/runtime/server/plugins/oauth-hash.js +8 -0
  124. package/dist/runtime/server/routes/atproto/client-metadata.json.get.d.ts +1 -1
  125. package/dist/runtime/server/routes/atproto/client-metadata.json.get.js +5 -5
  126. package/dist/runtime/server/utils/atproto.d.ts +2 -2
  127. package/dist/runtime/server/utils/atproto.js +2 -3
  128. package/dist/runtime/server/utils/password.js +1 -1
  129. package/dist/runtime/server/utils/session.d.ts +29 -16
  130. package/dist/runtime/server/utils/session.js +72 -29
  131. package/dist/runtime/types/event.d.ts +27 -3
  132. package/dist/runtime/types/index.d.ts +1 -1
  133. package/dist/runtime/types/oauth-config.d.ts +3 -3
  134. package/dist/runtime/types/webauthn.d.ts +14 -17
  135. package/package.json +10 -6
  136. package/dist/runtime/server/plugins/oauth.d.ts +0 -2
  137. package/dist/runtime/server/plugins/oauth.js +0 -16
  138. package/dist/runtime/server/plugins/ws.d.ts +0 -2
  139. package/dist/runtime/server/plugins/ws.js +0 -7
@@ -1,3 +1,3 @@
1
- import type { EventHandler } from 'h3';
1
+ import type { EventHandler } from 'nuxt/server';
2
2
  import type { WebAuthnAuthenticateEventHandlerOptions, WebAuthnCredential } from '#auth-utils';
3
3
  export declare function defineWebAuthnAuthenticateEventHandler<T extends WebAuthnCredential>({ storeChallenge, getChallenge, getCredential, allowCredentials, getOptions, onSuccess, onError, }: WebAuthnAuthenticateEventHandlerOptions<T>): EventHandler;
@@ -1,9 +1,8 @@
1
- import { eventHandler, H3Error, createError, getRequestURL, readBody } from "h3";
1
+ import { defineEventHandler, createError, getRequestURL, isNuxtError, readBody, useRuntimeConfig } from "nuxt/server";
2
2
  import { generateAuthenticationOptions, verifyAuthenticationResponse } from "@simplewebauthn/server";
3
3
  import defu from "defu";
4
4
  import { getRandomValues } from "uncrypto";
5
5
  import { base64URLStringToBuffer, bufferToBase64URLString } from "@simplewebauthn/browser";
6
- import { useRuntimeConfig } from "#imports";
7
6
  export function defineWebAuthnAuthenticateEventHandler({
8
7
  storeChallenge,
9
8
  getChallenge,
@@ -13,10 +12,10 @@ export function defineWebAuthnAuthenticateEventHandler({
13
12
  onSuccess,
14
13
  onError
15
14
  }) {
16
- return eventHandler(async (event) => {
15
+ return defineEventHandler(async (event) => {
17
16
  const url = getRequestURL(event);
18
17
  const body = await readBody(event);
19
- const _config = defu(await getOptions?.(event, body) ?? {}, useRuntimeConfig(event).webauthn.authenticate, {
18
+ const _config = defu(await getOptions?.(event, body) ?? {}, useRuntimeConfig().webauthn.authenticate, {
20
19
  rpID: url.hostname
21
20
  });
22
21
  if (!storeChallenge) {
@@ -38,7 +37,7 @@ export function defineWebAuthnAuthenticateEventHandler({
38
37
  };
39
38
  }
40
39
  if (!body.attemptId)
41
- throw createError({ statusCode: 400 });
40
+ throw createError({ status: 400 });
42
41
  let expectedChallenge = "";
43
42
  if (getChallenge) {
44
43
  expectedChallenge = await getChallenge(event, body.attemptId);
@@ -59,7 +58,7 @@ export function defineWebAuthnAuthenticateEventHandler({
59
58
  }
60
59
  });
61
60
  if (!verification.verified)
62
- throw createError({ statusCode: 400, message: "Failed to verify registration response" });
61
+ throw createError({ status: 400, message: "Failed to verify registration response" });
63
62
  await onSuccess(event, {
64
63
  credential,
65
64
  authenticationInfo: verification.authenticationInfo
@@ -67,9 +66,9 @@ export function defineWebAuthnAuthenticateEventHandler({
67
66
  return verification;
68
67
  } catch (error) {
69
68
  if (!onError) throw error;
70
- if (error instanceof H3Error)
69
+ if (isNuxtError(error))
71
70
  return onError(event, error);
72
- return onError(event, createError({ statusCode: 500, message: "Failed to authenticate credential" }));
71
+ return onError(event, createError({ status: 500, message: "Failed to authenticate credential" }));
73
72
  }
74
73
  });
75
74
  }
@@ -1,5 +1,5 @@
1
- import type { H3Event, EventHandler } from 'h3';
1
+ import type { EventHandler, RequestEvent } from 'nuxt/server';
2
2
  import type { ValidateUserFunction } from '../../../types/webauthn.js';
3
3
  import type { WebAuthnUser, WebAuthnRegisterEventHandlerOptions } from '#auth-utils';
4
4
  export declare function defineWebAuthnRegisterEventHandler<T extends WebAuthnUser>({ storeChallenge, getChallenge, getOptions, validateUser, excludeCredentials, onSuccess, onError, }: WebAuthnRegisterEventHandlerOptions<T>): EventHandler;
5
- export declare function validateUserData<T>(userBody: WebAuthnUser, event: H3Event, fn: ValidateUserFunction<T>): Promise<T>;
5
+ export declare function validateUserData<T>(userBody: WebAuthnUser, event: RequestEvent, fn: ValidateUserFunction<T>): Promise<T>;
@@ -1,9 +1,8 @@
1
- import { eventHandler, H3Error, createError, getRequestURL, readBody } from "h3";
1
+ import { defineEventHandler, createError, getRequestURL, isNuxtError, readBody, useRuntimeConfig } from "nuxt/server";
2
2
  import { generateRegistrationOptions, verifyRegistrationResponse } from "@simplewebauthn/server";
3
3
  import defu from "defu";
4
4
  import { bufferToBase64URLString } from "@simplewebauthn/browser";
5
5
  import { getRandomValues } from "uncrypto";
6
- import { useRuntimeConfig } from "#imports";
7
6
  export function defineWebAuthnRegisterEventHandler({
8
7
  storeChallenge,
9
8
  getChallenge,
@@ -13,19 +12,19 @@ export function defineWebAuthnRegisterEventHandler({
13
12
  onSuccess,
14
13
  onError
15
14
  }) {
16
- return eventHandler(async (event) => {
15
+ return defineEventHandler(async (event) => {
17
16
  const url = getRequestURL(event);
18
17
  const body = await readBody(event);
19
18
  if (body.verify === void 0 || !body.user?.userName)
20
19
  throw createError({
21
20
  message: "Invalid request, missing userName or verify property",
22
- statusCode: 400
21
+ status: 400
23
22
  });
24
23
  let user = body.user;
25
24
  if (validateUser) {
26
25
  user = await validateUserData(body.user, event, validateUser);
27
26
  }
28
- const _config = defu(await getOptions?.(event, body) ?? {}, useRuntimeConfig(event).webauthn.register, {
27
+ const _config = defu(await getOptions?.(event, body) ?? {}, useRuntimeConfig().webauthn.register, {
29
28
  rpID: url.hostname,
30
29
  rpName: url.hostname,
31
30
  userName: user.userName,
@@ -55,7 +54,7 @@ export function defineWebAuthnRegisterEventHandler({
55
54
  if (!body.attemptId) {
56
55
  throw createError({
57
56
  message: "Invalid request, missing attemptId",
58
- statusCode: 400
57
+ status: 400
59
58
  });
60
59
  }
61
60
  let expectedChallenge = "";
@@ -74,7 +73,7 @@ export function defineWebAuthnRegisterEventHandler({
74
73
  if (!verification.verified) {
75
74
  throw createError({
76
75
  message: "Failed to verify registration response",
77
- statusCode: 400
76
+ status: 400
78
77
  });
79
78
  }
80
79
  await onSuccess(event, {
@@ -92,9 +91,9 @@ export function defineWebAuthnRegisterEventHandler({
92
91
  return verification;
93
92
  } catch (error) {
94
93
  if (!onError) throw error;
95
- if (error instanceof H3Error)
94
+ if (isNuxtError(error))
96
95
  return onError(event, error);
97
- return onError(event, createError({ statusCode: 500, message: "Failed to register credential" }));
96
+ return onError(event, createError({ status: 500, message: "Failed to register credential" }));
98
97
  }
99
98
  });
100
99
  }
@@ -114,7 +113,7 @@ export async function validateUserData(userBody, event, fn) {
114
113
  }
115
114
  function createUserValidationError(validateError) {
116
115
  throw createError({
117
- status: validateError?.statusCode || 400,
116
+ status: validateError?.status || validateError?.statusCode || 400,
118
117
  message: validateError?.message || "User Validation Error",
119
118
  data: validateError
120
119
  });
@@ -0,0 +1,2 @@
1
+ declare const _default: () => void;
2
+ export default _default;
@@ -0,0 +1,8 @@
1
+ import { useRuntimeConfig, useServerHooks } from "nuxt/server";
2
+ export default () => {
3
+ useServerHooks().hook("render:html", (html) => {
4
+ const oauth = useRuntimeConfig().oauth;
5
+ if (!oauth?.facebook?.clientId && !oauth?.instagram?.clientId) return;
6
+ html.head.unshift('<script>if(window.location.hash==="#_=_"){history.replaceState?history.replaceState(null,null,window.location.href.split("#")[0]):window.location.hash=""}<\/script>');
7
+ });
8
+ };
@@ -1,4 +1,4 @@
1
- declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, {
1
+ declare const _default: import("nuxt/server").EventHandler<{
2
2
  redirect_uris: [string, ...string[]];
3
3
  scope?: string | undefined;
4
4
  response_types?: ["code" | "none" | "token" | "code id_token token" | "code id_token" | "code token" | "id_token token" | "id_token", ...("code" | "none" | "token" | "code id_token token" | "code id_token" | "code token" | "id_token token" | "id_token")[]] | undefined;
@@ -1,10 +1,10 @@
1
- import { defineEventHandler, createError } from "h3";
1
+ import { createError, defineEventHandler, getRequestURL, useRuntimeConfig } from "nuxt/server";
2
+ import { withoutBase } from "ufo";
2
3
  import { getAtprotoClientMetadata } from "../../utils/atproto.js";
3
4
  import { atprotoProviders, getClientMetadataFilename } from "../../../utils/atproto.js";
4
- import { useRuntimeConfig } from "#imports";
5
5
  export default defineEventHandler((event) => {
6
- const path = event.path.slice(1);
7
- const runtimeConfig = useRuntimeConfig(event);
6
+ const runtimeConfig = useRuntimeConfig();
7
+ const path = withoutBase(getRequestURL(event).pathname, runtimeConfig.app.baseURL).slice(1);
8
8
  for (const provider of atprotoProviders) {
9
9
  const config = runtimeConfig.oauth[provider];
10
10
  if (getClientMetadataFilename(provider, config) === path) {
@@ -12,7 +12,7 @@ export default defineEventHandler((event) => {
12
12
  }
13
13
  }
14
14
  throw createError({
15
- statusCode: 404,
15
+ status: 404,
16
16
  message: "Provider not found"
17
17
  });
18
18
  });
@@ -1,5 +1,5 @@
1
- import type { H3Event } from 'h3';
1
+ import type { RequestEvent } from 'nuxt/server';
2
2
  import type { OAuthClientMetadataInput } from '@atproto/oauth-client-node';
3
3
  import type { OAuthBlueskyConfig } from '../lib/atproto/bluesky.js';
4
4
  import type { ATProtoProvider, OAuthConfig } from '#auth-utils';
5
- export declare function getAtprotoClientMetadata(event: H3Event, provider: ATProtoProvider, config?: OAuthConfig<OAuthBlueskyConfig>['config']): OAuthClientMetadataInput;
5
+ export declare function getAtprotoClientMetadata(event: RequestEvent, provider: ATProtoProvider, config?: OAuthConfig<OAuthBlueskyConfig>['config']): OAuthClientMetadataInput;
@@ -1,9 +1,8 @@
1
- import { getRequestURL } from "h3";
1
+ import { getRequestURL, useRuntimeConfig } from "nuxt/server";
2
2
  import { getOAuthRedirectURL } from "../lib/utils.js";
3
3
  import { getClientMetadataFilename } from "../../utils/atproto.js";
4
- import { useRuntimeConfig } from "#imports";
5
4
  export function getAtprotoClientMetadata(event, provider, config) {
6
- const providerRuntimeConfig = useRuntimeConfig(event).oauth[provider];
5
+ const providerRuntimeConfig = useRuntimeConfig().oauth[provider];
7
6
  const scopes = [.../* @__PURE__ */ new Set(["atproto", ...config?.scope ?? [], ...providerRuntimeConfig.scope ?? []])];
8
7
  const scope = scopes.join(" ");
9
8
  const grantTypes = [.../* @__PURE__ */ new Set(["authorization_code", ...providerRuntimeConfig.grantTypes ?? []])];
@@ -1,6 +1,6 @@
1
1
  import { Hash } from "@adonisjs/hash";
2
2
  import { Scrypt } from "@adonisjs/hash/drivers/scrypt";
3
- import { useRuntimeConfig } from "#imports";
3
+ import { useRuntimeConfig } from "nuxt/server";
4
4
  let _hash;
5
5
  function getHash() {
6
6
  if (!_hash) {
@@ -1,55 +1,68 @@
1
- import type { H3Event, SessionConfig } from 'h3';
2
- import { useSession } from 'h3';
1
+ import type { RequestEvent, SessionConfig } from 'nuxt/server';
3
2
  import type { OmitWithIndexSignature } from '../../types/utils.js';
4
- import type { SessionEvent, UserSession, UserSessionRequired } from '#auth-utils';
5
- type UseSessionEvent = Parameters<typeof useSession>[0] | SessionEvent;
3
+ import type { LegacyH3Event, SessionEvent, UserSession, UserSessionRequired } from '#auth-utils';
4
+ /**
5
+ * Name of the cookie the user session is sealed into.
6
+ */
7
+ export declare const USER_SESSION_COOKIE_NAME = "nuxt-auth-session";
8
+ type UserSessionData = OmitWithIndexSignature<UserSession, 'id'>;
9
+ /**
10
+ * Session options, the session is always sealed with a secret derived from `appSecret`.
11
+ */
12
+ type UserSessionConfig = Omit<SessionConfig, 'password'>;
13
+ /**
14
+ * An event the session can be written with, WebSocket peers and upgrade requests are read-only.
15
+ */
16
+ type WritableSessionEvent = RequestEvent | LegacyH3Event;
6
17
  export interface SessionHooks {
7
18
  /**
8
19
  * Called when fetching the session from the API
9
20
  * - Add extra properties to the session
10
21
  * - Throw an error if the session could not be verified (with a database for example)
11
22
  */
12
- fetch: (session: UserSession, event: H3Event) => void | Promise<void>;
23
+ fetch: (session: UserSession, event: RequestEvent) => void | Promise<void>;
13
24
  /**
14
25
  * Called before clearing the session
15
26
  */
16
- clear: (session: UserSession, event: H3Event) => void | Promise<void>;
27
+ clear: (session: UserSession, event: RequestEvent) => void | Promise<void>;
17
28
  }
18
29
  export declare const sessionHooks: import("hookable").Hookable<SessionHooks, import("hookable").HookKeys<SessionHooks>>;
19
30
  /**
20
31
  * Get the user session from the current request
21
- * @param event The Request (h3) event
32
+ * @param event The request event
22
33
  * @returns The user session
23
34
  */
24
- export declare function getUserSession(event: UseSessionEvent): Promise<UserSession>;
35
+ export declare function getUserSession(event: SessionEvent): Promise<UserSession>;
25
36
  /**
26
37
  * Set a user session
27
- * @param event The Request (h3) event
38
+ * @param event The request event
28
39
  * @param data User session data, please only store public information since it can be decoded with API calls
29
40
  * @see https://github.com/atinux/nuxt-auth-utils
30
41
  */
31
- export declare function setUserSession(event: SessionEvent, data: OmitWithIndexSignature<UserSession, 'id'>, config?: Partial<SessionConfig>): Promise<UserSession>;
42
+ export declare function setUserSession(event: WritableSessionEvent, data: UserSessionData, config?: UserSessionConfig): Promise<UserSession>;
32
43
  /**
33
44
  * Replace a user session
34
- * @param event The Request (h3) event
45
+ * @param event The request event
35
46
  * @param data User session data, please only store public information since it can be decoded with API calls
36
47
  */
37
- export declare function replaceUserSession(event: SessionEvent, data: OmitWithIndexSignature<UserSession, 'id'>, config?: Partial<SessionConfig>): Promise<UserSession>;
48
+ export declare function replaceUserSession(event: WritableSessionEvent, data: UserSessionData, config?: UserSessionConfig): Promise<UserSession>;
38
49
  /**
39
50
  * Clear the user session and removing the session cookie
40
- * @param event The Request (h3) event
51
+ * @param event The request event
41
52
  * @returns true if the session was cleared
42
53
  */
43
- export declare function clearUserSession(event: SessionEvent, config?: Partial<SessionConfig>): Promise<boolean>;
54
+ export declare function clearUserSession(event: WritableSessionEvent, config?: UserSessionConfig): Promise<boolean>;
44
55
  /**
45
56
  * Require a user session, throw a 401 error if the user is not logged in
46
57
  * @param event
47
58
  * @param opts Options to customize the error message and status code
48
- * @param opts.statusCode The status code to use for the error (defaults to 401)
59
+ * @param opts.status The status code to use for the error (defaults to 401)
60
+ * @param opts.statusCode Deprecated, use `status`
49
61
  * @param opts.message The message to use for the error (defaults to Unauthorized)
50
62
  * @see https://github.com/atinux/nuxt-auth-utils
51
63
  */
52
- export declare function requireUserSession(event: UseSessionEvent, opts?: {
64
+ export declare function requireUserSession(event: SessionEvent, opts?: {
65
+ status?: number;
53
66
  statusCode?: number;
54
67
  message?: string;
55
68
  }): Promise<UserSessionRequired>;
@@ -1,7 +1,7 @@
1
- import { useSession, createError, isEvent } from "h3";
1
+ import { createError, defineEventHandler, useRuntimeConfig, useSession } from "nuxt/server";
2
2
  import { defu } from "defu";
3
3
  import { createHooks } from "hookable";
4
- import { useRuntimeConfig } from "#imports";
4
+ export const USER_SESSION_COOKIE_NAME = "nuxt-auth-session";
5
5
  export const sessionHooks = createHooks();
6
6
  export async function getUserSession(event) {
7
7
  const session = await _useSession(event);
@@ -11,53 +11,96 @@ export async function getUserSession(event) {
11
11
  };
12
12
  }
13
13
  export async function setUserSession(event, data, config) {
14
- const session = await _useSession(event, config);
15
- await session.update(defu(data, session.data));
14
+ const session = await _useSession(event, config, true);
15
+ await session.update(defu(toJSONData(data), session.data));
16
16
  return session.data;
17
17
  }
18
18
  export async function replaceUserSession(event, data, config) {
19
- const session = await _useSession(event, config);
20
- await session.clear();
19
+ const session = await _useSession(event, config, true);
21
20
  await session.update((oldData) => {
22
21
  for (const key of Object.keys(oldData)) {
23
22
  Reflect.deleteProperty(oldData, key);
24
23
  }
25
- return data;
24
+ return toJSONData(data);
26
25
  });
27
26
  return session.data;
28
27
  }
29
28
  export async function clearUserSession(event, config) {
30
- const session = await _useSession(event, config);
31
- await sessionHooks.callHookParallel("clear", session.data, event);
29
+ const session = await _useSession(event, config, true);
30
+ await sessionHooks.callHookParallel("clear", session.data, toSessionEvent(event).event);
32
31
  await session.clear();
33
32
  return true;
34
33
  }
35
34
  export async function requireUserSession(event, opts = {}) {
36
35
  const userSession = await getUserSession(event);
37
36
  if (!userSession.user) {
38
- if (isEvent(event)) {
39
- throw createError({
40
- statusCode: opts.statusCode || 401,
41
- message: opts.message || "Unauthorized"
42
- });
43
- } else {
44
- throw new Response(opts.message || "Unauthorized", {
45
- status: opts.statusCode || 401
46
- });
37
+ const status = opts.status || opts.statusCode || 401;
38
+ const message = opts.message || "Unauthorized";
39
+ if (toSessionEvent(event).webSocket) {
40
+ throw new Response(message, { status });
47
41
  }
42
+ throw createError({ status, message });
48
43
  }
49
44
  return userSession;
50
45
  }
51
- let sessionConfig;
52
- function _useSession(event, config = {}) {
53
- if (!sessionConfig) {
54
- const runtimeConfig = useRuntimeConfig(isEvent(event) ? event : void 0);
55
- const envSessionPassword = `${runtimeConfig.nitro?.envPrefix || "NUXT_"}SESSION_PASSWORD`;
56
- sessionConfig = defu({ password: process.env[envSessionPassword] }, runtimeConfig.session);
57
- if (!sessionConfig.password) {
58
- console.error(`[nuxt-auth-utils] ${envSessionPassword} environment variable or runtimeConfig.session.password was not set.`);
59
- }
46
+ async function _useSession(event, config = {}, write = false) {
47
+ const { event: sessionEvent, webSocket } = toSessionEvent(event);
48
+ if (write && webSocket) {
49
+ throw createError({
50
+ status: 500,
51
+ message: "[nuxt-auth-utils] The user session is read-only in WebSocket handlers: `setUserSession`, `replaceUserSession` and `clearUserSession` need the event of an HTTP request."
52
+ });
53
+ }
54
+ const runtimeConfig = useRuntimeConfig();
55
+ warnLegacySessionPassword(runtimeConfig);
56
+ const { password: _password, ...finalConfig } = defu(config, runtimeConfig.session, { name: USER_SESSION_COOKIE_NAME });
57
+ if (finalConfig.name === APP_SESSION_COOKIE_NAME) {
58
+ warnAppSessionName();
59
+ finalConfig.name = USER_SESSION_COOKIE_NAME;
60
+ }
61
+ return useSession(sessionEvent, finalConfig);
62
+ }
63
+ function toJSONData(data) {
64
+ return JSON.parse(JSON.stringify(data));
65
+ }
66
+ const APP_SESSION_COOKIE_NAME = "nuxt-session";
67
+ let warnedAppSessionName = false;
68
+ function warnAppSessionName() {
69
+ if (warnedAppSessionName) return;
70
+ warnedAppSessionName = true;
71
+ console.warn(`[nuxt-auth-utils] The session name \`${APP_SESSION_COOKIE_NAME}\` is the cookie of \`useSession()\` from \`nuxt/server\`, using \`${USER_SESSION_COOKIE_NAME}\` instead. Set another \`runtimeConfig.session.name\` (\`NUXT_SESSION_NAME\`) to rename the user session cookie.`);
72
+ }
73
+ const toPortableEvent = defineEventHandler((event) => event);
74
+ function toSessionEvent(event) {
75
+ const input = event;
76
+ if (input["~portable"] === true || typeof input.res?.headers?.append === "function") {
77
+ return { event: input, webSocket: false };
78
+ }
79
+ if (input.node?.req) {
80
+ return { event: toPortableEvent(input), webSocket: false };
81
+ }
82
+ const headers = input.request?.headers || input.headers;
83
+ if (headers && typeof headers.get === "function") {
84
+ return {
85
+ event: {
86
+ req: { headers },
87
+ res: { status: 200, statusText: "", headers: new Headers() }
88
+ },
89
+ webSocket: true
90
+ };
91
+ }
92
+ throw createError({
93
+ status: 500,
94
+ message: "[nuxt-auth-utils] The session utils need a request event, a WebSocket peer or a WebSocket upgrade request."
95
+ });
96
+ }
97
+ let checkedLegacySessionPassword = false;
98
+ function warnLegacySessionPassword(runtimeConfig) {
99
+ if (checkedLegacySessionPassword) return;
100
+ checkedLegacySessionPassword = true;
101
+ const envPrefix = runtimeConfig.nitro?.envPrefix || "NUXT_";
102
+ const envKey = `${envPrefix}SESSION_PASSWORD`;
103
+ if (globalThis.process?.env?.[envKey] || runtimeConfig.session?.password) {
104
+ console.warn(`[nuxt-auth-utils] \`${envKey}\` (\`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\`.`);
60
105
  }
61
- const finalConfig = defu(config, sessionConfig);
62
- return useSession(event, finalConfig);
63
106
  }
@@ -1,4 +1,28 @@
1
- import type { H3Event } from 'h3';
2
- import type { RequestEvent } from '@nuxt/schema';
1
+ import type { RequestEvent } from 'nuxt/server';
2
+ import type { IncomingMessage, ServerResponse } from 'node:http';
3
3
  export type { RequestEvent };
4
- export type SessionEvent = H3Event | RequestEvent;
4
+ /**
5
+ * The h3 v1 event a handler defined with `defineEventHandler` from `h3` (or its auto-import) receives on Nuxt 4.
6
+ * @deprecated Use `defineEventHandler` from `nuxt/server`. Removed with Nuxt 5 support.
7
+ */
8
+ export interface LegacyH3Event {
9
+ node: {
10
+ req: IncomingMessage;
11
+ res: ServerResponse;
12
+ };
13
+ }
14
+ /**
15
+ * A WebSocket peer or upgrade request, from `defineWebSocketHandler`.
16
+ * The session is read-only: changes are not sent back to the client.
17
+ */
18
+ export type WebSocketSessionEvent = {
19
+ request: {
20
+ headers: Headers;
21
+ };
22
+ } | {
23
+ headers: Headers;
24
+ };
25
+ /**
26
+ * Any event the session utils accept.
27
+ */
28
+ export type SessionEvent = RequestEvent | LegacyH3Event | WebSocketSessionEvent;
@@ -1,4 +1,4 @@
1
1
  export type { User, UserSession, UserSessionRequired, UserSessionComposable, SecureSessionData } from './session.js';
2
- export type { RequestEvent, SessionEvent } from './event.js';
2
+ export type { RequestEvent, SessionEvent, LegacyH3Event, WebSocketSessionEvent } from './event.js';
3
3
  export type { OAuthConfig, OAuthProvider, ATProtoProvider, OnError } from './oauth-config.js';
4
4
  export type { WebAuthnCredential, WebAuthnRegisterEventHandlerOptions, WebAuthnAuthenticateEventHandlerOptions, WebAuthnComposable, WebAuthnUser, } from './webauthn.js';
@@ -1,12 +1,12 @@
1
- import type { H3Event, H3Error } from 'h3';
1
+ import type { NuxtError, RequestEvent } from 'nuxt/server';
2
2
  export type ATProtoProvider = 'bluesky';
3
3
  export type OAuthProvider = ATProtoProvider | 'atlassian' | 'auth0' | 'authentik' | 'azureb2c' | 'battledotnet' | 'cloudflare' | 'cognito' | 'discord' | 'dropbox' | 'facebook' | 'gitea' | 'github' | 'gitlab' | 'google' | 'hubspot' | 'instagram' | 'kick' | 'keycloak' | 'line' | 'linear' | 'linkedin' | 'mastodon' | 'microsoft' | 'paypal' | 'polar' | 'spotify' | 'seznam' | 'steam' | 'strava' | 'tiktok' | 'twitch' | 'vk' | 'wechat' | 'workos' | 'x' | 'xsuaa' | 'yandex' | 'zitadel' | 'apple' | 'livechat' | 'salesforce' | 'slack' | 'heroku' | 'roblox' | 'okta' | 'ory' | 'shopifyCustomer' | 'oidc' | 'osu' | 'riotgames' | 'box' | 'zendesk' | (string & {});
4
- export type OnError = (event: H3Event, error: H3Error) => Promise<void> | void;
4
+ export type OnError = (event: RequestEvent, error: NuxtError) => unknown;
5
5
  export interface OAuthConfig<TConfig, TResult = {
6
6
  user: any;
7
7
  tokens: any;
8
8
  }> {
9
9
  config?: TConfig;
10
- onSuccess: (event: H3Event, result: TResult) => Promise<void> | void;
10
+ onSuccess: (event: RequestEvent, result: TResult) => unknown;
11
11
  onError?: OnError;
12
12
  }
@@ -1,9 +1,6 @@
1
1
  import type { Ref } from 'vue';
2
- import type { H3Event, H3Error, ValidateResult } from 'h3';
3
- import type { GenerateAuthenticationOptionsOpts, GenerateRegistrationOptionsOpts, VerifiedAuthenticationResponse, VerifiedRegistrationResponse, verifyAuthenticationResponse, verifyRegistrationResponse } from '@simplewebauthn/server';
4
- type RegistrationResponseJSON = Parameters<typeof verifyRegistrationResponse>[0]['response'];
5
- type AuthenticationResponseJSON = Parameters<typeof verifyAuthenticationResponse>[0]['response'];
6
- type AuthenticatorTransportFuture = NonNullable<Parameters<typeof verifyAuthenticationResponse>[0]['credential']['transports']>[number];
2
+ import type { NuxtError, RequestEvent, ValidateResult } from 'nuxt/server';
3
+ import type { AuthenticationResponseJSON, AuthenticatorTransportFuture, GenerateAuthenticationOptionsOpts, GenerateRegistrationOptionsOpts, RegistrationResponseJSON, VerifiedAuthenticationResponse, VerifiedRegistrationResponse } from '@simplewebauthn/server';
7
4
  export interface WebAuthnCredential {
8
5
  id: string;
9
6
  publicKey: string;
@@ -20,15 +17,15 @@ export interface WebAuthnUser {
20
17
  }
21
18
  type CredentialsList = NonNullable<GenerateAuthenticationOptionsOpts['allowCredentials']>;
22
19
  type WebAuthnEventHandlerBase<T extends Record<PropertyKey, unknown>> = {
23
- storeChallenge: (event: H3Event, challenge: string, attemptId: string) => void | Promise<void>;
24
- getChallenge: (event: H3Event, attemptId: string) => string | Promise<string>;
25
- onSuccess: (event: H3Event, data: T) => void | Promise<void>;
26
- onError?: (event: H3Event, error: H3Error) => void | Promise<void>;
20
+ storeChallenge: (event: RequestEvent, challenge: string, attemptId: string) => void | Promise<void>;
21
+ getChallenge: (event: RequestEvent, attemptId: string) => string | Promise<string>;
22
+ onSuccess: (event: RequestEvent, data: T) => unknown;
23
+ onError?: (event: RequestEvent, error: NuxtError) => unknown;
27
24
  } | {
28
25
  storeChallenge?: undefined;
29
26
  getChallenge?: undefined;
30
- onSuccess: (event: H3Event, data: T) => void | Promise<void>;
31
- onError?: (event: H3Event, error: H3Error) => void | Promise<void>;
27
+ onSuccess: (event: RequestEvent, data: T) => unknown;
28
+ onError?: (event: RequestEvent, error: NuxtError) => unknown;
32
29
  };
33
30
  export type RegistrationBody<T extends WebAuthnUser> = {
34
31
  user: T;
@@ -39,15 +36,15 @@ export type RegistrationBody<T extends WebAuthnUser> = {
39
36
  attemptId: string;
40
37
  response: RegistrationResponseJSON;
41
38
  };
42
- export type ValidateUserFunction<T> = (userBody: WebAuthnUser, event: H3Event) => ValidateResult<T> | Promise<ValidateResult<T>>;
39
+ export type ValidateUserFunction<T> = (userBody: WebAuthnUser, event: RequestEvent) => ValidateResult<T> | Promise<ValidateResult<T>>;
43
40
  export type WebAuthnRegisterEventHandlerOptions<T extends WebAuthnUser> = WebAuthnEventHandlerBase<{
44
41
  user: T;
45
42
  credential: WebAuthnCredential;
46
43
  registrationInfo: Exclude<VerifiedRegistrationResponse['registrationInfo'], undefined>;
47
44
  }> & {
48
- getOptions?: (event: H3Event, body: RegistrationBody<T>) => Partial<GenerateRegistrationOptionsOpts> | Promise<Partial<GenerateRegistrationOptionsOpts>>;
45
+ getOptions?: (event: RequestEvent, body: RegistrationBody<T>) => Partial<GenerateRegistrationOptionsOpts> | Promise<Partial<GenerateRegistrationOptionsOpts>>;
49
46
  validateUser?: ValidateUserFunction<T>;
50
- excludeCredentials?: (event: H3Event, userName: string) => CredentialsList | Promise<CredentialsList>;
47
+ excludeCredentials?: (event: RequestEvent, userName: string) => CredentialsList | Promise<CredentialsList>;
51
48
  };
52
49
  export type AuthenticationBody = {
53
50
  verify: false;
@@ -62,9 +59,9 @@ export type WebAuthnAuthenticateEventHandlerOptions<T extends WebAuthnCredential
62
59
  credential: T;
63
60
  authenticationInfo: Exclude<VerifiedAuthenticationResponse['authenticationInfo'], undefined>;
64
61
  }> & {
65
- getOptions?: (event: H3Event, body: AuthenticationBody) => Partial<GenerateAuthenticationOptionsOpts> | Promise<Partial<GenerateAuthenticationOptionsOpts>>;
66
- getCredential: (event: H3Event, credentialID: string) => T | Promise<T>;
67
- allowCredentials?: (event: H3Event, userName: string) => CredentialsList | Promise<CredentialsList>;
62
+ getOptions?: (event: RequestEvent, body: AuthenticationBody) => Partial<GenerateAuthenticationOptionsOpts> | Promise<Partial<GenerateAuthenticationOptionsOpts>>;
63
+ getCredential: (event: RequestEvent, credentialID: string) => T | Promise<T>;
64
+ allowCredentials?: (event: RequestEvent, userName: string) => CredentialsList | Promise<CredentialsList>;
68
65
  };
69
66
  export interface WebAuthnComposable {
70
67
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-auth-utils",
3
- "version": "0.5.34",
3
+ "version": "0.6.0",
4
4
  "description": "Add Authentication to Nuxt applications with secured & sealed cookies sessions.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,25 +25,27 @@
25
25
  "files": [
26
26
  "dist"
27
27
  ],
28
+ "engines": {
29
+ "node": "^22.22.3 || ^24.15.0 || >=26.0.0"
30
+ },
28
31
  "dependencies": {
29
32
  "@adonisjs/hash": "^9.1.1",
30
- "@nuxt/kit": "^4.3.1",
33
+ "@nuxt/kit": "^4.6.0",
31
34
  "@nuxt/schema": "^4.6.0",
32
35
  "defu": "^6.1.5",
33
- "h3": "^1.15.9",
34
36
  "hookable": "^6.0.1",
35
37
  "jose": "^6.1.3",
36
38
  "ofetch": "^1.5.1",
37
39
  "openid-client": "^6.8.2",
38
- "pathe": "^2.0.3",
39
40
  "scule": "^1.3.0",
41
+ "ufo": "^1.6.4",
40
42
  "uncrypto": "^0.1.3"
41
43
  },
42
44
  "peerDependencies": {
43
45
  "@atproto/api": "^0.13.15",
44
46
  "@atproto/oauth-client-node": "^0.2.0",
45
- "@simplewebauthn/browser": "^11.0.0 || ^13.0.0",
46
- "@simplewebauthn/server": "^11.0.0 || ^13.3.2"
47
+ "@simplewebauthn/browser": "^13.0.0",
48
+ "@simplewebauthn/server": "^13.3.2"
47
49
  },
48
50
  "peerDependenciesMeta": {
49
51
  "@simplewebauthn/browser": {
@@ -77,6 +79,8 @@
77
79
  "dev": "nuxi dev playground",
78
80
  "dev:build": "nuxi build playground",
79
81
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
82
+ "dev:v5": "pnpm install:nuxt5 && nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground && nuxi dev playground",
83
+ "install:nuxt5": "pnpm install --config.pnpmfile=scripts/nuxt-nightly.cjs --config.lockfile=false --config.minimum-release-age-exclude=*-nightly",
80
84
  "lint": "eslint .",
81
85
  "lint:fix": "eslint . --fix",
82
86
  "test": "vitest run",
@@ -1,2 +0,0 @@
1
- declare const _default: import("nitropack/types").NitroAppPlugin;
2
- export default _default;
@@ -1,16 +0,0 @@
1
- import { defineNitroPlugin } from "nitropack/runtime";
2
- export default defineNitroPlugin((nitroApp) => {
3
- if (process.env.NUXT_OAUTH_FACEBOOK_CLIENT_ID && process.env.NUXT_OAUTH_FACEBOOK_CLIENT_SECRET || process.env.NUXT_OAUTH_INSTAGRAM_CLIENT_ID && process.env.NUXT_OAUTH_INSTAGRAM_CLIENT_SECRET) {
4
- nitroApp.hooks.hook("render:html", (html) => {
5
- html.head.unshift(`
6
- <script>
7
- if (window.location.hash === "#_=_"){
8
- history.replaceState
9
- ? history.replaceState(null, null, window.location.href.split("#")[0])
10
- : window.location.hash = "";
11
- }
12
- <\/script>
13
- `);
14
- });
15
- }
16
- });
@@ -1,2 +0,0 @@
1
- declare const _default: import("nitropack").NitroAppPlugin;
2
- export default _default;