nuxt-auth-utils 0.5.25 → 0.5.27

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 (71) hide show
  1. package/README.md +30 -6
  2. package/dist/module.d.mts +3 -4
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +21 -6
  5. package/dist/runtime/app/components/AuthState.vue.d.ts +7 -6
  6. package/dist/runtime/server/api/session.get.d.ts +1 -5
  7. package/dist/runtime/server/lib/atproto/bluesky.d.ts +1 -1
  8. package/dist/runtime/server/lib/oauth/apple.d.ts +1 -1
  9. package/dist/runtime/server/lib/oauth/atlassian.d.ts +1 -1
  10. package/dist/runtime/server/lib/oauth/auth0.d.ts +1 -1
  11. package/dist/runtime/server/lib/oauth/authentik.d.ts +1 -1
  12. package/dist/runtime/server/lib/oauth/azureb2c.d.ts +1 -1
  13. package/dist/runtime/server/lib/oauth/azureb2c.js +0 -1
  14. package/dist/runtime/server/lib/oauth/battledotnet.d.ts +1 -1
  15. package/dist/runtime/server/lib/oauth/cognito.d.ts +1 -1
  16. package/dist/runtime/server/lib/oauth/discord.d.ts +1 -1
  17. package/dist/runtime/server/lib/oauth/dropbox.d.ts +1 -1
  18. package/dist/runtime/server/lib/oauth/facebook.d.ts +1 -1
  19. package/dist/runtime/server/lib/oauth/gitea.d.ts +1 -1
  20. package/dist/runtime/server/lib/oauth/github.d.ts +1 -1
  21. package/dist/runtime/server/lib/oauth/gitlab.d.ts +1 -1
  22. package/dist/runtime/server/lib/oauth/google.d.ts +1 -1
  23. package/dist/runtime/server/lib/oauth/heroku.d.ts +1 -1
  24. package/dist/runtime/server/lib/oauth/hubspot.d.ts +1 -1
  25. package/dist/runtime/server/lib/oauth/instagram.d.ts +1 -1
  26. package/dist/runtime/server/lib/oauth/keycloak.d.ts +1 -1
  27. package/dist/runtime/server/lib/oauth/kick.d.ts +1 -1
  28. package/dist/runtime/server/lib/oauth/line.d.ts +1 -1
  29. package/dist/runtime/server/lib/oauth/linear.d.ts +1 -1
  30. package/dist/runtime/server/lib/oauth/linkedin.d.ts +1 -1
  31. package/dist/runtime/server/lib/oauth/livechat.d.ts +2 -3
  32. package/dist/runtime/server/lib/oauth/livechat.js +1 -3
  33. package/dist/runtime/server/lib/oauth/microsoft.d.ts +1 -1
  34. package/dist/runtime/server/lib/oauth/oidc.d.ts +216 -0
  35. package/dist/runtime/server/lib/oauth/oidc.js +83 -0
  36. package/dist/runtime/server/lib/oauth/okta.d.ts +1 -1
  37. package/dist/runtime/server/lib/oauth/ory.d.ts +1 -1
  38. package/dist/runtime/server/lib/oauth/ory.js +1 -1
  39. package/dist/runtime/server/lib/oauth/paypal.d.ts +1 -1
  40. package/dist/runtime/server/lib/oauth/polar.d.ts +1 -1
  41. package/dist/runtime/server/lib/oauth/roblox.d.ts +1 -1
  42. package/dist/runtime/server/lib/oauth/salesforce.d.ts +1 -1
  43. package/dist/runtime/server/lib/oauth/seznam.d.ts +1 -1
  44. package/dist/runtime/server/lib/oauth/shopifyCustomer.d.ts +26 -0
  45. package/dist/runtime/server/lib/oauth/shopifyCustomer.js +90 -0
  46. package/dist/runtime/server/lib/oauth/slack.d.ts +1 -1
  47. package/dist/runtime/server/lib/oauth/spotify.d.ts +1 -1
  48. package/dist/runtime/server/lib/oauth/steam.d.ts +1 -1
  49. package/dist/runtime/server/lib/oauth/steam.js +2 -1
  50. package/dist/runtime/server/lib/oauth/strava.d.ts +1 -1
  51. package/dist/runtime/server/lib/oauth/tiktok.d.ts +1 -1
  52. package/dist/runtime/server/lib/oauth/twitch.d.ts +1 -1
  53. package/dist/runtime/server/lib/oauth/vk.d.ts +1 -1
  54. package/dist/runtime/server/lib/oauth/workos.d.ts +1 -1
  55. package/dist/runtime/server/lib/oauth/x.d.ts +1 -1
  56. package/dist/runtime/server/lib/oauth/x.js +18 -12
  57. package/dist/runtime/server/lib/oauth/xsuaa.d.ts +1 -1
  58. package/dist/runtime/server/lib/oauth/yandex.d.ts +1 -1
  59. package/dist/runtime/server/lib/oauth/zitadel.d.ts +1 -1
  60. package/dist/runtime/server/lib/oauth/zitadel.js +5 -4
  61. package/dist/runtime/server/lib/utils.d.ts +9 -9
  62. package/dist/runtime/server/lib/utils.js +36 -20
  63. package/dist/runtime/server/lib/webauthn/register.js +2 -1
  64. package/dist/runtime/server/plugins/oauth.d.ts +1 -1
  65. package/dist/runtime/server/utils/password.d.ts +17 -0
  66. package/dist/runtime/server/utils/password.js +3 -0
  67. package/dist/runtime/server/utils/session.d.ts +3 -2
  68. package/dist/runtime/types/oauth-config.d.ts +1 -1
  69. package/dist/runtime/types/utils.d.ts +14 -0
  70. package/dist/runtime/types/webauthn.d.ts +1 -0
  71. package/package.json +18 -18
