nuxt-auth-utils 0.5.23 → 0.5.25

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 CHANGED
@@ -600,6 +600,18 @@ This is because the user session is stored in a secure cookie and cannot be acce
600
600
 
601
601
  **This means that you should not rely on the user session during prerendering.**
602
602
 
603
+ You may also choose to instruct Nuxt AUth Utils to fetch the user session only on the client side, with the `loadStrategy` option in your `nuxt.config.ts`:
604
+
605
+ ```ts
606
+ export default defineNuxtConfig({
607
+ auth: {
608
+ loadStrategy: 'client-only'
609
+ }
610
+ })
611
+ ```
612
+
613
+ When using the `client-only` load strategy, the user session can still be manually fetched on the server side by calling `fetch` from the `useUserSession` composable.
614
+
603
615
  ### `<AuthState>` component
604
616
 
605
617
  You can use the `<AuthState>` component to safely display auth-related data in your components without worrying about the rendering mode.
@@ -617,7 +629,7 @@ One common use case if the Login button in the header:
617
629
  </template>
618
630
  ```
619
631
 
620
- If the page is cached or prerendered, nothing will be rendered until the user session is fetched on the client-side.
632
+ If the page is cached or prerendered or the load strategy set as `client-only`, nothing will be rendered until the user session is fetched on the client-side.
621
633
 
622
634
  You can use the `placeholder` slot to show a placeholder on server-side and while the user session is being fetched on client-side for the prerendered pages:
623
635
 
package/dist/module.d.mts CHANGED
@@ -22,6 +22,11 @@ interface ModuleOptions {
22
22
  */
23
23
  scrypt?: ScryptConfig;
24
24
  };
25
+ /**
26
+ * Session load strategy
27
+ * @default 'server-first'
28
+ */
29
+ loadStrategy?: 'server-first' | 'client-only';
25
30
  }
26
31
  declare module 'nuxt/schema' {
27
32
  interface RuntimeConfig {
@@ -33,7 +38,13 @@ declare module 'nuxt/schema' {
33
38
  */
34
39
  session: SessionConfig;
35
40
  }
41
+ interface PublicRuntimeConfig {
42
+ auth: {
43
+ loadStrategy: 'server-first' | 'client-only';
44
+ };
45
+ }
36
46
  }
37
47
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
38
48
 
39
- export { type ModuleOptions, _default as default };
49
+ export { _default as default };
50
+ export type { ModuleOptions };
package/dist/module.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "auth-utils",
3
3
  "configKey": "auth",
4
- "version": "0.5.23",
4
+ "version": "0.5.25",
5
5
  "builder": {
6
- "@nuxt/module-builder": "0.8.4",
7
- "unbuild": "2.0.0"
6
+ "@nuxt/module-builder": "1.0.2",
7
+ "unbuild": "3.6.1"
8
8
  }
9
9
  }
package/dist/module.mjs CHANGED
@@ -16,7 +16,8 @@ const module = defineNuxtModule({
16
16
  atproto: false,
17
17
  hash: {
18
18
  scrypt: {}
19
- }
19
+ },
20
+ loadStrategy: "server-first"
20
21
  },
21
22
  async setup(options, nuxt) {
22
23
  const resolver = createResolver(import.meta.url);
@@ -83,17 +84,24 @@ const module = defineNuxtModule({
83
84
  scrypt: options.hash?.scrypt
84
85
  });
85
86
  if (nuxt.options.dev && !process.env[envSessionPassword]) {
86
- const password = process.env[envSessionPassword] = randomUUID().replace(/-/g, "");
87
- const envPath = join(nuxt.options.rootDir, ".env");
88
- const envContent = await readFile(envPath, "utf-8").catch(() => "");
89
- if (!envContent.includes(envSessionPassword)) {
90
- await writeFile(
91
- envPath,
92
- `${envContent ? envContent + "\n" : envContent}${envSessionPassword}=${password}`,
93
- "utf-8"
94
- );
87
+ if (nuxt.options.runtimeConfig.session.password) {
88
+ process.env[envSessionPassword] = nuxt.options.runtimeConfig.session.password;
89
+ } else {
90
+ const password = process.env[envSessionPassword] = randomUUID().replace(/-/g, "");
91
+ const envPath = join(nuxt.options.rootDir, ".env");
92
+ const envContent = await readFile(envPath, "utf-8").catch(() => "");
93
+ if (!envContent.includes(envSessionPassword)) {
94
+ await writeFile(
95
+ envPath,
96
+ `${envContent ? envContent + "\n" : envContent}${envSessionPassword}=${password}`,
97
+ "utf-8"
98
+ );
99
+ }
95
100
  }
96
101
  }
102
+ runtimeConfig.public.auth = defu(runtimeConfig.public.auth, {
103
+ loadStrategy: options.loadStrategy ?? "server-first"
104
+ });
97
105
  runtimeConfig.webauthn = defu(runtimeConfig.webauthn, {
98
106
  register: {},
99
107
  authenticate: {}
@@ -1,7 +1,6 @@
1
- <script lang="ts" setup>
2
- import { useUserSession } from '#imports'
3
-
4
- const { loggedIn, user, session, clear, ready } = useUserSession()
1
+ <script setup>
2
+ import { useUserSession } from "#imports";
3
+ const { loggedIn, user, session, clear, ready } = useUserSession();
5
4
  </script>
6
5
 
7
6
  <template>
@@ -0,0 +1,19 @@
1
+ declare var __VLS_1: {
2
+ loggedIn: boolean;
3
+ user: import("../../types/index.js").User | null;
4
+ session: import("../../types/index.js").UserSession | null;
5
+ clear: () => Promise<void>;
6
+ }, __VLS_3: {};
7
+ type __VLS_Slots = {} & {
8
+ default?: (props: typeof __VLS_1) => any;
9
+ } & {
10
+ placeholder?: (props: typeof __VLS_3) => any;
11
+ };
12
+ declare const __VLS_component: import("vue-demi").DefineComponent<{}, {}, {}, {}, {}, import("vue-demi").ComponentOptionsMixin, import("vue-demi").ComponentOptionsMixin, {}, string, import("vue-demi").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue-demi").ComponentProvideOptions, true, {}, any>;
13
+ declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
14
+ export default _default;
15
+ type __VLS_WithSlots<T, S> = T & {
16
+ new (): {
17
+ $slots: S;
18
+ };
19
+ };
@@ -1,2 +1,2 @@
1
- declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
1
+ declare const _default: any;
2
2
  export default _default;
@@ -2,7 +2,7 @@ import { defineNuxtPlugin, useUserSession, useError } from "#imports";
2
2
  export default defineNuxtPlugin(async (nuxtApp) => {
3
3
  if (!nuxtApp.payload.serverRendered) {
4
4
  await useUserSession().fetch();
5
- } else if (Boolean(nuxtApp.payload.prerenderedAt) || Boolean(nuxtApp.payload.isCached)) {
5
+ } else if (Boolean(nuxtApp.payload.prerenderedAt) || Boolean(nuxtApp.payload.isCached) || nuxtApp.$config.public.auth.loadStrategy === "client-only") {
6
6
  nuxtApp.hook("app:mounted", async () => {
7
7
  await useUserSession().fetch();
8
8
  });
@@ -1,2 +1,2 @@
1
- declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
1
+ declare const _default: any;
2
2
  export default _default;
@@ -4,7 +4,7 @@ export default defineNuxtPlugin({
4
4
  enforce: "pre",
5
5
  async setup(nuxtApp) {
6
6
  nuxtApp.payload.isCached = Boolean(useRequestEvent()?.context.cache);
7
- if (nuxtApp.payload.serverRendered && !nuxtApp.payload.prerenderedAt && !nuxtApp.payload.isCached) {
7
+ if (nuxtApp.payload.serverRendered && !nuxtApp.payload.prerenderedAt && !nuxtApp.payload.isCached && nuxtApp.$config.public.auth.loadStrategy !== "client-only") {
8
8
  await useUserSession().fetch();
9
9
  }
10
10
  }
@@ -1,6 +1,6 @@
1
1
  declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<{
2
2
  [key: string]: unknown;
3
3
  id: string;
4
- user?: import("../../types").User;
4
+ user?: import("../../types/index.js").User;
5
5
  }>>;
6
6
  export default _default;
@@ -15,6 +15,17 @@ export function defineOAuthAuth0EventHandler({ config, onSuccess, onError }) {
15
15
  const tokenURL = `https://${config.domain}/oauth/token`;
