nuxt-auth-utils 0.5.33 → 0.5.34

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
@@ -261,6 +261,7 @@ It can also be set using environment variables:
261
261
  - X (Twitter)
262
262
  - XSUAA
263
263
  - Yandex
264
+ - Zendesk
264
265
  - Zitadel
265
266
 
266
267
  You can add your favorite provider by creating a new file in [src/runtime/server/lib/oauth/](https://github.com/atinux/nuxt-auth-utils/tree/main/src/runtime/server/lib/oauth).
@@ -391,7 +392,7 @@ To enable WebAuthn you need to:
391
392
  1. Install the peer dependencies:
392
393
 
393
394
  ```bash
394
- npx nypm i @simplewebauthn/server@11 @simplewebauthn/browser@11
395
+ npx nypm i @simplewebauthn/server@13 @simplewebauthn/browser@13
395
396
  ```
396
397
 
397
398
  2. Enable it in your `nuxt.config.ts`
package/dist/module.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "auth-utils",
3
3
  "configKey": "auth",
4
- "version": "0.5.33",
4
+ "version": "0.5.34",
5
5
  "builder": {
6
- "@nuxt/module-builder": "1.0.2",
6
+ "@nuxt/module-builder": "1.0.3",
7
7
  "unbuild": "3.6.1"
8
8
  }
9
9
  }
package/dist/module.mjs CHANGED
@@ -436,6 +436,16 @@ const module$1 = defineNuxtModule({
436
436
  redirectURL: "",
437
437
  scope: []
438
438
  });
439
+ runtimeConfig.oauth.zendesk = defu(runtimeConfig.oauth.zendesk, {
440
+ clientId: "",
441
+ clientSecret: "",
442
+ subdomain: "",
443
+ redirectURL: "",
444
+ marketplaceName: "",
445
+ marketplaceOrgId: "",
446
+ marketplaceBotId: "",
447
+ marketplaceAppId: ""
448
+ });
439
449
  }
440
450
  });
441
451
 
@@ -0,0 +1,20 @@
1
+ declare var __VLS_1: {
2
+ loggedIn: any;
3
+ user: any;
4
+ session: any;
5
+ clear: any;
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_base: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
13
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
14
+ declare const _default: typeof __VLS_export;
15
+ export default _default;
16
+ type __VLS_WithSlots<T, S> = T & {
17
+ new (): {
18
+ $slots: S;
19
+ };
20
+ };
@@ -53,7 +53,7 @@ export function defineOAuthOktaEventHandler({ config, onSuccess, onError }) {
53
53
  openIdConfigCache.delete(openIdConfigurationUrl2);
54
54
  }
55
55
  }