@@ -1,5 +1,5 @@
1
1
  import { eventHandler, getQuery, sendRedirect } from "h3";
2
- import { withQuery } from "ufo";
2
+ import { hasProtocol, withQuery } from "ufo";
3
3
  import { defu } from "defu";
4
4
  import { handleMissingConfiguration, handleAccessTokenErrorResponse, getOAuthRedirectURL, requestAccessToken, handleState, handlePkceVerifier, handleInvalidState } from "../utils.js";
5
5
  import { useRuntimeConfig, createError } from "#imports";
@@ -21,8 +21,9 @@ export function defineOAuthZitadelEventHandler({ config, onSuccess, onError }) {
21
21
  if (!config.clientId || !config.domain) {
22
22
  return handleMissingConfiguration(event, "zitadel", ["clientId", "domain"], onError);
23
23
  }
24
- const authorizationURL = `https://${config.domain}/oauth/v2/authorize`;
25
- const tokenURL = `https://${config.domain}/oauth/v2/token`;
24
+ const domain = hasProtocol(config.domain) ? config.domain : `https://${config.domain}`;
25
+ const authorizationURL = `${domain}/oauth/v2/authorize`;
26
+ const tokenURL = `${domain}/oauth/v2/token`;
26
27
  const redirectURL = config.redirectURL || getOAuthRedirectURL(event);
27
28
  const verifier = await handlePkceVerifier(event);
28
29
  const state = await handleState(event);
@@ -66,7 +67,7 @@ export function defineOAuthZitadelEventHandler({ config, onSuccess, onError }) {
66
67
  return handleAccessTokenErrorResponse(event, "zitadel", tokens, onError);
67
68
  }
68
69
  const accessToken = tokens.access_token;
69
- const user = await $fetch(`https://${config.domain}/oidc/v1/userinfo`, {
70
+ const user = await $fetch(`${domain}/oidc/v1/userinfo`, {
70
71
  headers: {
71
72
  Authorization: `Bearer ${accessToken}`,
72
73
  Accept: "application/json"
@@ -26,15 +26,15 @@ export interface RequestAccessTokenOptions {
26
26
  *
27
27
  * @see https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.3
28
28
  */
29
- export declare function requestAccessToken(url: string, options: RequestAccessTokenOptions): Promise<any>;
29
+ export declare function requestAccessToken<T = any>(url: string, options: RequestAccessTokenOptions): Promise<T>;
30
30
  /**
31
31
  * Handle OAuth access token error response
32
32
  *
33
33
  * @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
34
34
  */
35
- export declare function handleAccessTokenErrorResponse(event: H3Event, oauthProvider: OAuthProvider, oauthError: any, onError?: OnError): void | Promise<void>;
36
- export declare function handleMissingConfiguration(event: H3Event, provider: OAuthProvider, missingKeys: string[], onError?: OnError): void | Promise<void>;
37
- export declare function handleInvalidState(event: H3Event, provider: OAuthProvider, onError?: OnError): void | Promise<void>;
35
+ export declare function handleAccessTokenErrorResponse(event: H3Event, oauthProvider: OAuthProvider, oauthError: any, onError?: OnError): any;
36
+ export declare function handleMissingConfiguration(event: H3Event, provider: OAuthProvider, missingKeys: string[], onError?: OnError): any;
37
+ export declare function handleInvalidState(event: H3Event, provider: OAuthProvider, onError?: OnError): any;
38
38
  /**
39
39
  * JWT signing using jose
40
40
  *
@@ -61,13 +61,13 @@ interface JWTVerifyOptions {
61
61
  }
62
62
  export declare function verifyJwt<T>(token: string, options: JWTVerifyOptions): Promise<T>;
63
63
  export declare function handlePkceVerifier(event: H3Event): Promise<{
64
- code_verifier: string;
65
- code_challenge?: undefined;
66
- code_challenge_method?: undefined;
67
- } | {
68
64
  code_verifier: string;
69
65
  code_challenge: string;
70
66
  code_challenge_method: string;
67
+ } | {
68
+ code_verifier: string | undefined;
69
+ code_challenge?: undefined;
70
+ code_challenge_method?: undefined;
71
71
  }>;
72
- export declare function handleState(event: H3Event): Promise<string>;
72
+ export declare function handleState(event: H3Event): Promise<string | undefined>;
73
73
  export {};
@@ -1,10 +1,12 @@
1
- import { deleteCookie, getCookie, setCookie } from "h3";
1
+ import { deleteCookie, getCookie, getQuery, setCookie } from "h3";
2
2
  import { getRequestURL } from "h3";
3
3
  import { FetchError } from "ofetch";
4
4
  import { snakeCase, upperFirst } from "scule";
5
5
  import * as jose from "jose";
6
6
  import { subtle, getRandomValues } from "uncrypto";
7
7
  import { createError } from "#imports";
8
+ const isDevelopment = process.env.NODE_ENV === "development";
9
+ const OAUTH_COOKIE_MAX_AGE = 60 * 10;
8
10
  export function getOAuthRedirectURL(event) {
9
11
  const requestURL = getRequestURL(event);
10
12
  return `${requestURL.protocol}//${requestURL.host}${requestURL.pathname}`;
@@ -79,29 +81,43 @@ function getRandomBytes(size = 32) {
79
81
  return getRandomValues(new Uint8Array(size));
80
82
  }
81
83
  export async function handlePkceVerifier(event) {
82
- let verifier = getCookie(event, "nuxt-auth-pkce");
83
- if (verifier) {
84
- deleteCookie(event, "nuxt-auth-pkce");
85
- return { code_verifier: verifier };
84
+ const query = getQuery(event);
85
+ if (!query.code) {
86
+ const verifier2 = encodeBase64Url(getRandomBytes());
87
+ setCookie(event, "nuxt-auth-pkce", verifier2, {
88
+ httpOnly: true,
89
+ secure: !isDevelopment,
90
+ sameSite: "lax",
91
+ maxAge: OAUTH_COOKIE_MAX_AGE,
92
+ path: "/"
93
+ });
94
+ const encodedPkce = new TextEncoder().encode(verifier2);
95
+ const pkceHash = await subtle.digest("SHA-256", encodedPkce);
96
+ const pkce = encodeBase64Url(new Uint8Array(pkceHash));
97
+ return {
98
+ code_verifier: verifier2,
99
+ code_challenge: pkce,
100
+ code_challenge_method: "S256"
101
+ };
86
102
  }
87
- verifier = encodeBase64Url(getRandomBytes());
88
- setCookie(event, "nuxt-auth-pkce", verifier);
89
- const encodedPkce = new TextEncoder().encode(verifier);
90
- const pkceHash = await subtle.digest("SHA-256", encodedPkce);
91
- const pkce = encodeBase64Url(new Uint8Array(pkceHash));
92
- return {
93
- code_verifier: verifier,
94
- code_challenge: pkce,
95
- code_challenge_method: "S256"
96
- };
103
+ const verifier = getCookie(event, "nuxt-auth-pkce");
104
+ deleteCookie(event, "nuxt-auth-pkce");
105
+ return { code_verifier: verifier };
97
106
  }
98
107
  export async function handleState(event) {
99
- let state = getCookie(event, "nuxt-auth-state");
100
- if (state) {
108
+ const query = getQuery(event);
109
+ if (query.state) {
110
+ const state2 = getCookie(event, "nuxt-auth-state");
101
111
  deleteCookie(event, "nuxt-auth-state");
102
- return state;
112
+ return state2;
103
113
  }
104
- state = encodeBase64Url(getRandomBytes(8));
105
- setCookie(event, "nuxt-auth-state", state);
114
+ const state = encodeBase64Url(getRandomBytes(8));
115
+ setCookie(event, "nuxt-auth-state", state, {
116
+ httpOnly: true,
117
+ secure: !isDevelopment,
118
+ sameSite: "lax",
119
+ maxAge: OAUTH_COOKIE_MAX_AGE,
120
+ path: "/"
121
+ });
106
122
  return state;
107
123
  }
@@ -84,7 +84,8 @@ export function defineWebAuthnRegisterEventHandler({
84
84
  publicKey: bufferToBase64URLString(verification.registrationInfo.credential.publicKey.buffer),
85
85
  counter: verification.registrationInfo.credential.counter,
86
86
  backedUp: verification.registrationInfo.credentialBackedUp,
87
- transports: verification.registrationInfo.credential.transports
87
+ transports: verification.registrationInfo.credential.transports,
88
+ aaguid: verification.registrationInfo.aaguid
88
89
  },
89
90
  registrationInfo: verification.registrationInfo
90
91
  });
@@ -1,2 +1,2 @@
1
- declare const _default: import("nitropack").NitroAppPlugin;
1
+ declare const _default: import("nitropack/types").NitroAppPlugin;
2
2
  export default _default;
@@ -21,3 +21,20 @@ export declare function hashPassword(password: string): Promise<string>;
21
21
  * @more you can configure the scrypt options in `auth.hash.scrypt`
22
22
  */
23
23
  export declare function verifyPassword(hashedPassword: string, plainPassword: string): Promise<boolean>;
24
+ /**
25
+ * Check if the hash value needs a rehash or not. The rehash is required if
26
+ * configuration settings have changed.
27
+ * @param hashedPassword - The hashed password to check
28
+ * @returns `true` if a rehash is needed, `false` otherwise
29
+ * @example
30
+ * ```ts
31
+ * const isValid = await verifyPassword(hashedPassword, plainText)
32
+ *
33
+ * // Plain password is valid, and hash needs a rehash
34
+ * if (isValid && passwordNeedsReHash(hashedPassword)) {
35
+ * const newHash = await hashPassword(plainText)
36
+ * }
37
+ * ```
38
+ * @more you can configure the scrypt options in `auth.hash.scrypt`
39
+ */
40
+ export declare function passwordNeedsReHash(hashedPassword: string): boolean;
@@ -16,3 +16,6 @@ export async function hashPassword(password) {
16
16
  export async function verifyPassword(hashedPassword, plainPassword) {
17
17
  return await getHash().verify(hashedPassword, plainPassword);
18
18
  }
19
+ export function passwordNeedsReHash(hashedPassword) {
20
+ return getHash().needsReHash(hashedPassword);
21
+ }
@@ -1,5 +1,6 @@
1
1
  import type { H3Event, SessionConfig } from 'h3';
2
2
  import { useSession } from 'h3';
3
+ import type { OmitWithIndexSignature } from '../../types/utils.js';
3
4
  import type { UserSession, UserSessionRequired } from '#auth-utils';
4
5
  type UseSessionEvent = Parameters<typeof useSession>[0];
5
6
  export interface SessionHooks {
@@ -27,13 +28,13 @@ export declare function getUserSession(event: UseSessionEvent): Promise<UserSess
27
28
  * @param data User session data, please only store public information since it can be decoded with API calls
28
29
  * @see https://github.com/atinux/nuxt-auth-utils
29
30
  */
30
- export declare function setUserSession(event: H3Event, data: Omit<UserSession, 'id'>, config?: Partial<SessionConfig>): Promise<UserSession>;
31
+ export declare function setUserSession(event: H3Event, data: OmitWithIndexSignature<UserSession, 'id'>, config?: Partial<SessionConfig>): Promise<UserSession>;
31
32
  /**
32
33
  * Replace a user session
33
34
  * @param event The Request (h3) event
34
35
  * @param data User session data, please only store public information since it can be decoded with API calls
35
36
  */
36
- export declare function replaceUserSession(event: H3Event, data: Omit<UserSession, 'id'>, config?: Partial<SessionConfig>): Promise<UserSession>;
37
+ export declare function replaceUserSession(event: H3Event, data: OmitWithIndexSignature<UserSession, 'id'>, config?: Partial<SessionConfig>): Promise<UserSession>;
37
38
  /**
38
39
  * Clear the user session and removing the session cookie
39
40
  * @param event The Request (h3) event
@@ -1,6 +1,6 @@
1
1
  import type { H3Event, H3Error } from 'h3';
2
2
  export type ATProtoProvider = 'bluesky';
3
- export type OAuthProvider = ATProtoProvider | 'atlassian' | 'auth0' | 'authentik' | 'azureb2c' | 'battledotnet' | 'cognito' | 'discord' | 'dropbox' | 'facebook' | 'gitea' | 'github' | 'gitlab' | 'google' | 'hubspot' | 'instagram' | 'kick' | 'keycloak' | 'line' | 'linear' | 'linkedin' | 'microsoft' | 'paypal' | 'polar' | 'spotify' | 'seznam' | 'steam' | 'strava' | 'tiktok' | 'twitch' | 'vk' | 'workos' | 'x' | 'xsuaa' | 'yandex' | 'zitadel' | 'apple' | 'livechat' | 'salesforce' | 'slack' | 'heroku' | 'roblox' | 'okta' | 'ory' | (string & {});
3
+ export type OAuthProvider = ATProtoProvider | 'atlassian' | 'auth0' | 'authentik' | 'azureb2c' | 'battledotnet' | 'cognito' | 'discord' | 'dropbox' | 'facebook' | 'gitea' | 'github' | 'gitlab' | 'google' | 'hubspot' | 'instagram' | 'kick' | 'keycloak' | 'line' | 'linear' | 'linkedin' | 'microsoft' | 'paypal' | 'polar' | 'spotify' | 'seznam' | 'steam' | 'strava' | 'tiktok' | 'twitch' | 'vk' | 'workos' | 'x' | 'xsuaa' | 'yandex' | 'zitadel' | 'apple' | 'livechat' | 'salesforce' | 'slack' | 'heroku' | 'roblox' | 'okta' | 'ory' | 'shopifyCustomer' | 'oicd' | (string & {});
4
4
  export type OnError = (event: H3Event, error: H3Error) => Promise<void> | void;
5
5
  export interface OAuthConfig<TConfig, TResult = {
6
6
  user: any;
@@ -0,0 +1,14 @@
1
+ type Prettify<T> = {
2
+ [K in keyof T]: T[K]
3
+ }
4
+
5
+ type RemoveIndexSignature<T> = {
6
+ [K in keyof T as string extends K ? never : K]: T[K]
7
+ }
8
+
9
+ type GetIndexSignature<T> = {
10
+ [K in keyof T as string extends K ? K : never]: T[K]
11
+ }
12
+
13
+ // Basic Omit but does not break if a [x:string]:unknown Index Signature is present in the type
14
+ export type OmitWithIndexSignature<T extends Record<string, unknown>, K extends keyof RemoveIndexSignature<T>> = Prettify<Omit<RemoveIndexSignature<T>, K> & GetIndexSignature<T>>
@@ -8,6 +8,7 @@ export interface WebAuthnCredential {
8
8
  counter: number;
9
9
  backedUp: boolean;
10
10
  transports?: AuthenticatorTransportFuture[];
11
+ aaguid?: string;
11
12
  [key: string]: unknown;
12
13
  }
13
14
  export interface WebAuthnUser {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-auth-utils",
3
- "version": "0.5.25",
3
+ "version": "0.5.27",
4
4
  "description": "Add Authentication to Nuxt applications with secured & sealed cookies sessions.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "license": "MIT",
10
10
  "type": "module",
11
- "packageManager": "pnpm@10.16.1",
11
+ "packageManager": "pnpm@10.28.0",
12
12
  "exports": {
13
13
  ".": {
14
14
  "types": "./dist/types.d.mts",
@@ -40,13 +40,13 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@adonisjs/hash": "^9.1.1",
43
- "@nuxt/kit": "^4.1.2",
43
+ "@nuxt/kit": "^4.2.2",
44
44
  "defu": "^6.1.4",
45
45
  "h3": "^1.15.4",
46
- "hookable": "^5.5.3",
47
- "jose": "^6.1.0",
48
- "ofetch": "^1.4.1",
49
- "openid-client": "^6.8.0",
46
+ "hookable": "^6.0.1",
47
+ "jose": "^6.1.3",
48
+ "ofetch": "^1.5.1",
49
+ "openid-client": "^6.8.1",
50
50
  "pathe": "^2.0.3",
51
51
  "scule": "^1.3.0",
52
52
  "uncrypto": "^0.1.3"
@@ -72,20 +72,20 @@
72
72
  }
73
73
  },
74
74
  "devDependencies": {
75
- "@iconify-json/simple-icons": "^1.2.52",
76
- "@nuxt/devtools": "2.6.3",
77
- "@nuxt/eslint-config": "^1.9.0",
75
+ "@iconify-json/simple-icons": "^1.2.66",
76
+ "@nuxt/devtools": "3.1.1",
77
+ "@nuxt/eslint-config": "^1.12.1",
78
78
  "@nuxt/module-builder": "^1.0.2",
79
- "@nuxt/schema": "^4.1.2",
80
- "@nuxt/test-utils": "^3.19.2",
79
+ "@nuxt/schema": "^4.2.2",
80
+ "@nuxt/test-utils": "^3.23.0",
81
81
  "@types/node": "latest",
82
- "@nuxt/ui": "^4.0.0-alpha.1",
82
+ "@nuxt/ui": "^4.3.0",
83
83
  "@simplewebauthn/types": "^12.0.0",
84
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"
85
+ "eslint": "^9.39.2",
86
+ "nuxt": "^4.2.2",
87
+ "typescript": "5.9.3",
88
+ "vitest": "^4.0.17",
89
+ "vue-tsc": "^3.2.2"
90
90
  }
91
91
  }