16
16
  const query = getQuery(event);
17
17
  const redirectURL = config.redirectURL || getOAuthRedirectURL(event);
18
+ if (query.error) {
19
+ return handleAccessTokenErrorResponse(
20
+ event,
21
+ "auth0",
22
+ {
23
+ error: query.error,
24
+ error_description: query.error_description
25
+ },
26
+ onError
27
+ );
28
+ }
18
29
  if (!query.code) {
19
30
  config.scope = config.scope || ["openid", "offline_access"];
20
31
  if (config.emailRequired && !config.scope.includes("email")) {
@@ -21,5 +21,10 @@ export interface OAuthAuthentikConfig {
21
21
  * @default process.env.NUXT_OAUTH_AUTHENTIK_REDIRECT_URL or current URL
22
22
  */
23
23
  redirectURL?: string;
24
+ /**
25
+ * Authentik Scope
26
+ * @default ['openid', 'profile', 'email']
27
+ */
28
+ scope?: string[];
24
29
  }
25
30
  export declare function defineOAuthAuthentikEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthAuthentikConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void>>;
@@ -29,7 +29,7 @@ export function defineOAuthAuthentikEventHandler({ config, onSuccess, onError })
29
29
  response_type: "code",
30
30
  client_id: config.clientId,
31
31
  redirect_uri: redirectURL,
32
- scope: ["openid", "profile", "email"].join(" ")
32
+ scope: (config.scope || ["openid", "profile", "email"]).join(" ")
33
33
  })