56
- let openIdConfig2 = null;
56
+ let openIdConfig2;
57
57
  try {
58
58
  openIdConfig2 = await $fetch(openIdConfigurationUrl2);
59
59
  if (openIdConfig2) {
@@ -14,12 +14,15 @@ export interface OAuthSpotifyConfig {
14
14
  * Spotify OAuth Scope
15
15
  * @default []
16
16
  * @see https://developer.spotify.com/documentation/web-api/concepts/scopes
17
- * @example ['user-read-email']
17
+ * @example ['playlist-read-private']
18
18
  */
19
19
  scope?: string[];
20
20
  /**
21
21
  * Require email from user, adds the ['user-read-email'] scope if not present
22
+ *
23
+ * Spotify doesn't return the email to Development Mode apps created since February 11, 2026, nor to existing ones since March 9, 2026. Extended Quota Mode apps still receive it.
22
24
  * @default false
25
+ * @see https://developer.spotify.com/documentation/web-api/tutorials/february-2026-migration-guide
23
26
  */
24
27
  emailRequired?: boolean;
25
28
  /**
@@ -44,4 +47,48 @@ export interface OAuthSpotifyConfig {
44
47
  */
45
48
  redirectURL?: string;
46
49
  }
47
- export declare function defineOAuthSpotifyEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthSpotifyConfig>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
50
+ interface SpotifyUser {
51
+ /** Stable identifier, recommended by Spotify for account linking instead of `id` */
52
+ account_id: string;
53
+ display_name: string | null;
54
+ external_urls: {
55
+ spotify: string;
56
+ };
57
+ href: string;
58
+ id: string;
59
+ images: {
60
+ url: string;
61
+ height: number | null;
62
+ width: number | null;
63
+ }[];
64
+ type: string;
65
+ uri: string;
66
+ /** @deprecated Only returned to Extended Quota Mode apps since February 2026 */
67
+ country?: string;
68
+ /** @deprecated Only returned to Extended Quota Mode apps since February 2026 */
69
+ email?: string;
70
+ /** @deprecated Only returned to Extended Quota Mode apps since February 2026 */
71
+ explicit_content?: {
72
+ filter_enabled: boolean;
73
+ filter_locked: boolean;
74
+ };
75
+ /** @deprecated Only returned to Extended Quota Mode apps since February 2026 */
76
+ followers?: {
77
+ href: string | null;
78
+ total: number;
79
+ };
80
+ /** @deprecated Only returned to Extended Quota Mode apps since February 2026 */
81
+ product?: string;
82
+ }
83
+ interface SpotifyTokens {
84
+ access_token: string;
85
+ token_type: string;
86
+ scope: string;
87
+ expires_in: number;
88
+ refresh_token: string;
89
+ }
90
+ export declare function defineOAuthSpotifyEventHandler({ config, onSuccess, onError }: OAuthConfig<OAuthSpotifyConfig, {
91
+ user: SpotifyUser;
92
+ tokens: SpotifyTokens;
93
+ }>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
94
+ export {};
@@ -0,0 +1,110 @@
1
+ import type { OAuthConfig } from '#auth-utils';
2
+ export interface OAuthZendeskConfig {
3
+ /**
4
+ * Zendesk OAuth Client ID
5
+ * @default process.env.NUXT_OAUTH_ZENDESK_CLIENT_ID
6
+ */
7
+ clientId?: string;
8
+ /**
9
+ * Zendesk OAuth Client Secret
10
+ * @default process.env.NUXT_OAUTH_ZENDESK_CLIENT_SECRET
11
+ */
12
+ clientSecret?: string;
13
+ /**
14
+ * Zendesk subdomain, for example `mycompany` for `mycompany.zendesk.com`
15
+ * @default process.env.NUXT_OAUTH_ZENDESK_SUBDOMAIN
16
+ */
17
+ subdomain?: string;
18
+ /**
19
+ * Zendesk OAuth Scope
20
+ * @default ['read']
21
+ * @see https://support.zendesk.com/hc/en-us/articles/4408845965210-Using-OAuth-authentication-with-your-application
22
+ * @example ['read', 'write']
23
+ */
24
+ scope?: string[];
25
+ /**
26
+ * Redirect URL to allow overriding for situations like prod failing to determine public hostname
27
+ * @default process.env.NUXT_OAUTH_ZENDESK_REDIRECT_URL
28
+ */
29
+ redirectURL?: string;
30
+ /**
31
+ * Zendesk Marketplace name header value.
32
+ * Only required for apps published in the Zendesk Marketplace.
33
+ * @default process.env.NUXT_OAUTH_ZENDESK_MARKETPLACE_NAME
34
+ */
35
+ marketplaceName?: string;
36
+ /**
37
+ * Zendesk Marketplace organization ID header value.
38
+ * Only required for apps published in the Zendesk Marketplace.
39
+ * @default process.env.NUXT_OAUTH_ZENDESK_MARKETPLACE_ORG_ID
40
+ */
41
+ marketplaceOrgId?: string;
42
+ /**
43
+ * Zendesk Marketplace bot ID header value.
44
+ * Only required for marketplace bot integrations.
45
+ * @default process.env.NUXT_OAUTH_ZENDESK_MARKETPLACE_BOT_ID
46
+ */
47
+ marketplaceBotId?: string;
48
+ /**
49
+ * Zendesk Marketplace app ID header value.
50
+ * Only required for apps published in the Zendesk Marketplace.
51
+ * @default process.env.NUXT_OAUTH_ZENDESK_MARKETPLACE_APP_ID
52
+ */
53
+ marketplaceAppId?: string;
54
+ }
55
+ export interface ZendeskUser {
56
+ id: number;
57
+ url: string;
58
+ name: string;
59
+ email: string;
60
+ created_at: string;
61
+ updated_at: string;
62
+ time_zone: string | null;
63
+ iana_time_zone: string | null;
64
+ phone: string | null;
65
+ shared_phone_number: boolean | null;
66
+ photo: {
67
+ url: string | null;
68
+ content_url: string | null;
69
+ } | null;
70
+ locale_id: number;
71
+ locale: string;
72
+ organization_id: number | null;
73
+ role: string;
74
+ verified: boolean;
75
+ external_id: string | null;
76
+ tags: string[];
77
+ alias: string | null;
78
+ active: boolean;
79
+ shared: boolean;
80
+ shared_agent: boolean;
81
+ last_login_at: string | null;
82
+ two_factor_auth_enabled: boolean;
83
+ signature: string | null;
84
+ details: string | null;
85
+ notes: string | null;
86
+ role_type: number | null;
87
+ custom_role_id: number | null;
88
+ is_billing_admin: boolean;
89
+ moderator: boolean;
90
+ ticket_restriction: string | null;
91
+ only_private_comments: boolean;
92
+ restricted_agent: boolean;
93
+ suspended: boolean;
94
+ default_group_id: number | null;
95
+ report_csv: boolean;
96
+ user_fields: Record<string, unknown>;
97
+ suspension_details: unknown | null;
98
+ }
99
+ export interface ZendeskTokens {
100
+ access_token: string;
101
+ refresh_token?: string;
102
+ token_type: string;
103
+ scope: string;
104
+ expires_in?: number;
105
+ refresh_token_expires_in?: number;
106
+ }
107
+ export declare function defineOAuthZendeskEventHandler({ config, onSuccess, onError, }: OAuthConfig<OAuthZendeskConfig, {
108
+ user: ZendeskUser;
109
+ tokens: ZendeskTokens;
110
+ }>): import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<any>>;
@@ -0,0 +1,109 @@
1
+ import { eventHandler, getQuery, sendRedirect } from "h3";
2
+ import { withQuery } from "ufo";
3
+ import { defu } from "defu";
4
+ import {
5
+ handleMissingConfiguration,
6
+ handleAccessTokenErrorResponse,
7
+ getOAuthRedirectURL,
8
+ handleInvalidState,
9
+ handleState,
10
+ requestAccessToken
11
+ } from "../utils.js";
12
+ import { useRuntimeConfig } from "#imports";
13
+ function getMarketplaceHeaders(config) {
14
+ const headers = {};
15
+ if (config.marketplaceName) {
16
+ headers["X-Zendesk-Marketplace-Name"] = config.marketplaceName;
17
+ }
18
+ if (config.marketplaceOrgId) {
19
+ headers["X-Zendesk-Marketplace-Organization-Id"] = config.marketplaceOrgId;
20
+ }
21
+ if (config.marketplaceBotId) {
22
+ headers["X-Zendesk-Marketplace-Bot-Id"] = config.marketplaceBotId;
23
+ }
24
+ if (config.marketplaceAppId) {
25
+ headers["X-Zendesk-Marketplace-App-Id"] = config.marketplaceAppId;
26
+ }
27
+ return headers;
28
+ }
29
+ export function defineOAuthZendeskEventHandler({
30
+ config,
31
+ onSuccess,
32
+ onError
33
+ }) {
34
+ return eventHandler(async (event) => {
35
+ const runtimeConfig = useRuntimeConfig(event).oauth?.zendesk;
36
+ config = defu(config, runtimeConfig);
37
+ config.scope = config.scope?.length ? config.scope : ["read"];
38
+ if (!config.scope.includes("read") && !config.scope.includes("users:read")) {
39
+ config.scope.push("users:read");
40
+ }
41
+ if (!config.clientId || !config.clientSecret || !config.subdomain) {
42
+ return handleMissingConfiguration(
43
+ event,
44
+ "zendesk",
45
+ ["clientId", "clientSecret", "subdomain"],
46
+ onError
47
+ );
48
+ }
49
+ const baseURL = `https://${config.subdomain}.zendesk.com`;
50
+ const query = getQuery(event);
51
+ const redirectURL = config.redirectURL || getOAuthRedirectURL(event);
52
+ if (query.error) {
53
+ return handleAccessTokenErrorResponse(
54
+ event,
55
+ "zendesk",
56
+ {
57
+ error: query.error,
58
+ error_description: query.error_description
59
+ },
60
+ onError
61
+ );
62
+ }
63
+ const state = await handleState(event);
64
+ if (!query.code) {
65
+ return sendRedirect(
66
+ event,
67
+ withQuery(`${baseURL}/oauth/authorizations/new`, {
68
+ response_type: "code",
69
+ client_id: config.clientId,
70
+ redirect_uri: redirectURL,
71
+ scope: config.scope.join(" "),
72
+ state
73
+ })
74
+ );
75
+ }
76
+ if (!state || query.state !== state) {
77
+ return handleInvalidState(event, "zendesk", onError);
78
+ }
79
+ const marketplaceHeaders = getMarketplaceHeaders(config);
80
+ const tokens = await requestAccessToken(`${baseURL}/oauth/tokens`, {
81
+ headers: {
82
+ // Zendesk documents JSON bodies for the token endpoint
83
+ "Content-Type": "application/json",
84
+ ...marketplaceHeaders
85
+ },
86
+ body: {
87
+ grant_type: "authorization_code",
88
+ client_id: config.clientId,
89
+ client_secret: config.clientSecret,
90
+ redirect_uri: redirectURL,
91
+ code: query.code,
92
+ scope: config.scope.join(" ")
93
+ }
94
+ });
95
+ if (tokens.error) {
96
+ return handleAccessTokenErrorResponse(event, "zendesk", tokens, onError);
97
+ }
98
+ const data = await $fetch(`${baseURL}/api/v2/users/me.json`, {
99
+ headers: {
100
+ Authorization: `Bearer ${tokens.access_token}`,
101
+ ...marketplaceHeaders
102
+ }
103
+ });
104
+ return onSuccess(event, {
105
+ user: data.user,
106
+ tokens
107
+ });
108
+ });
109
+ }
@@ -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' | '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' | (string & {});
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
4
  export type OnError = (event: H3Event, error: H3Error) => Promise<void> | void;
5
5
  export interface OAuthConfig<TConfig, TResult = {
6
6
  user: any;
@@ -1,7 +1,9 @@
1
- import type { AuthenticationResponseJSON, AuthenticatorTransportFuture, RegistrationResponseJSON } from '@simplewebauthn/types';
2
1
  import type { Ref } from 'vue';
3
2
  import type { H3Event, H3Error, ValidateResult } from 'h3';
4
- import type { GenerateAuthenticationOptionsOpts, GenerateRegistrationOptionsOpts, VerifiedAuthenticationResponse, VerifiedRegistrationResponse } from '@simplewebauthn/server';
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];
5
7
  export interface WebAuthnCredential {
6
8
  id: string;
7
9
  publicKey: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-auth-utils",
3
- "version": "0.5.33",
3
+ "version": "0.5.34",
4
4
  "description": "Add Authentication to Nuxt applications with secured & sealed cookies sessions.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,8 +29,8 @@
29
29
  "@adonisjs/hash": "^9.1.1",
30
30
  "@nuxt/kit": "^4.3.1",
31
31
  "@nuxt/schema": "^4.6.0",
32
- "defu": "^6.1.4",
33
- "h3": "^1.15.4",
32
+ "defu": "^6.1.5",
33
+ "h3": "^1.15.9",
34
34
  "hookable": "^6.0.1",
35
35
  "jose": "^6.1.3",
36
36
  "ofetch": "^1.5.1",
@@ -42,8 +42,8 @@
42
42
  "peerDependencies": {
43
43
  "@atproto/api": "^0.13.15",
44
44
  "@atproto/oauth-client-node": "^0.2.0",
45
- "@simplewebauthn/browser": "^11.0.0",
46
- "@simplewebauthn/server": "^11.0.0"
45
+ "@simplewebauthn/browser": "^11.0.0 || ^13.0.0",
46
+ "@simplewebauthn/server": "^11.0.0 || ^13.3.2"
47
47
  },
48
48
  "peerDependenciesMeta": {
49
49
  "@simplewebauthn/browser": {
@@ -61,12 +61,11 @@
61
61
  },
62
62
  "devDependencies": {
63
63
  "@iconify-json/simple-icons": "^1.2.71",
64
- "@nuxt/devtools": "3.2.1",
64
+ "@nuxt/devtools": "3.4.4",
65
65
  "@nuxt/eslint-config": "^1.15.1",
66
66
  "@nuxt/module-builder": "^1.0.2",
67
67
  "@nuxt/test-utils": "^4.0.0",
68
68
  "@nuxt/ui": "^4.4.0",
69
- "@simplewebauthn/types": "^12.0.0",
70
69
  "@types/node": "latest",
71
70
  "eslint": "^10.0.0",
72
71
  "nuxt": "^4.6.0",