@wix/sdk 1.7.4 → 1.7.6

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.
@@ -1,5 +1,11 @@
1
1
  import { AuthenticationStrategy } from '@wix/sdk-types';
2
- export type WixAppOAuthStrategy = AuthenticationStrategy & {
2
+ export type WixAppOAuthStrategy = AuthenticationStrategy<undefined, (opts: {
3
+ instanceId: string;
4
+ } | {
5
+ refreshToken: string;
6
+ } | {
7
+ fromRequest: Request;
8
+ }) => WixAppOAuthStrategy> & {
3
9
  getInstallUrl(opts: {
4
10
  redirectUrl: string;
5
11
  state?: string;
@@ -20,6 +26,7 @@ export type WixAppOAuthStrategy = AuthenticationStrategy & {
20
26
  * @param opts.appId The Wix App ID
21
27
  * @param opts.appSecret The Wix App Secret
22
28
  * @param opts.refreshToken An optional refresh token previously retrieved from Wix OAuth API
29
+ * @param opts.instanceId An optional instance ID of the Wix App instance the client is making requests on behalf of
23
30
  * @param opts.publicKey An optional public key for validating webhook requests (supports both PEM and base64 encoded keys)
24
31
  * @returns An authentication strategy that can be used with WixClient
25
32
  * @example
@@ -54,5 +61,10 @@ export declare function WixAppOAuthStrategy(opts: {
54
61
  appId: string;
55
62
  appSecret?: string;
56
63
  publicKey?: string;
64
+ } & ({
57
65
  refreshToken?: string;
58
- }): WixAppOAuthStrategy;
66
+ } | {
67
+ instanceId?: string;
68
+ } | {
69
+ accessToken?: string;
70
+ })): WixAppOAuthStrategy;
@@ -1,4 +1,4 @@
1
- import { verify } from 'jsonwebtoken';
1
+ import { jwtVerify, importSPKI } from 'jose';
2
2
  import { parsePublicKeyIfEncoded } from '../helpers.js';
3
3
  /**
4
4
  * Creates an authentication strategy for Wix Apps OAuth installation process.
@@ -7,6 +7,7 @@ import { parsePublicKeyIfEncoded } from '../helpers.js';
7
7
  * @param opts.appId The Wix App ID
8
8
  * @param opts.appSecret The Wix App Secret
9
9
  * @param opts.refreshToken An optional refresh token previously retrieved from Wix OAuth API
10
+ * @param opts.instanceId An optional instance ID of the Wix App instance the client is making requests on behalf of
10
11
  * @param opts.publicKey An optional public key for validating webhook requests (supports both PEM and base64 encoded keys)
11
12
  * @returns An authentication strategy that can be used with WixClient
12
13
  * @example
@@ -39,7 +40,7 @@ import { parsePublicKeyIfEncoded } from '../helpers.js';
39
40
  */
40
41
  // eslint-disable-next-line @typescript-eslint/no-redeclare
41
42
  export function WixAppOAuthStrategy(opts) {
42
- let refreshToken = opts.refreshToken;
43
+ let refreshToken = 'refreshToken' in opts ? opts.refreshToken : undefined;
43
44
  return {
44
45
  getInstallUrl({ redirectUrl, token, state }) {
45
46
  const params = new URLSearchParams();
@@ -53,6 +54,39 @@ export function WixAppOAuthStrategy(opts) {
53
54
  }
54
55
  return `https://www.wix.com/installer/install?${params.toString()}`;
55
56
  },
57
+ withAuth(params) {
58
+ if ('instanceId' in params) {
59
+ return WixAppOAuthStrategy({
60
+ appId: opts.appId,
61
+ appSecret: opts.appSecret,
62
+ publicKey: opts.publicKey,
63
+ instanceId: params.instanceId,
64
+ });
65
+ }
66
+ else if ('refreshToken' in params) {
67
+ return WixAppOAuthStrategy({
68
+ appId: opts.appId,
69
+ appSecret: opts.appSecret,
70
+ publicKey: opts.publicKey,
71
+ refreshToken: params.refreshToken,
72
+ });
73
+ }
74
+ else if ('fromRequest' in params) {
75
+ const authFromRequest = params.fromRequest.headers.get('Authorization');
76
+ if (!authFromRequest) {
77
+ throw new Error('Missing Authorization header in the request');
78
+ }
79
+ return WixAppOAuthStrategy({
80
+ appId: opts.appId,
81
+ appSecret: opts.appSecret,
82
+ publicKey: opts.publicKey,
83
+ accessToken: authFromRequest,
84
+ });
85
+ }
86
+ else {
87
+ throw new Error('Invalid parameters for withAuth');
88
+ }
89
+ },
56
90
  async handleOAuthCallback(url, oauthOpts) {
57
91
  if (!opts.appSecret) {
58
92
  throw new Error('App secret is required for handling OAuth callback. Make sure to pass it to the WixAppOAuthStrategy');
@@ -91,48 +125,82 @@ export function WixAppOAuthStrategy(opts) {
91
125
  };
92
126
  },
93
127
  async getAuthHeaders() {
94
- if (!refreshToken) {
95
- throw new Error('Missing refresh token. Either pass it to the WixAppOAuthStrategy or use the handleOAuthCallback method to retrieve it.');
96
- }
97
128
  if (!opts.appSecret) {
98
- throw new Error('App secret is required for refreshing access tokens. Make sure to pass it to the WixAppOAuthStrategy');
129
+ throw new Error('App secret is required for retrieveing app-level access tokens. Make sure to pass it to the WixAppOAuthStrategy');
99
130
  }
100
- const tokensRes = await fetch('https://www.wixapis.com/oauth/access', {
101
- method: 'POST',
102
- headers: {
103
- 'Content-Type': 'application/json',
104
- },
105
- body: JSON.stringify({
106
- refresh_token: refreshToken,
107
- client_id: opts.appId,
108
- client_secret: opts.appSecret,
109
- grant_type: 'refresh_token',
110
- }),
111
- });
112
- if (tokensRes.status !== 200) {
113
- throw new Error(`Failed to exchange refresh token for access token. Unexpected status code from Wix OAuth API: ${tokensRes.status}`);
131
+ if ('refreshToken' in opts || refreshToken) {
132
+ const tokensRes = await fetch('https://www.wixapis.com/oauth/access', {
133
+ method: 'POST',
134
+ headers: {
135
+ 'Content-Type': 'application/json',
136
+ },
137
+ body: JSON.stringify({
138
+ refresh_token: refreshToken,
139
+ client_id: opts.appId,
140
+ client_secret: opts.appSecret,
141
+ grant_type: 'refresh_token',
142
+ }),
143
+ });
144
+ if (tokensRes.status !== 200) {
145
+ throw new Error(`Failed to exchange refresh token for access token. Unexpected status code from Wix OAuth API: ${tokensRes.status}`);
146
+ }
147
+ const tokens = (await tokensRes.json());
148
+ refreshToken = tokens.refresh_token;
149
+ return {
150
+ headers: {
151
+ Authorization: tokens.access_token,
152
+ },
153
+ };
154
+ }
155
+ else if ('instanceId' in opts) {
156
+ const tokensRes = await fetch('https://www.wixapis.com/oauth2/token', {
157
+ method: 'POST',
158
+ headers: {
159
+ 'Content-Type': 'application/json',
160
+ },
161
+ body: JSON.stringify({
162
+ instance_id: opts.instanceId,
163
+ client_id: opts.appId,
164
+ client_secret: opts.appSecret,
165
+ grant_type: 'client_credentials',
166
+ }),
167
+ });
168
+ if (tokensRes.status !== 200) {
169
+ throw new Error(`Failed to exchange instance ID for access token. Unexpected status code from Wix OAuth API: ${tokensRes.status}`);
170
+ }
171
+ const tokens = (await tokensRes.json());
172
+ return {
173
+ headers: {
174
+ Authorization: tokens.access_token,
175
+ },
176
+ };
177
+ }
178
+ else if ('accessToken' in opts && opts.accessToken) {
179
+ return {
180
+ headers: {
181
+ Authorization: opts.accessToken,
182
+ },
183
+ };
184
+ }
185
+ else {
186
+ throw new Error('Missing refresh token or instance ID. Either one is needed to get app level access tokens. Make sure to pass one of them to the WixAppOAuthStrategy');
114
187
  }
115
- const tokens = (await tokensRes.json());
116
- refreshToken = tokens.refresh_token;
117
- return {
118
- headers: {
119
- Authorization: tokens.access_token,
120
- },
121
- };
122
188
  },
123
- decodeJWT(token, verifyCallerClaims = false) {
189
+ async decodeJWT(token, verifyCallerClaims = false) {
124
190
  if (!opts.publicKey) {
125
191
  throw new Error('Missing public key. Make sure to pass it to the WixAppOAuthStrategy');
126
192
  }
127
- const publicKey = parsePublicKeyIfEncoded(opts.publicKey);
128
- const decoded = verify(token, publicKey, verifyCallerClaims
193
+ const publicKey = await importSPKI(parsePublicKeyIfEncoded(opts.publicKey), 'RS256');
194
+ const decoded = await jwtVerify(token, publicKey, verifyCallerClaims
129
195
  ? {
130
196
  issuer: 'wix.com',
131
197
  audience: opts.appId,
132
198
  }
133
199
  : undefined);
134
200
  return {
135
- decoded,
201
+ decoded: {
202
+ data: decoded.payload.data,
203
+ },
136
204
  valid: true,
137
205
  };
138
206
  },
@@ -118,7 +118,7 @@ export function OAuthStrategy(config) {
118
118
  const getAuthUrl = async (oauthData, opts = {
119
119
  prompt: 'login',
120
120
  }) => {
121
- return getAuthorizationUrlWithOptions(oauthData, opts.responseMode ?? 'fragment', opts.prompt ?? 'login');
121
+ return getAuthorizationUrlWithOptions(oauthData, opts.responseMode ?? 'fragment', opts.prompt ?? 'login', opts.sessionToken);
122
122
  };
123
123
  const parseFromUrl = (url, responseMode = 'fragment') => {
124
124
  const parsedUrl = new URL(url ?? window.location.href);
package/build/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export * from './wixMedia.js';
3
3
  export * from './auth/oauth2/OAuthStrategy.js';
4
4
  export * from './auth/oauth2/types.js';
5
5
  export * from './auth/ApiKeyAuthStrategy.js';
6
+ export * from './auth/WixAppOAuthStrategy.js';
6
7
  export * from '@wix/sdk-types';
7
8
  export { getDefaultDomain } from './rest-modules.js';
8
9
  export { API_URL } from './common.js';
package/build/index.js CHANGED
@@ -3,6 +3,7 @@ export * from './wixMedia.js';
3
3
  export * from './auth/oauth2/OAuthStrategy.js';
4
4
  export * from './auth/oauth2/types.js';
5
5
  export * from './auth/ApiKeyAuthStrategy.js';
6
+ export * from './auth/WixAppOAuthStrategy.js';
6
7
  export * from '@wix/sdk-types';
7
8
  export { getDefaultDomain } from './rest-modules.js';
8
9
  export { API_URL } from './common.js';
@@ -1,4 +1,4 @@
1
- import { AuthenticationStrategy, BoundAuthenticationStrategy, BuildRESTFunction, Host, HostModule, HostModuleAPI, RESTFunctionDescriptor, EventDefinition, SPIDefinition } from '@wix/sdk-types';
1
+ import { AuthenticationStrategy, BoundAuthenticationStrategy, BuildRESTFunction, Host, HostModule, HostModuleAPI, RESTFunctionDescriptor, SPIDefinition, EventDefinition } from '@wix/sdk-types';
2
2
  import { ConditionalExcept, EmptyObject } from 'type-fest';
3
3
  import { AmbassadorFunctionDescriptor, BuildAmbassadorFunction } from './ambassador-modules.js';
4
4
  import { PublicMetadata } from './common.js';
@@ -54,7 +54,9 @@ type TypedQueryInput<Result = {
54
54
  export type WixClient<H extends Host<any> | undefined = undefined, Z extends AuthenticationStrategy<H> = AuthenticationStrategy<H>, T extends Descriptors = Descriptors> = {
55
55
  setHeaders(headers: Headers): void;
56
56
  auth: Omit<Z, 'getAuthHeaders'> & BoundAuthenticationStrategy;
57
+ withAuth: Z['withAuth'] extends undefined ? never : (...args: Parameters<NonNullable<Z['withAuth']>>) => WixClient<H, Z, T>;
57
58
  fetch(relativeUrl: string, options: RequestInit): Promise<Response>;
59
+ fetchWithAuth: typeof fetch;
58
60
  use<R extends Descriptors = EmptyObject>(modules: H extends Host<any> ? AssertHostMatches<R, H> : R): BuildDescriptors<R, H>;
59
61
  graphql<Result, Variables>(query: string | ((string | String) & TypedQueryInput<Result, Variables>), variables?: Variables): Promise<{
60
62
  data: Result;
@@ -63,7 +65,7 @@ export type WixClient<H extends Host<any> | undefined = undefined, Z extends Aut
63
65
  webhooks: {
64
66
  process<ExpectedEvents extends EventDefinition<any>[] = []>(jwt: string, opts?: {
65
67
  expectedEvents: ExpectedEvents;
66
- }): ProcessedEvent<ExpectedEvents>;
68
+ }): Promise<ProcessedEvent<ExpectedEvents>>;
67
69
  processRequest<ExpectedEvents extends EventDefinition<any>[] = []>(request: Request, opts?: {
68
70
  expectedEvents: ExpectedEvents;
69
71
  }): Promise<ProcessedEvent<ExpectedEvents>>;
@@ -71,14 +73,14 @@ export type WixClient<H extends Host<any> | undefined = undefined, Z extends Aut
71
73
  AppInstalled: EventDefinition<{
72
74
  appId: string;
73
75
  originInstanceId: string;
74
- }>;
76
+ }, 'AppInstalled'>;
75
77
  AppRemoved: EventDefinition<{
76
78
  appId: string;
77
- }>;
79
+ }, 'AppRemoved'>;
78
80
  };
79
81
  };
80
82
  spi: <S extends SPIDefinition<any, any>>() => {
81
- process(jwt: string): S['__input'];
83
+ process(jwt: string): Promise<S['__input']>;
82
84
  processRequest(request: Request): Promise<S['__input']>;
83
85
  result(result: S['__result']): S['__result'];
84
86
  };
@@ -95,7 +97,7 @@ export type ProcessedEvent<T extends EventDefinition<any>[] = []> = {
95
97
  eventType: string;
96
98
  payload: unknown;
97
99
  } : ResolvePossibleEvents<T>);
98
- export declare function createClient<H extends Host<any> | undefined = undefined, Z extends AuthenticationStrategy<H> = AuthenticationStrategy<H>, T extends Descriptors = EmptyObject>(config: {
100
+ export declare function createClient<H extends Host<any> | undefined = undefined, Z extends AuthenticationStrategy<H, any> = AuthenticationStrategy<H>, T extends Descriptors = EmptyObject>(config: {
99
101
  modules?: H extends Host<any> ? AssertHostMatches<T, H> : T;
100
102
  auth?: Z;
101
103
  headers?: Headers;
@@ -1,3 +1,4 @@
1
+ import { EventDefinition, } from '@wix/sdk-types';
1
2
  import { toHTTPModule, isAmbassadorModule, ambassadorModuleOptions, } from './ambassador-modules.js';
2
3
  import { API_URL, PUBLIC_METADATA_KEY } from './common.js';
3
4
  import { getDefaultContentHeader, isObject } from './helpers.js';
@@ -61,6 +62,12 @@ export function createClient(config) {
61
62
  return {
62
63
  ...wrappedModules,
63
64
  auth: authStrategy,
65
+ withAuth: (authStrategy.withAuth
66
+ ? (...args) => createClient({
67
+ ...config,
68
+ auth: authStrategy.withAuth(...args),
69
+ })
70
+ : undefined),
64
71
  setHeaders,
65
72
  use,
66
73
  fetch: (relativeUrl, options) => {
@@ -69,6 +76,23 @@ export function createClient(config) {
69
76
  finalUrl.protocol = 'https';
70
77
  return boundFetch(finalUrl.toString(), options);
71
78
  },
79
+ fetchWithAuth: async (urlOrRequest, requestInit) => {
80
+ if (typeof urlOrRequest === 'string' || urlOrRequest instanceof URL) {
81
+ return fetch(urlOrRequest, {
82
+ ...requestInit,
83
+ headers: {
84
+ ...requestInit?.headers,
85
+ ...(await boundGetAuthHeaders()).headers,
86
+ },
87
+ });
88
+ }
89
+ else {
90
+ for (const [k, v] of Object.entries((await boundGetAuthHeaders()).headers)) {
91
+ urlOrRequest.headers.set(k, v);
92
+ }
93
+ return fetch(urlOrRequest, requestInit);
94
+ }
95
+ },
72
96
  async graphql(query, variables, opts = {
73
97
  apiVersion: 'alpha',
74
98
  }) {
@@ -86,13 +110,13 @@ export function createClient(config) {
86
110
  return { data: data ?? {}, errors };
87
111
  },
88
112
  webhooks: {
89
- process: (jwt, opts = {
113
+ process: async (jwt, opts = {
90
114
  expectedEvents: [],
91
115
  }) => {
92
116
  if (!authStrategy.decodeJWT) {
93
117
  throw new Error('decodeJWT is not supported by the authentication strategy');
94
118
  }
95
- const { decoded, valid } = authStrategy.decodeJWT(jwt);
119
+ const { decoded, valid } = await authStrategy.decodeJWT(jwt);
96
120
  if (!valid) {
97
121
  throw new Error('JWT is not valid');
98
122
  }
@@ -117,23 +141,17 @@ export function createClient(config) {
117
141
  return this.process(body, opts);
118
142
  },
119
143
  apps: {
120
- AppInstalled: {
121
- type: 'AppInstalled',
122
- __payload: void 0,
123
- },
124
- AppRemoved: {
125
- type: 'AppRemoved',
126
- __payload: void 0,
127
- },
144
+ AppInstalled: EventDefinition('AppInstalled')(),
145
+ AppRemoved: EventDefinition('AppRemoved')(),
128
146
  },
129
147
  },
130
148
  spi() {
131
149
  return {
132
- process(jwt) {
150
+ async process(jwt) {
133
151
  if (!authStrategy.decodeJWT) {
134
152
  throw new Error('decodeJWT is not supported by the authentication strategy');
135
153
  }
136
- const { decoded, valid } = authStrategy.decodeJWT(jwt, true);
154
+ const { decoded, valid } = await authStrategy.decodeJWT(jwt, true);
137
155
  if (!valid) {
138
156
  throw new Error('JWT is not valid');
139
157
  }
@@ -1,5 +1,11 @@
1
1
  import { AuthenticationStrategy } from '@wix/sdk-types';
2
- export type WixAppOAuthStrategy = AuthenticationStrategy & {
2
+ export type WixAppOAuthStrategy = AuthenticationStrategy<undefined, (opts: {
3
+ instanceId: string;
4
+ } | {
5
+ refreshToken: string;
6
+ } | {
7
+ fromRequest: Request;
8
+ }) => WixAppOAuthStrategy> & {
3
9
  getInstallUrl(opts: {
4
10
  redirectUrl: string;
5
11
  state?: string;
@@ -20,6 +26,7 @@ export type WixAppOAuthStrategy = AuthenticationStrategy & {
20
26
  * @param opts.appId The Wix App ID
21
27
  * @param opts.appSecret The Wix App Secret
22
28
  * @param opts.refreshToken An optional refresh token previously retrieved from Wix OAuth API
29
+ * @param opts.instanceId An optional instance ID of the Wix App instance the client is making requests on behalf of
23
30
  * @param opts.publicKey An optional public key for validating webhook requests (supports both PEM and base64 encoded keys)
24
31
  * @returns An authentication strategy that can be used with WixClient
25
32
  * @example
@@ -54,5 +61,10 @@ export declare function WixAppOAuthStrategy(opts: {
54
61
  appId: string;
55
62
  appSecret?: string;
56
63
  publicKey?: string;
64
+ } & ({
57
65
  refreshToken?: string;
58
- }): WixAppOAuthStrategy;
66
+ } | {
67
+ instanceId?: string;
68
+ } | {
69
+ accessToken?: string;
70
+ })): WixAppOAuthStrategy;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WixAppOAuthStrategy = void 0;
4
- const jsonwebtoken_1 = require("jsonwebtoken");
4
+ const jose_1 = require("jose");
5
5
  const helpers_js_1 = require("../helpers.js");
6
6
  /**
7
7
  * Creates an authentication strategy for Wix Apps OAuth installation process.
@@ -10,6 +10,7 @@ const helpers_js_1 = require("../helpers.js");
10
10
  * @param opts.appId The Wix App ID
11
11
  * @param opts.appSecret The Wix App Secret
12
12
  * @param opts.refreshToken An optional refresh token previously retrieved from Wix OAuth API
13
+ * @param opts.instanceId An optional instance ID of the Wix App instance the client is making requests on behalf of
13
14
  * @param opts.publicKey An optional public key for validating webhook requests (supports both PEM and base64 encoded keys)
14
15
  * @returns An authentication strategy that can be used with WixClient
15
16
  * @example
@@ -42,7 +43,7 @@ const helpers_js_1 = require("../helpers.js");
42
43
  */
43
44
  // eslint-disable-next-line @typescript-eslint/no-redeclare
44
45
  function WixAppOAuthStrategy(opts) {
45
- let refreshToken = opts.refreshToken;
46
+ let refreshToken = 'refreshToken' in opts ? opts.refreshToken : undefined;
46
47
  return {
47
48
  getInstallUrl({ redirectUrl, token, state }) {
48
49
  const params = new URLSearchParams();
@@ -56,6 +57,39 @@ function WixAppOAuthStrategy(opts) {
56
57
  }
57
58
  return `https://www.wix.com/installer/install?${params.toString()}`;
58
59
  },
60
+ withAuth(params) {
61
+ if ('instanceId' in params) {
62
+ return WixAppOAuthStrategy({
63
+ appId: opts.appId,
64
+ appSecret: opts.appSecret,
65
+ publicKey: opts.publicKey,
66
+ instanceId: params.instanceId,
67
+ });
68
+ }
69
+ else if ('refreshToken' in params) {
70
+ return WixAppOAuthStrategy({
71
+ appId: opts.appId,
72
+ appSecret: opts.appSecret,
73
+ publicKey: opts.publicKey,
74
+ refreshToken: params.refreshToken,
75
+ });
76
+ }
77
+ else if ('fromRequest' in params) {
78
+ const authFromRequest = params.fromRequest.headers.get('Authorization');
79
+ if (!authFromRequest) {
80
+ throw new Error('Missing Authorization header in the request');
81
+ }
82
+ return WixAppOAuthStrategy({
83
+ appId: opts.appId,
84
+ appSecret: opts.appSecret,
85
+ publicKey: opts.publicKey,
86
+ accessToken: authFromRequest,
87
+ });
88
+ }
89
+ else {
90
+ throw new Error('Invalid parameters for withAuth');
91
+ }
92
+ },
59
93
  async handleOAuthCallback(url, oauthOpts) {
60
94
  if (!opts.appSecret) {
61
95
  throw new Error('App secret is required for handling OAuth callback. Make sure to pass it to the WixAppOAuthStrategy');
@@ -94,48 +128,82 @@ function WixAppOAuthStrategy(opts) {
94
128
  };
95
129
  },
96
130
  async getAuthHeaders() {
97
- if (!refreshToken) {
98
- throw new Error('Missing refresh token. Either pass it to the WixAppOAuthStrategy or use the handleOAuthCallback method to retrieve it.');
99
- }
100
131
  if (!opts.appSecret) {
101
- throw new Error('App secret is required for refreshing access tokens. Make sure to pass it to the WixAppOAuthStrategy');
132
+ throw new Error('App secret is required for retrieveing app-level access tokens. Make sure to pass it to the WixAppOAuthStrategy');
102
133
  }
103
- const tokensRes = await fetch('https://www.wixapis.com/oauth/access', {
104
- method: 'POST',
105
- headers: {
106
- 'Content-Type': 'application/json',
107
- },
108
- body: JSON.stringify({
109
- refresh_token: refreshToken,
110
- client_id: opts.appId,
111
- client_secret: opts.appSecret,
112
- grant_type: 'refresh_token',
113
- }),
114
- });
115
- if (tokensRes.status !== 200) {
116
- throw new Error(`Failed to exchange refresh token for access token. Unexpected status code from Wix OAuth API: ${tokensRes.status}`);
134
+ if ('refreshToken' in opts || refreshToken) {
135
+ const tokensRes = await fetch('https://www.wixapis.com/oauth/access', {
136
+ method: 'POST',
137
+ headers: {
138
+ 'Content-Type': 'application/json',
139
+ },
140
+ body: JSON.stringify({
141
+ refresh_token: refreshToken,
142
+ client_id: opts.appId,
143
+ client_secret: opts.appSecret,
144
+ grant_type: 'refresh_token',
145
+ }),
146
+ });
147
+ if (tokensRes.status !== 200) {
148
+ throw new Error(`Failed to exchange refresh token for access token. Unexpected status code from Wix OAuth API: ${tokensRes.status}`);
149
+ }
150
+ const tokens = (await tokensRes.json());
151
+ refreshToken = tokens.refresh_token;
152
+ return {
153
+ headers: {
154
+ Authorization: tokens.access_token,
155
+ },
156
+ };
157
+ }
158
+ else if ('instanceId' in opts) {
159
+ const tokensRes = await fetch('https://www.wixapis.com/oauth2/token', {
160
+ method: 'POST',
161
+ headers: {
162
+ 'Content-Type': 'application/json',
163
+ },
164
+ body: JSON.stringify({
165
+ instance_id: opts.instanceId,
166
+ client_id: opts.appId,
167
+ client_secret: opts.appSecret,
168
+ grant_type: 'client_credentials',
169
+ }),
170
+ });
171
+ if (tokensRes.status !== 200) {
172
+ throw new Error(`Failed to exchange instance ID for access token. Unexpected status code from Wix OAuth API: ${tokensRes.status}`);
173
+ }
174
+ const tokens = (await tokensRes.json());
175
+ return {
176
+ headers: {
177
+ Authorization: tokens.access_token,
178
+ },
179
+ };
180
+ }
181
+ else if ('accessToken' in opts && opts.accessToken) {
182
+ return {
183
+ headers: {
184
+ Authorization: opts.accessToken,
185
+ },
186
+ };
187
+ }
188
+ else {
189
+ throw new Error('Missing refresh token or instance ID. Either one is needed to get app level access tokens. Make sure to pass one of them to the WixAppOAuthStrategy');
117
190
  }
118
- const tokens = (await tokensRes.json());
119
- refreshToken = tokens.refresh_token;
120
- return {
121
- headers: {
122
- Authorization: tokens.access_token,
123
- },
124
- };
125
191
  },
126
- decodeJWT(token, verifyCallerClaims = false) {
192
+ async decodeJWT(token, verifyCallerClaims = false) {
127
193
  if (!opts.publicKey) {
128
194
  throw new Error('Missing public key. Make sure to pass it to the WixAppOAuthStrategy');
129
195
  }
130
- const publicKey = (0, helpers_js_1.parsePublicKeyIfEncoded)(opts.publicKey);
131
- const decoded = (0, jsonwebtoken_1.verify)(token, publicKey, verifyCallerClaims
196
+ const publicKey = await (0, jose_1.importSPKI)((0, helpers_js_1.parsePublicKeyIfEncoded)(opts.publicKey), 'RS256');
197
+ const decoded = await (0, jose_1.jwtVerify)(token, publicKey, verifyCallerClaims
132
198
  ? {
133
199
  issuer: 'wix.com',
134
200
  audience: opts.appId,
135
201
  }
136
202
  : undefined);
137
203
  return {
138
- decoded,
204
+ decoded: {
205
+ data: decoded.payload.data,
206
+ },
139
207
  valid: true,
140
208
  };
141
209
  },
@@ -121,7 +121,7 @@ function OAuthStrategy(config) {
121
121
  const getAuthUrl = async (oauthData, opts = {
122
122
  prompt: 'login',
123
123
  }) => {
124
- return getAuthorizationUrlWithOptions(oauthData, opts.responseMode ?? 'fragment', opts.prompt ?? 'login');
124
+ return getAuthorizationUrlWithOptions(oauthData, opts.responseMode ?? 'fragment', opts.prompt ?? 'login', opts.sessionToken);
125
125
  };
126
126
  const parseFromUrl = (url, responseMode = 'fragment') => {
127
127
  const parsedUrl = new URL(url ?? window.location.href);
@@ -3,6 +3,7 @@ export * from './wixMedia.js';
3
3
  export * from './auth/oauth2/OAuthStrategy.js';
4
4
  export * from './auth/oauth2/types.js';
5
5
  export * from './auth/ApiKeyAuthStrategy.js';
6
+ export * from './auth/WixAppOAuthStrategy.js';
6
7
  export * from '@wix/sdk-types';
7
8
  export { getDefaultDomain } from './rest-modules.js';
8
9
  export { API_URL } from './common.js';
@@ -20,6 +20,7 @@ __exportStar(require("./wixMedia.js"), exports);
20
20
  __exportStar(require("./auth/oauth2/OAuthStrategy.js"), exports);
21
21
  __exportStar(require("./auth/oauth2/types.js"), exports);
22
22
  __exportStar(require("./auth/ApiKeyAuthStrategy.js"), exports);
23
+ __exportStar(require("./auth/WixAppOAuthStrategy.js"), exports);
23
24
  __exportStar(require("@wix/sdk-types"), exports);
24
25
  var rest_modules_js_1 = require("./rest-modules.js");
25
26
  Object.defineProperty(exports, "getDefaultDomain", { enumerable: true, get: function () { return rest_modules_js_1.getDefaultDomain; } });
@@ -1,4 +1,4 @@
1
- import { AuthenticationStrategy, BoundAuthenticationStrategy, BuildRESTFunction, Host, HostModule, HostModuleAPI, RESTFunctionDescriptor, EventDefinition, SPIDefinition } from '@wix/sdk-types';
1
+ import { AuthenticationStrategy, BoundAuthenticationStrategy, BuildRESTFunction, Host, HostModule, HostModuleAPI, RESTFunctionDescriptor, SPIDefinition, EventDefinition } from '@wix/sdk-types';
2
2
  import { ConditionalExcept, EmptyObject } from 'type-fest';
3
3
  import { AmbassadorFunctionDescriptor, BuildAmbassadorFunction } from './ambassador-modules.js';
4
4
  import { PublicMetadata } from './common.js';
@@ -54,7 +54,9 @@ type TypedQueryInput<Result = {
54
54
  export type WixClient<H extends Host<any> | undefined = undefined, Z extends AuthenticationStrategy<H> = AuthenticationStrategy<H>, T extends Descriptors = Descriptors> = {
55
55
  setHeaders(headers: Headers): void;
56
56
  auth: Omit<Z, 'getAuthHeaders'> & BoundAuthenticationStrategy;
57
+ withAuth: Z['withAuth'] extends undefined ? never : (...args: Parameters<NonNullable<Z['withAuth']>>) => WixClient<H, Z, T>;
57
58
  fetch(relativeUrl: string, options: RequestInit): Promise<Response>;
59
+ fetchWithAuth: typeof fetch;
58
60
  use<R extends Descriptors = EmptyObject>(modules: H extends Host<any> ? AssertHostMatches<R, H> : R): BuildDescriptors<R, H>;
59
61
  graphql<Result, Variables>(query: string | ((string | String) & TypedQueryInput<Result, Variables>), variables?: Variables): Promise<{
60
62
  data: Result;
@@ -63,7 +65,7 @@ export type WixClient<H extends Host<any> | undefined = undefined, Z extends Aut
63
65
  webhooks: {
64
66
  process<ExpectedEvents extends EventDefinition<any>[] = []>(jwt: string, opts?: {
65
67
  expectedEvents: ExpectedEvents;
66
- }): ProcessedEvent<ExpectedEvents>;
68
+ }): Promise<ProcessedEvent<ExpectedEvents>>;
67
69
  processRequest<ExpectedEvents extends EventDefinition<any>[] = []>(request: Request, opts?: {
68
70
  expectedEvents: ExpectedEvents;
69
71
  }): Promise<ProcessedEvent<ExpectedEvents>>;
@@ -71,14 +73,14 @@ export type WixClient<H extends Host<any> | undefined = undefined, Z extends Aut
71
73
  AppInstalled: EventDefinition<{
72
74
  appId: string;
73
75
  originInstanceId: string;
74
- }>;
76
+ }, 'AppInstalled'>;
75
77
  AppRemoved: EventDefinition<{
76
78
  appId: string;
77
- }>;
79
+ }, 'AppRemoved'>;
78
80
  };
79
81
  };
80
82
  spi: <S extends SPIDefinition<any, any>>() => {
81
- process(jwt: string): S['__input'];
83
+ process(jwt: string): Promise<S['__input']>;
82
84
  processRequest(request: Request): Promise<S['__input']>;
83
85
  result(result: S['__result']): S['__result'];
84
86
  };
@@ -95,7 +97,7 @@ export type ProcessedEvent<T extends EventDefinition<any>[] = []> = {
95
97
  eventType: string;
96
98
  payload: unknown;
97
99
  } : ResolvePossibleEvents<T>);
98
- export declare function createClient<H extends Host<any> | undefined = undefined, Z extends AuthenticationStrategy<H> = AuthenticationStrategy<H>, T extends Descriptors = EmptyObject>(config: {
100
+ export declare function createClient<H extends Host<any> | undefined = undefined, Z extends AuthenticationStrategy<H, any> = AuthenticationStrategy<H>, T extends Descriptors = EmptyObject>(config: {
99
101
  modules?: H extends Host<any> ? AssertHostMatches<T, H> : T;
100
102
  auth?: Z;
101
103
  headers?: Headers;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createClient = void 0;
4
+ const sdk_types_1 = require("@wix/sdk-types");
4
5
  const ambassador_modules_js_1 = require("./ambassador-modules.js");
5
6
  const common_js_1 = require("./common.js");
6
7
  const helpers_js_1 = require("./helpers.js");
@@ -64,6 +65,12 @@ function createClient(config) {
64
65
  return {
65
66
  ...wrappedModules,
66
67
  auth: authStrategy,
68
+ withAuth: (authStrategy.withAuth
69
+ ? (...args) => createClient({
70
+ ...config,
71
+ auth: authStrategy.withAuth(...args),
72
+ })
73
+ : undefined),
67
74
  setHeaders,
68
75
  use,
69
76
  fetch: (relativeUrl, options) => {
@@ -72,6 +79,23 @@ function createClient(config) {
72
79
  finalUrl.protocol = 'https';
73
80
  return boundFetch(finalUrl.toString(), options);
74
81
  },
82
+ fetchWithAuth: async (urlOrRequest, requestInit) => {
83
+ if (typeof urlOrRequest === 'string' || urlOrRequest instanceof URL) {
84
+ return fetch(urlOrRequest, {
85
+ ...requestInit,
86
+ headers: {
87
+ ...requestInit?.headers,
88
+ ...(await boundGetAuthHeaders()).headers,
89
+ },
90
+ });
91
+ }
92
+ else {
93
+ for (const [k, v] of Object.entries((await boundGetAuthHeaders()).headers)) {
94
+ urlOrRequest.headers.set(k, v);
95
+ }
96
+ return fetch(urlOrRequest, requestInit);
97
+ }
98
+ },
75
99
  async graphql(query, variables, opts = {
76
100
  apiVersion: 'alpha',
77
101
  }) {
@@ -89,13 +113,13 @@ function createClient(config) {
89
113
  return { data: data ?? {}, errors };
90
114
  },
91
115
  webhooks: {
92
- process: (jwt, opts = {
116
+ process: async (jwt, opts = {
93
117
  expectedEvents: [],
94
118
  }) => {
95
119
  if (!authStrategy.decodeJWT) {
96
120
  throw new Error('decodeJWT is not supported by the authentication strategy');
97
121
  }
98
- const { decoded, valid } = authStrategy.decodeJWT(jwt);
122
+ const { decoded, valid } = await authStrategy.decodeJWT(jwt);
99
123
  if (!valid) {
100
124
  throw new Error('JWT is not valid');
101
125
  }
@@ -120,23 +144,17 @@ function createClient(config) {
120
144
  return this.process(body, opts);
121
145
  },
122
146
  apps: {
123
- AppInstalled: {
124
- type: 'AppInstalled',
125
- __payload: void 0,
126
- },
127
- AppRemoved: {
128
- type: 'AppRemoved',
129
- __payload: void 0,
130
- },
147
+ AppInstalled: (0, sdk_types_1.EventDefinition)('AppInstalled')(),
148
+ AppRemoved: (0, sdk_types_1.EventDefinition)('AppRemoved')(),
131
149
  },
132
150
  },
133
151
  spi() {
134
152
  return {
135
- process(jwt) {
153
+ async process(jwt) {
136
154
  if (!authStrategy.decodeJWT) {
137
155
  throw new Error('decodeJWT is not supported by the authentication strategy');
138
156
  }
139
- const { decoded, valid } = authStrategy.decodeJWT(jwt, true);
157
+ const { decoded, valid } = await authStrategy.decodeJWT(jwt, true);
140
158
  if (!valid) {
141
159
  throw new Error('JWT is not valid');
142
160
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/sdk",
3
- "version": "1.7.4",
3
+ "version": "1.7.6",
4
4
  "license": "UNLICENSED",
5
5
  "author": {
6
6
  "name": "Ronny Ringel",
@@ -59,12 +59,12 @@
59
59
  },
60
60
  "dependencies": {
61
61
  "@babel/runtime": "^7.23.2",
62
- "@wix/identity": "^1.0.72",
63
- "@wix/image-kit": "^1.50.0",
62
+ "@wix/identity": "^1.0.73",
63
+ "@wix/image-kit": "^1.56.0",
64
64
  "@wix/redirects": "^1.0.32",
65
- "@wix/sdk-types": "^1.5.6",
65
+ "@wix/sdk-types": "^1.5.9",
66
66
  "crypto-js": "^4.2.0",
67
- "jsonwebtoken": "^9.0.2",
67
+ "jose": "^5.2.1",
68
68
  "pkce-challenge": "^3.1.0",
69
69
  "querystring": "^0.2.1",
70
70
  "type-fest": "^4.9.0"
@@ -75,14 +75,13 @@
75
75
  "devDependencies": {
76
76
  "@types/crypto-js": "^4.2.1",
77
77
  "@types/is-ci": "^3.0.4",
78
- "@types/jsonwebtoken": "^9.0.5",
79
78
  "@types/node": "^20.10.6",
80
79
  "@vitest/ui": "^1.1.3",
81
- "@wix/ecom": "^1.0.474",
80
+ "@wix/ecom": "^1.0.477",
82
81
  "@wix/events": "^1.0.145",
83
82
  "@wix/metro": "^1.0.73",
84
- "@wix/metro-runtime": "^1.1618.0",
85
- "@wix/sdk-runtime": "0.2.7",
83
+ "@wix/metro-runtime": "^1.1635.0",
84
+ "@wix/sdk-runtime": "0.2.8",
86
85
  "eslint": "^8.56.0",
87
86
  "eslint-config-sdk": "0.0.0",
88
87
  "graphql": "^16.8.0",
@@ -116,5 +115,5 @@
116
115
  "wallaby": {
117
116
  "autoDetect": true
118
117
  },
119
- "falconPackageHash": "93a9673030401f9f114208015d7df832e9f3e9b1189763fcd4380c61"
118
+ "falconPackageHash": "676b313e3902721adc8337cd1542cd05dbe775e43ddee5030eef4706"
120
119
  }