34
34
  );
35
35
  }
@@ -1,5 +1,3 @@
1
+ import type { EventHandler } from 'h3';
1
2
  import type { WebAuthnAuthenticateEventHandlerOptions, WebAuthnCredential } from '#auth-utils';
2
- export declare function defineWebAuthnAuthenticateEventHandler<T extends WebAuthnCredential>({ storeChallenge, getChallenge, getCredential, allowCredentials, getOptions, onSuccess, onError, }: WebAuthnAuthenticateEventHandlerOptions<T>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void | import("@simplewebauthn/server").VerifiedAuthenticationResponse | {
3
- requestOptions: import("@simplewebauthn/types").PublicKeyCredentialRequestOptionsJSON;
4
- attemptId: string;
5
- }>>;
3
+ export declare function defineWebAuthnAuthenticateEventHandler<T extends WebAuthnCredential>({ storeChallenge, getChallenge, getCredential, allowCredentials, getOptions, onSuccess, onError, }: WebAuthnAuthenticateEventHandlerOptions<T>): EventHandler;
@@ -28,7 +28,7 @@ export function defineWebAuthnAuthenticateEventHandler({
28
28
  _config.allowCredentials = await allowCredentials(event, body.userName);
29
29
  }
30
30
  const options = await generateAuthenticationOptions(_config);
31
- const attemptId = bufferToBase64URLString(getRandomValues(new Uint8Array(32)));
31
+ const attemptId = bufferToBase64URLString(getRandomValues(new Uint8Array(32)).buffer);
32
32
  if (storeChallenge) {
33
33
  await storeChallenge(event, options.challenge, attemptId);
34
34
  }
@@ -1,8 +1,5 @@
1
- import type { H3Event } from 'h3';
1
+ import type { H3Event, EventHandler } from 'h3';
2
2
  import type { ValidateUserFunction } from '../../../types/webauthn.js';
3
3
  import type { WebAuthnUser, WebAuthnRegisterEventHandlerOptions } from '#auth-utils';
4
- export declare function defineWebAuthnRegisterEventHandler<T extends WebAuthnUser>({ storeChallenge, getChallenge, getOptions, validateUser, excludeCredentials, onSuccess, onError, }: WebAuthnRegisterEventHandlerOptions<T>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<void | import("@simplewebauthn/server").VerifiedRegistrationResponse | {
5
- creationOptions: import("@simplewebauthn/types").PublicKeyCredentialCreationOptionsJSON;
6
- attemptId: string;
7
- }>>;
4
+ export declare function defineWebAuthnRegisterEventHandler<T extends WebAuthnUser>({ storeChallenge, getChallenge, getOptions, validateUser, excludeCredentials, onSuccess, onError, }: WebAuthnRegisterEventHandlerOptions<T>): EventHandler;
8
5
  export declare function validateUserData<T>(userBody: WebAuthnUser, event: H3Event, fn: ValidateUserFunction<T>): Promise<T>;
@@ -43,7 +43,7 @@ export function defineWebAuthnRegisterEventHandler({
43
43
  _config.excludeCredentials = await excludeCredentials(event, user.userName);
44
44
  }
45
45
  const options = await generateRegistrationOptions(_config);
46
- const attemptId = bufferToBase64URLString(getRandomValues(new Uint8Array(32)));
46
+ const attemptId = bufferToBase64URLString(getRandomValues(new Uint8Array(32)).buffer);
47
47
  if (storeChallenge) {
48
48
  await storeChallenge(event, options.challenge, attemptId);
49
49
  }
@@ -81,7 +81,7 @@ export function defineWebAuthnRegisterEventHandler({
81
81
  user,
82
82
  credential: {
83
83
  id: verification.registrationInfo.credential.id,
84
- publicKey: bufferToBase64URLString(verification.registrationInfo.credential.publicKey),
84
+ publicKey: bufferToBase64URLString(verification.registrationInfo.credential.publicKey.buffer),
85
85
  counter: verification.registrationInfo.credential.counter,
86
86
  backedUp: verification.registrationInfo.credentialBackedUp,
87
87
  transports: verification.registrationInfo.credential.transports
@@ -1,2 +1,2 @@
1
- declare const _default: import("nitropack/types").NitroAppPlugin;
1
+ declare const _default: import("nitropack").NitroAppPlugin;
2
2
  export default _default;
@@ -1,2 +1,2 @@
1
- declare const _default: import("nitropack/types").NitroAppPlugin;
1
+ declare const _default: import("nitropack").NitroAppPlugin;
2
2
  export default _default;
@@ -2,15 +2,16 @@ export const atprotoProviders = ["bluesky"];
2
2
  export const atprotoProviderDefaultClientMetadata = {
3
3
  clientMetadataFilename: "",
4
4
  clientName: "",
5
- clientUri: "",
6
- logoUri: "",
7
- policyUri: "",
8
- tosUri: "",
5
+ clientUri: void 0,
6
+ logoUri: void 0,
7
+ policyUri: void 0,
8
+ tosUri: void 0,
9
9
  scope: ["atproto"],
10
10
  grantTypes: ["authorization_code"],
11
11
  responseTypes: ["code"],
12
12
  applicationType: "web",
13
- redirectUris: [],
13
+ // @ts-expect-error TypeScript is too smart for its own good
14
+ redirectUris: void 0,
14
15
  dpopBoundAccessTokens: true,
15
16
  tokenEndpointAuthMethod: "none"
16
17
  };
package/dist/types.d.mts CHANGED
@@ -1 +1,3 @@
1
- export { type ModuleOptions, default } from './module.js'
1
+ export { default } from './module.mjs'
2
+
3
+ export { type ModuleOptions } from './module.mjs'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-auth-utils",
3
- "version": "0.5.23",
3
+ "version": "0.5.25",
4
4
  "description": "Add Authentication to Nuxt applications with secured & sealed cookies sessions.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,16 +8,21 @@
8
8
  },
9
9
  "license": "MIT",
10
10
  "type": "module",
11
- "packageManager": "pnpm@9.15.4",
11
+ "packageManager": "pnpm@10.16.1",
12
12
  "exports": {
13
13
  ".": {
14
- "types": "./dist/types.d.ts",
15
- "import": "./dist/module.mjs",
16
- "require": "./dist/module.cjs"
14
+ "types": "./dist/types.d.mts",
15
+ "import": "./dist/module.mjs"
16
+ }
17
+ },
18
+ "main": "./dist/module.mjs",
19
+ "typesVersions": {
20
+ "*": {
21
+ ".": [
22
+ "./dist/types.d.mts"
23
+ ]
17
24
  }
18
25
  },
19
- "main": "./dist/module.cjs",
20
- "types": "./dist/types.d.ts",
21
26
  "files": [
22
27
  "dist"
23
28
  ],
@@ -30,19 +35,18 @@
30
35
  "lint": "eslint .",
31
36
  "lint:fix": "eslint . --fix",
32
37
  "test": "vitest run",
33
- "test:types": "vue-tsc --noEmit",
34
- "test:types:playground": "nuxt typecheck playground",
38
+ "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
35
39
  "test:watch": "vitest watch"
36
40
  },
37
41
  "dependencies": {
38
42
  "@adonisjs/hash": "^9.1.1",
39
- "@nuxt/kit": "^3.18.1",
43
+ "@nuxt/kit": "^4.1.2",
40
44
  "defu": "^6.1.4",
41
45
  "h3": "^1.15.4",
42
46
  "hookable": "^5.5.3",
43
- "jose": "^5.10.0",
47
+ "jose": "^6.1.0",
44
48
  "ofetch": "^1.4.1",
45
- "openid-client": "^6.6.2",
49
+ "openid-client": "^6.8.0",
46
50
  "pathe": "^2.0.3",
47
51
  "scule": "^1.3.0",
48
52
  "uncrypto": "^0.1.3"
@@ -68,20 +72,20 @@
68
72
  }
69
73
  },
70
74
  "devDependencies": {
71
- "@iconify-json/simple-icons": "^1.2.46",
72
- "@nuxt/devtools": "2.0.0-beta.7",
73
- "@nuxt/eslint-config": "^0.7.6",
74
- "@nuxt/module-builder": "^0.8.4",
75
- "@nuxt/schema": "^3.15.4",
76
- "@nuxt/test-utils": "^3.15.4",
77
- "@nuxt/ui": "^2.21.0",
78
- "@nuxt/ui-pro": "^1.7.0",
79
- "@simplewebauthn/types": "^11.0.0",
80
- "changelogen": "^0.5.7",
81
- "eslint": "^9.32.0",
82
- "nuxt": "^3.18.1",
83
- "typescript": "5.6.3",
84
- "vitest": "^3.0.5",
85
- "vue-tsc": "^2.2.12"
75
+ "@iconify-json/simple-icons": "^1.2.52",
76
+ "@nuxt/devtools": "2.6.3",
77
+ "@nuxt/eslint-config": "^1.9.0",
78
+ "@nuxt/module-builder": "^1.0.2",
79
+ "@nuxt/schema": "^4.1.2",
80
+ "@nuxt/test-utils": "^3.19.2",
81
+ "@types/node": "latest",
82
+ "@nuxt/ui": "^4.0.0-alpha.1",
83
+ "@simplewebauthn/types": "^12.0.0",
84
+ "changelogen": "^0.6.2",
85
+ "eslint": "^9.35.0",
86
+ "nuxt": "^4.1.2",
87
+ "typescript": "5.9.2",
88
+ "vitest": "^3.2.4",
89
+ "vue-tsc": "^3.0.7"
86
90
  }
87
91
  }
package/dist/module.cjs DELETED
@@ -1,5 +0,0 @@
1
- module.exports = function(...args) {
2
- return import('./module.mjs').then(m => m.default.call(this, ...args))
3
- }
4
- const _meta = module.exports.meta = require('./module.json')
5
- module.exports.getMeta = () => Promise.resolve(_meta)
package/dist/module.d.ts DELETED
@@ -1,39 +0,0 @@
1
- import * as _nuxt_schema from '@nuxt/schema';
2
- import { ScryptConfig } from '@adonisjs/hash/types';
3
- import { SessionConfig } from 'h3';
4
-
5
- interface ModuleOptions {
6
- /**
7
- * Enable WebAuthn (Passkeys)
8
- * @default false
9
- */
10
- webAuthn?: boolean;
11
- /**
12
- * Enable atproto OAuth (Bluesky, etc.)
13
- * @default false
14
- */
15
- atproto?: boolean;
16
- /**
17
- * Hash options used for password hashing
18
- */
19
- hash?: {
20
- /**
21
- * scrypt options used for password hashing
22
- */
23
- scrypt?: ScryptConfig;
24
- };
25
- }
26
- declare module 'nuxt/schema' {
27
- interface RuntimeConfig {
28
- hash: {
29
- scrypt: ScryptConfig;
30
- };
31
- /**
32
- * Session configuration
33
- */
34
- session: SessionConfig;
35
- }
36
- }
37
- declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
38
-
39
- export { type ModuleOptions, _default as default };
package/dist/types.d.ts DELETED
@@ -1 +0,0 @@
1
- export { type ModuleOptions, default } from './module'