@wix/sdk 1.5.9 → 1.6.1
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/auth/api-key/package.json +3 -0
- package/auth/oauth2/package.json +3 -0
- package/auth/wix-app-oauth/package.json +3 -0
- package/build/ambassador-modules.d.ts +31 -0
- package/build/ambassador-modules.js +89 -0
- package/build/auth/ApiKeyAuthStrategy.d.ts +16 -0
- package/build/auth/ApiKeyAuthStrategy.js +22 -0
- package/build/auth/WixAppOAuthStrategy.d.ts +54 -0
- package/build/auth/WixAppOAuthStrategy.js +106 -0
- package/build/auth/oauth2/OAuthStrategy.d.ts +12 -0
- package/build/auth/oauth2/OAuthStrategy.js +357 -0
- package/build/auth/oauth2/constants.d.ts +5 -0
- package/build/auth/oauth2/constants.js +5 -0
- package/build/auth/oauth2/pkce-challenge.d.ts +5 -0
- package/build/auth/oauth2/pkce-challenge.js +33 -0
- package/build/auth/oauth2/types.d.ts +121 -0
- package/build/auth/oauth2/types.js +16 -0
- package/build/bi/biHeaderGenerator.d.ts +12 -0
- package/build/bi/biHeaderGenerator.js +17 -0
- package/build/common.d.ts +7 -0
- package/build/common.js +4 -0
- package/build/fetch-error.d.ts +9 -0
- package/build/fetch-error.js +31 -0
- package/build/helpers.d.ts +4 -0
- package/build/helpers.js +11 -0
- package/build/host-modules.d.ts +3 -0
- package/build/host-modules.js +5 -0
- package/build/iframeUtils.d.ts +4 -0
- package/build/iframeUtils.js +43 -0
- package/build/index.d.ts +8 -388
- package/build/index.js +9 -1115
- package/build/rest-modules.d.ts +7 -0
- package/build/rest-modules.js +82 -0
- package/build/tokenHelpers.d.ts +4 -0
- package/build/tokenHelpers.js +11 -0
- package/build/wixClient.d.ts +70 -0
- package/build/wixClient.js +86 -0
- package/build/wixMedia.d.ts +46 -0
- package/build/wixMedia.js +156 -0
- package/cjs/build/ambassador-modules.d.ts +31 -0
- package/cjs/build/ambassador-modules.js +95 -0
- package/cjs/build/auth/ApiKeyAuthStrategy.d.ts +16 -0
- package/cjs/build/auth/ApiKeyAuthStrategy.js +26 -0
- package/cjs/build/auth/WixAppOAuthStrategy.d.ts +54 -0
- package/cjs/build/auth/WixAppOAuthStrategy.js +110 -0
- package/cjs/build/auth/oauth2/OAuthStrategy.d.ts +12 -0
- package/cjs/build/auth/oauth2/OAuthStrategy.js +361 -0
- package/cjs/build/auth/oauth2/constants.d.ts +5 -0
- package/cjs/build/auth/oauth2/constants.js +8 -0
- package/cjs/build/auth/oauth2/pkce-challenge.d.ts +5 -0
- package/cjs/build/auth/oauth2/pkce-challenge.js +41 -0
- package/cjs/build/auth/oauth2/types.d.ts +121 -0
- package/cjs/build/auth/oauth2/types.js +19 -0
- package/cjs/build/bi/biHeaderGenerator.d.ts +12 -0
- package/cjs/build/bi/biHeaderGenerator.js +21 -0
- package/cjs/build/common.d.ts +7 -0
- package/cjs/build/common.js +7 -0
- package/cjs/build/fetch-error.d.ts +9 -0
- package/cjs/build/fetch-error.js +35 -0
- package/cjs/build/helpers.d.ts +4 -0
- package/cjs/build/helpers.js +16 -0
- package/cjs/build/host-modules.d.ts +3 -0
- package/cjs/build/host-modules.js +10 -0
- package/cjs/build/iframeUtils.d.ts +4 -0
- package/cjs/build/iframeUtils.js +50 -0
- package/cjs/build/index.d.ts +9 -0
- package/cjs/build/index.js +28 -0
- package/cjs/build/rest-modules.d.ts +7 -0
- package/cjs/build/rest-modules.js +87 -0
- package/cjs/build/tokenHelpers.d.ts +4 -0
- package/cjs/build/tokenHelpers.js +17 -0
- package/cjs/build/wixClient.d.ts +70 -0
- package/cjs/build/wixClient.js +90 -0
- package/cjs/build/wixMedia.d.ts +46 -0
- package/cjs/build/wixMedia.js +160 -0
- package/cjs/package.json +3 -0
- package/client/package.json +3 -0
- package/package.json +45 -22
- package/build/browser/index.mjs +0 -1075
- package/build/index.d.mts +0 -389
- package/build/index.mjs +0 -1066
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
import { createClient } from '../../wixClient.js';
|
|
2
|
+
import { redirects } from '@wix/redirects';
|
|
3
|
+
import { createAccessToken, isTokenExpired } from '../../tokenHelpers.js';
|
|
4
|
+
import { authentication, recovery, verification } from '@wix/identity';
|
|
5
|
+
import { API_URL } from '../../common.js';
|
|
6
|
+
import { LoginState, TokenRole, } from './types.js';
|
|
7
|
+
import { addPostMessageListener, loadFrame } from '../../iframeUtils.js';
|
|
8
|
+
import { EMAIL_EXISTS, INVALID_CAPTCHA, INVALID_PASSWORD, MISSING_CAPTCHA, RESET_PASSWORD, } from './constants.js';
|
|
9
|
+
import { biHeaderGenerator } from '../../bi/biHeaderGenerator.js';
|
|
10
|
+
import { pkceChallenge } from './pkce-challenge.js';
|
|
11
|
+
const moduleWithTokens = { redirects, authentication, recovery, verification };
|
|
12
|
+
export function OAuthStrategy(config) {
|
|
13
|
+
const _tokens = config.tokens || {
|
|
14
|
+
accessToken: { value: '', expiresAt: 0 },
|
|
15
|
+
refreshToken: { value: '', role: TokenRole.NONE },
|
|
16
|
+
};
|
|
17
|
+
const setTokens = (tokens) => {
|
|
18
|
+
_tokens.accessToken = tokens.accessToken;
|
|
19
|
+
_tokens.refreshToken = tokens.refreshToken;
|
|
20
|
+
};
|
|
21
|
+
let _state = {
|
|
22
|
+
loginState: LoginState.INITIAL,
|
|
23
|
+
};
|
|
24
|
+
const getAuthHeaders = async () => {
|
|
25
|
+
if (!_tokens.accessToken?.value || isTokenExpired(_tokens.accessToken)) {
|
|
26
|
+
const tokens = await generateVisitorTokens({
|
|
27
|
+
refreshToken: _tokens.refreshToken,
|
|
28
|
+
});
|
|
29
|
+
setTokens(tokens);
|
|
30
|
+
}
|
|
31
|
+
return Promise.resolve({
|
|
32
|
+
headers: { Authorization: _tokens.accessToken.value },
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
const wixClientWithTokens = createClient({
|
|
36
|
+
modules: moduleWithTokens,
|
|
37
|
+
auth: { getAuthHeaders },
|
|
38
|
+
});
|
|
39
|
+
const generateVisitorTokens = async (tokens) => {
|
|
40
|
+
if (tokens?.accessToken?.value &&
|
|
41
|
+
tokens?.refreshToken?.value &&
|
|
42
|
+
!isTokenExpired(tokens.accessToken)) {
|
|
43
|
+
return tokens;
|
|
44
|
+
}
|
|
45
|
+
if (tokens?.refreshToken?.value) {
|
|
46
|
+
try {
|
|
47
|
+
const newTokens = await renewToken(tokens.refreshToken);
|
|
48
|
+
return newTokens;
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
// just continue and create a visitor one
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const tokensResponse = await fetchTokens({
|
|
55
|
+
clientId: config.clientId,
|
|
56
|
+
grantType: 'anonymous',
|
|
57
|
+
});
|
|
58
|
+
return {
|
|
59
|
+
accessToken: createAccessToken(tokensResponse.access_token, tokensResponse.expires_in),
|
|
60
|
+
refreshToken: {
|
|
61
|
+
value: tokensResponse.refresh_token,
|
|
62
|
+
role: TokenRole.VISITOR,
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
const renewToken = async (refreshToken) => {
|
|
67
|
+
const tokensResponse = await fetchTokens({
|
|
68
|
+
refreshToken: refreshToken.value,
|
|
69
|
+
grantType: 'refresh_token',
|
|
70
|
+
});
|
|
71
|
+
const accessToken = createAccessToken(tokensResponse.access_token, tokensResponse.expires_in);
|
|
72
|
+
return {
|
|
73
|
+
accessToken,
|
|
74
|
+
refreshToken,
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
const generatePKCE = () => {
|
|
78
|
+
const pkceState = pkceChallenge();
|
|
79
|
+
return {
|
|
80
|
+
codeChallenge: pkceState.code_challenge,
|
|
81
|
+
codeVerifier: pkceState.code_verifier,
|
|
82
|
+
state: pkceChallenge().code_challenge,
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
const generateOAuthData = (redirectUri, originalUri) => {
|
|
86
|
+
const state = { redirectUri };
|
|
87
|
+
const pkceState = generatePKCE();
|
|
88
|
+
return {
|
|
89
|
+
...state,
|
|
90
|
+
originalUri: originalUri ?? '',
|
|
91
|
+
codeChallenge: pkceState.codeChallenge,
|
|
92
|
+
codeVerifier: pkceState.codeVerifier,
|
|
93
|
+
state: pkceChallenge().code_challenge,
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
const getAuthorizationUrlWithOptions = async (oauthData, responseMode, prompt, sessionToken) => {
|
|
97
|
+
const { redirectSession } = await wixClientWithTokens.redirects.createRedirectSession({
|
|
98
|
+
auth: {
|
|
99
|
+
authRequest: {
|
|
100
|
+
redirectUri: oauthData.redirectUri,
|
|
101
|
+
...(oauthData.redirectUri && {
|
|
102
|
+
redirectUri: oauthData.redirectUri,
|
|
103
|
+
}),
|
|
104
|
+
clientId: config.clientId,
|
|
105
|
+
codeChallenge: oauthData.codeChallenge,
|
|
106
|
+
codeChallengeMethod: 'S256',
|
|
107
|
+
responseMode,
|
|
108
|
+
responseType: 'code',
|
|
109
|
+
scope: 'offline_access',
|
|
110
|
+
state: oauthData.state,
|
|
111
|
+
...(sessionToken && { sessionToken }),
|
|
112
|
+
},
|
|
113
|
+
prompt: redirects.Prompt[prompt],
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
return { authUrl: redirectSession.fullUrl };
|
|
117
|
+
};
|
|
118
|
+
const getAuthUrl = async (oauthData, opts = {
|
|
119
|
+
prompt: 'login',
|
|
120
|
+
}) => {
|
|
121
|
+
return getAuthorizationUrlWithOptions(oauthData, opts.responseMode ?? 'fragment', opts.prompt ?? 'login');
|
|
122
|
+
};
|
|
123
|
+
const parseFromUrl = (url, responseMode = 'fragment') => {
|
|
124
|
+
const parsedUrl = new URL(url ?? window.location.href);
|
|
125
|
+
const params = responseMode === 'query'
|
|
126
|
+
? parsedUrl.searchParams
|
|
127
|
+
: new URLSearchParams(parsedUrl.hash.substring(1));
|
|
128
|
+
const code = params.get('code');
|
|
129
|
+
const state = params.get('state');
|
|
130
|
+
const error = params.get('error');
|
|
131
|
+
const errorDescription = params.get('error_description');
|
|
132
|
+
return { code, state, ...(error && { error, errorDescription }) };
|
|
133
|
+
};
|
|
134
|
+
const getMemberTokens = async (code, state, oauthData) => {
|
|
135
|
+
if (!code || !state) {
|
|
136
|
+
throw new Error('Missing code or _state');
|
|
137
|
+
}
|
|
138
|
+
else if (state !== oauthData.state) {
|
|
139
|
+
throw new Error('Invalid _state');
|
|
140
|
+
}
|
|
141
|
+
try {
|
|
142
|
+
const tokensResponse = await fetchTokens({
|
|
143
|
+
clientId: config.clientId,
|
|
144
|
+
grantType: 'authorization_code',
|
|
145
|
+
...(oauthData.redirectUri && { redirectUri: oauthData.redirectUri }),
|
|
146
|
+
code,
|
|
147
|
+
codeVerifier: oauthData.codeVerifier,
|
|
148
|
+
});
|
|
149
|
+
return {
|
|
150
|
+
accessToken: createAccessToken(tokensResponse.access_token, tokensResponse.expires_in),
|
|
151
|
+
refreshToken: {
|
|
152
|
+
value: tokensResponse.refresh_token,
|
|
153
|
+
role: TokenRole.MEMBER,
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
catch (e) {
|
|
158
|
+
throw new Error('Failed to get member tokens');
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
const logout = async (originalUrl) => {
|
|
162
|
+
const { redirectSession } = await wixClientWithTokens.redirects.createRedirectSession({
|
|
163
|
+
logout: { clientId: config.clientId },
|
|
164
|
+
callbacks: {
|
|
165
|
+
postFlowUrl: originalUrl,
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
_tokens.accessToken = { value: '', expiresAt: 0 };
|
|
169
|
+
_tokens.refreshToken = { value: '', role: TokenRole.NONE };
|
|
170
|
+
return { logoutUrl: redirectSession.fullUrl };
|
|
171
|
+
};
|
|
172
|
+
const handleState = (response) => {
|
|
173
|
+
if (response.state === authentication.StateType.SUCCESS) {
|
|
174
|
+
return {
|
|
175
|
+
loginState: LoginState.SUCCESS,
|
|
176
|
+
data: { sessionToken: response.sessionToken },
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
else if (response.state === authentication.StateType.REQUIRE_OWNER_APPROVAL) {
|
|
180
|
+
return {
|
|
181
|
+
loginState: LoginState.OWNER_APPROVAL_REQUIRED,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
else if (response.state === authentication.StateType.REQUIRE_EMAIL_VERIFICATION) {
|
|
185
|
+
_state = {
|
|
186
|
+
loginState: LoginState.EMAIL_VERIFICATION_REQUIRED,
|
|
187
|
+
data: { stateToken: response.stateToken },
|
|
188
|
+
};
|
|
189
|
+
return _state;
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
loginState: LoginState.FAILURE,
|
|
193
|
+
error: 'Unknown _state',
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
const register = async (params) => {
|
|
197
|
+
try {
|
|
198
|
+
const res = await wixClientWithTokens.authentication.registerV2({
|
|
199
|
+
email: params.email,
|
|
200
|
+
}, {
|
|
201
|
+
password: params.password,
|
|
202
|
+
profile: params.profile,
|
|
203
|
+
...(params.captchaTokens && {
|
|
204
|
+
captchaTokens: [
|
|
205
|
+
{
|
|
206
|
+
Recaptcha: params.captchaTokens?.recaptchaToken,
|
|
207
|
+
InvisibleRecaptcha: params.captchaTokens?.invisibleRecaptchaToken,
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
}),
|
|
211
|
+
});
|
|
212
|
+
return handleState(res);
|
|
213
|
+
}
|
|
214
|
+
catch (e) {
|
|
215
|
+
const emailValidation = e.details.validationError?.fieldViolations?.find((v) => v.data.type === 'EMAIL');
|
|
216
|
+
if (emailValidation) {
|
|
217
|
+
return {
|
|
218
|
+
loginState: LoginState.FAILURE,
|
|
219
|
+
error: emailValidation.description,
|
|
220
|
+
errorCode: 'invalidEmail',
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
if (e.details.applicationError?.code === MISSING_CAPTCHA) {
|
|
224
|
+
return {
|
|
225
|
+
loginState: LoginState.FAILURE,
|
|
226
|
+
error: e.message,
|
|
227
|
+
errorCode: 'missingCaptchaToken',
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
if (e.details.applicationError?.code === EMAIL_EXISTS) {
|
|
231
|
+
return {
|
|
232
|
+
loginState: LoginState.FAILURE,
|
|
233
|
+
error: e.message,
|
|
234
|
+
errorCode: 'emailAlreadyExists',
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
if (e.details.applicationError?.code === INVALID_CAPTCHA) {
|
|
238
|
+
return {
|
|
239
|
+
loginState: LoginState.FAILURE,
|
|
240
|
+
error: e.message,
|
|
241
|
+
errorCode: 'invalidCaptchaToken',
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
return {
|
|
245
|
+
loginState: LoginState.FAILURE,
|
|
246
|
+
error: e.message,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
const login = async (params) => {
|
|
251
|
+
try {
|
|
252
|
+
const res = await wixClientWithTokens.authentication.loginV2({
|
|
253
|
+
email: params.email,
|
|
254
|
+
}, {
|
|
255
|
+
password: params.password,
|
|
256
|
+
...(params.captchaTokens && {
|
|
257
|
+
captchaTokens: [
|
|
258
|
+
{
|
|
259
|
+
Recaptcha: params.captchaTokens?.recaptchaToken,
|
|
260
|
+
InvisibleRecaptcha: params.captchaTokens?.invisibleRecaptchaToken,
|
|
261
|
+
},
|
|
262
|
+
],
|
|
263
|
+
}),
|
|
264
|
+
});
|
|
265
|
+
return handleState(res);
|
|
266
|
+
}
|
|
267
|
+
catch (e) {
|
|
268
|
+
return {
|
|
269
|
+
loginState: LoginState.FAILURE,
|
|
270
|
+
error: e.message,
|
|
271
|
+
errorCode: e.details.applicationError?.code === MISSING_CAPTCHA
|
|
272
|
+
? 'missingCaptchaToken'
|
|
273
|
+
: e.details.applicationError?.code === INVALID_CAPTCHA
|
|
274
|
+
? 'invalidCaptchaToken'
|
|
275
|
+
: e.details.applicationError.code === INVALID_PASSWORD
|
|
276
|
+
? 'invalidPassword'
|
|
277
|
+
: e.details.applicationError.code === RESET_PASSWORD
|
|
278
|
+
? 'resetPassword'
|
|
279
|
+
: 'invalidEmail',
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
const processVerification = async (nextInputs, state) => {
|
|
284
|
+
const stateToUse = state ?? _state;
|
|
285
|
+
if (stateToUse.loginState === LoginState.EMAIL_VERIFICATION_REQUIRED) {
|
|
286
|
+
const code = nextInputs.verificationCode ?? nextInputs.code;
|
|
287
|
+
const res = await wixClientWithTokens.verification.verifyDuringAuthentication(code, { stateToken: stateToUse.data.stateToken });
|
|
288
|
+
return handleState(res);
|
|
289
|
+
}
|
|
290
|
+
return {
|
|
291
|
+
loginState: LoginState.FAILURE,
|
|
292
|
+
error: 'Unknown _state',
|
|
293
|
+
};
|
|
294
|
+
};
|
|
295
|
+
const getMemberTokensForDirectLogin = async (sessionToken) => {
|
|
296
|
+
const oauthPKCE = generatePKCE();
|
|
297
|
+
const { authUrl } = await getAuthorizationUrlWithOptions(oauthPKCE, 'web_message', 'none', sessionToken);
|
|
298
|
+
const iframePromise = addPostMessageListener(oauthPKCE.state);
|
|
299
|
+
const iframeEl = loadFrame(authUrl);
|
|
300
|
+
return iframePromise
|
|
301
|
+
.then((res) => {
|
|
302
|
+
return getMemberTokens(res.code, res.state, oauthPKCE);
|
|
303
|
+
})
|
|
304
|
+
.finally(() => {
|
|
305
|
+
if (document.body.contains(iframeEl)) {
|
|
306
|
+
iframeEl.parentElement?.removeChild(iframeEl);
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
};
|
|
310
|
+
const sendPasswordResetEmail = async (email, redirectUri) => {
|
|
311
|
+
await wixClientWithTokens.recovery.sendRecoveryEmail(email, {
|
|
312
|
+
redirect: { url: redirectUri, clientId: config.clientId },
|
|
313
|
+
});
|
|
314
|
+
};
|
|
315
|
+
const loggedIn = () => {
|
|
316
|
+
return _tokens.refreshToken.role === TokenRole.MEMBER;
|
|
317
|
+
};
|
|
318
|
+
return {
|
|
319
|
+
generateVisitorTokens,
|
|
320
|
+
renewToken,
|
|
321
|
+
parseFromUrl,
|
|
322
|
+
getAuthUrl,
|
|
323
|
+
getMemberTokens,
|
|
324
|
+
generateOAuthData,
|
|
325
|
+
getAuthHeaders,
|
|
326
|
+
setTokens,
|
|
327
|
+
getTokens: () => _tokens,
|
|
328
|
+
loggedIn,
|
|
329
|
+
logout,
|
|
330
|
+
register,
|
|
331
|
+
processVerification,
|
|
332
|
+
login,
|
|
333
|
+
getMemberTokensForDirectLogin,
|
|
334
|
+
sendPasswordResetEmail,
|
|
335
|
+
captchaInvisibleSiteKey: '6LdoPaUfAAAAAJphvHoUoOob7mx0KDlXyXlgrx5v',
|
|
336
|
+
captchaVisibleSiteKey: '6Ld0J8IcAAAAANyrnxzrRlX1xrrdXsOmsepUYosy',
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
const fetchTokens = async (payload) => {
|
|
340
|
+
const res = await fetch(`https://${API_URL}/oauth2/token`, {
|
|
341
|
+
method: 'POST',
|
|
342
|
+
body: JSON.stringify(payload),
|
|
343
|
+
headers: {
|
|
344
|
+
...biHeaderGenerator({
|
|
345
|
+
entityFqdn: 'wix.identity.oauth.v1.refresh_token',
|
|
346
|
+
methodFqn: 'wix.identity.oauth2.v1.Oauth2Ng.Token',
|
|
347
|
+
packageName: '@wix/sdk',
|
|
348
|
+
}),
|
|
349
|
+
'Content-Type': 'application/json',
|
|
350
|
+
},
|
|
351
|
+
});
|
|
352
|
+
if (res.status !== 200) {
|
|
353
|
+
throw new Error('something went wrong');
|
|
354
|
+
}
|
|
355
|
+
const json = await res.json();
|
|
356
|
+
return json;
|
|
357
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import SHA256 from 'crypto-js/sha256.js';
|
|
2
|
+
import encBase64url from 'crypto-js/enc-base64url.js';
|
|
3
|
+
export function pkceChallenge(length) {
|
|
4
|
+
if (!length) {
|
|
5
|
+
length = 43;
|
|
6
|
+
}
|
|
7
|
+
if (length < 43 || length > 128) {
|
|
8
|
+
throw new Error(`Expected a length between 43 and 128. Received ${length}.`);
|
|
9
|
+
}
|
|
10
|
+
const verifier = generateVerifier(length);
|
|
11
|
+
const challenge = generateChallenge(verifier);
|
|
12
|
+
return {
|
|
13
|
+
code_verifier: verifier,
|
|
14
|
+
code_challenge: challenge,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function generateVerifier(length) {
|
|
18
|
+
return random(length);
|
|
19
|
+
}
|
|
20
|
+
export function generateChallenge(code_verifier) {
|
|
21
|
+
return SHA256(code_verifier).toString(encBase64url);
|
|
22
|
+
}
|
|
23
|
+
function random(size) {
|
|
24
|
+
const mask = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~';
|
|
25
|
+
let result = '';
|
|
26
|
+
const randomUints = crypto.getRandomValues(new Uint8Array(size));
|
|
27
|
+
for (let i = 0; i < size; i++) {
|
|
28
|
+
// cap the value of the randomIndex to mask.length - 1
|
|
29
|
+
const randomIndex = randomUints[i] % mask.length;
|
|
30
|
+
result += mask[randomIndex];
|
|
31
|
+
}
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { authentication } from '@wix/identity';
|
|
2
|
+
import { AuthenticationStrategy } from '@wix/sdk-types';
|
|
3
|
+
export interface Tokens {
|
|
4
|
+
accessToken: AccessToken;
|
|
5
|
+
refreshToken: RefreshToken;
|
|
6
|
+
}
|
|
7
|
+
export interface Token {
|
|
8
|
+
value: string;
|
|
9
|
+
}
|
|
10
|
+
export interface AccessToken extends Token {
|
|
11
|
+
expiresAt: number;
|
|
12
|
+
}
|
|
13
|
+
export interface RefreshToken extends Token {
|
|
14
|
+
role: TokenRole;
|
|
15
|
+
}
|
|
16
|
+
export interface OauthData extends OauthPKCE {
|
|
17
|
+
originalUri: string;
|
|
18
|
+
redirectUri: string;
|
|
19
|
+
}
|
|
20
|
+
export interface OauthPKCE {
|
|
21
|
+
codeVerifier: string;
|
|
22
|
+
codeChallenge: string;
|
|
23
|
+
state: string;
|
|
24
|
+
}
|
|
25
|
+
export interface RegisterParams extends LoginParams {
|
|
26
|
+
profile?: authentication.IdentityProfile;
|
|
27
|
+
}
|
|
28
|
+
export interface LoginParams {
|
|
29
|
+
email: string;
|
|
30
|
+
password: string;
|
|
31
|
+
captchaTokens?: {
|
|
32
|
+
invisibleRecaptchaToken?: string;
|
|
33
|
+
recaptchaToken?: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export interface IOAuthStrategy extends AuthenticationStrategy {
|
|
37
|
+
generateVisitorTokens(tokens?: {
|
|
38
|
+
refreshToken?: RefreshToken;
|
|
39
|
+
accessToken?: AccessToken;
|
|
40
|
+
}): Promise<Tokens>;
|
|
41
|
+
renewToken: (refreshToken: RefreshToken) => Promise<Tokens>;
|
|
42
|
+
setTokens: (tokens: Tokens) => void;
|
|
43
|
+
getTokens: () => Tokens;
|
|
44
|
+
generateOAuthData: (redirectUri: string, originalUri?: string) => OauthData;
|
|
45
|
+
getAuthUrl: (oauthData: OauthData, opts?: {
|
|
46
|
+
prompt?: 'login' | 'none';
|
|
47
|
+
responseMode?: 'fragment' | 'web_message' | 'query';
|
|
48
|
+
}) => Promise<{
|
|
49
|
+
authUrl: string;
|
|
50
|
+
}>;
|
|
51
|
+
getMemberTokens: (code: string, state: string, oauthData: OauthData) => Promise<Tokens>;
|
|
52
|
+
logout: (originalUrl: string) => Promise<{
|
|
53
|
+
logoutUrl: string;
|
|
54
|
+
}>;
|
|
55
|
+
parseFromUrl: (url?: string, responseMode?: 'query' | 'fragment') => {
|
|
56
|
+
code: string;
|
|
57
|
+
state: string;
|
|
58
|
+
error?: string;
|
|
59
|
+
errorDescription?: string;
|
|
60
|
+
};
|
|
61
|
+
register: (params: RegisterParams) => Promise<StateMachine>;
|
|
62
|
+
login: (params: LoginParams) => Promise<StateMachine>;
|
|
63
|
+
processVerification<T extends ProcessableState>(nextInputs: CalculateNextState<T>, state?: StateMachine): Promise<StateMachine>;
|
|
64
|
+
getMemberTokensForDirectLogin: (sessionToken: string) => Promise<Tokens>;
|
|
65
|
+
sendPasswordResetEmail: (email: string, redirectUri: string) => Promise<void>;
|
|
66
|
+
captchaInvisibleSiteKey: string;
|
|
67
|
+
captchaVisibleSiteKey: string;
|
|
68
|
+
loggedIn: () => boolean;
|
|
69
|
+
}
|
|
70
|
+
export declare enum LoginState {
|
|
71
|
+
SUCCESS = "SUCCESS",
|
|
72
|
+
INITIAL = "INITIAL",
|
|
73
|
+
FAILURE = "FAILURE",
|
|
74
|
+
EMAIL_VERIFICATION_REQUIRED = "EMAIL_VERIFICATION_REQUIRED",
|
|
75
|
+
OWNER_APPROVAL_REQUIRED = "OWNER_APPROVAL_REQUIRED",
|
|
76
|
+
USER_CAPTCHA_REQUIRED = "USER_CAPTCHA_REQUIRED",
|
|
77
|
+
SILENT_CAPTCHA_REQUIRED = "SILENT_CAPTCHA_REQUIRED"
|
|
78
|
+
}
|
|
79
|
+
interface LoginResults<LK extends LoginState> {
|
|
80
|
+
loginState: LK;
|
|
81
|
+
}
|
|
82
|
+
interface SuccessState extends LoginResults<LoginState.SUCCESS> {
|
|
83
|
+
data: {
|
|
84
|
+
sessionToken: string;
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
interface InitialState extends LoginResults<LoginState.INITIAL> {
|
|
88
|
+
}
|
|
89
|
+
interface ErrorState extends LoginResults<LoginState.FAILURE> {
|
|
90
|
+
errorCode?: 'invalidEmail' | 'invalidPassword' | 'resetPassword' | 'missingCaptchaToken' | 'emailAlreadyExists' | 'invalidCaptchaToken';
|
|
91
|
+
error: string;
|
|
92
|
+
}
|
|
93
|
+
interface EmailVerificationRequiredState extends LoginResults<LoginState.EMAIL_VERIFICATION_REQUIRED> {
|
|
94
|
+
data: {
|
|
95
|
+
stateToken: string;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
interface OwnerApprovalRequiredState extends LoginResults<LoginState.OWNER_APPROVAL_REQUIRED> {
|
|
99
|
+
}
|
|
100
|
+
interface SilentCaptchaRequiredState extends LoginResults<LoginState.SILENT_CAPTCHA_REQUIRED> {
|
|
101
|
+
data: {
|
|
102
|
+
stateToken: string;
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
interface UserCaptchaRequiredState extends LoginResults<LoginState.USER_CAPTCHA_REQUIRED> {
|
|
106
|
+
data: {
|
|
107
|
+
stateToken: string;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
export declare enum TokenRole {
|
|
111
|
+
NONE = "none",
|
|
112
|
+
VISITOR = "visitor",
|
|
113
|
+
MEMBER = "member"
|
|
114
|
+
}
|
|
115
|
+
export type StateMachine = InitialState | SuccessState | ErrorState | EmailVerificationRequiredState | OwnerApprovalRequiredState | SilentCaptchaRequiredState | UserCaptchaRequiredState;
|
|
116
|
+
type VerificationCode = {
|
|
117
|
+
verificationCode: string;
|
|
118
|
+
};
|
|
119
|
+
export type CalculateNextState<T> = T extends EmailVerificationRequiredState ? VerificationCode : never;
|
|
120
|
+
export type ProcessableState = EmailVerificationRequiredState;
|
|
121
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export var LoginState;
|
|
2
|
+
(function (LoginState) {
|
|
3
|
+
LoginState["SUCCESS"] = "SUCCESS";
|
|
4
|
+
LoginState["INITIAL"] = "INITIAL";
|
|
5
|
+
LoginState["FAILURE"] = "FAILURE";
|
|
6
|
+
LoginState["EMAIL_VERIFICATION_REQUIRED"] = "EMAIL_VERIFICATION_REQUIRED";
|
|
7
|
+
LoginState["OWNER_APPROVAL_REQUIRED"] = "OWNER_APPROVAL_REQUIRED";
|
|
8
|
+
LoginState["USER_CAPTCHA_REQUIRED"] = "USER_CAPTCHA_REQUIRED";
|
|
9
|
+
LoginState["SILENT_CAPTCHA_REQUIRED"] = "SILENT_CAPTCHA_REQUIRED";
|
|
10
|
+
})(LoginState || (LoginState = {}));
|
|
11
|
+
export var TokenRole;
|
|
12
|
+
(function (TokenRole) {
|
|
13
|
+
TokenRole["NONE"] = "none";
|
|
14
|
+
TokenRole["VISITOR"] = "visitor";
|
|
15
|
+
TokenRole["MEMBER"] = "member";
|
|
16
|
+
})(TokenRole || (TokenRole = {}));
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { APIMetadata } from '@wix/sdk-types';
|
|
2
|
+
import { PublicMetadata } from '../common.js';
|
|
3
|
+
export declare const WixBIHeaderName = "x-wix-bi-gateway";
|
|
4
|
+
export type WixBIHeaderValues = {
|
|
5
|
+
['environment']: 'js-sdk';
|
|
6
|
+
['package-name']?: string;
|
|
7
|
+
['method-fqn']?: string;
|
|
8
|
+
['entity']?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function biHeaderGenerator(apiMetadata: APIMetadata, publicMetadata?: PublicMetadata): {
|
|
11
|
+
[WixBIHeaderName]: string;
|
|
12
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const WixBIHeaderName = 'x-wix-bi-gateway';
|
|
2
|
+
export function biHeaderGenerator(apiMetadata, publicMetadata) {
|
|
3
|
+
return {
|
|
4
|
+
[WixBIHeaderName]: objectToKeyValue({
|
|
5
|
+
environment: 'js-sdk',
|
|
6
|
+
'package-name': apiMetadata.packageName ?? publicMetadata?.PACKAGE_NAME,
|
|
7
|
+
'method-fqn': apiMetadata.methodFqn,
|
|
8
|
+
entity: apiMetadata.entityFqdn,
|
|
9
|
+
}),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
function objectToKeyValue(input) {
|
|
13
|
+
return Object.entries(input)
|
|
14
|
+
.filter(([_, value]) => Boolean(value))
|
|
15
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
16
|
+
.join(',');
|
|
17
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare const PUBLIC_METADATA_KEY = "__metadata";
|
|
2
|
+
export type PublicMetadata = {
|
|
3
|
+
PACKAGE_NAME?: string;
|
|
4
|
+
};
|
|
5
|
+
export declare const API_URL = "www.wixapis.com";
|
|
6
|
+
export declare const READ_ONLY_API_URL = "readonly.wixapis.com";
|
|
7
|
+
export declare const FORCE_WRITE_API_URLS: string[];
|
package/build/common.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export class FetchErrorResponse extends Error {
|
|
2
|
+
message;
|
|
3
|
+
response;
|
|
4
|
+
constructor(message, response) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.message = message;
|
|
7
|
+
this.response = response;
|
|
8
|
+
}
|
|
9
|
+
async details() {
|
|
10
|
+
const dataError = await this.response.json();
|
|
11
|
+
return errorBuilder(this.response.status, dataError?.message, dataError?.details, {
|
|
12
|
+
requestId: this.response.headers.get('X-Wix-Request-Id'),
|
|
13
|
+
details: dataError,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const errorBuilder = (code, description, details, data) => {
|
|
18
|
+
return {
|
|
19
|
+
details: {
|
|
20
|
+
...(!details?.validationError && {
|
|
21
|
+
applicationError: {
|
|
22
|
+
description,
|
|
23
|
+
code,
|
|
24
|
+
data,
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
|
+
...details,
|
|
28
|
+
},
|
|
29
|
+
message: description,
|
|
30
|
+
};
|
|
31
|
+
};
|
package/build/helpers.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// we follow a simplified version of the axios convention
|
|
2
|
+
// https://github.com/axios/axios/blob/649d739288c8e2c55829ac60e2345a0f3439c730/lib/defaults/index.js#L65
|
|
3
|
+
export const getDefaultContentHeader = (options) => {
|
|
4
|
+
if (options?.method &&
|
|
5
|
+
['post', 'put', 'patch'].includes(options.method.toLocaleLowerCase()) &&
|
|
6
|
+
options.body) {
|
|
7
|
+
return { 'Content-Type': 'application/json' };
|
|
8
|
+
}
|
|
9
|
+
return {};
|
|
10
|
+
};
|
|
11
|
+
export const isObject = (val) => val && typeof val === 'object' && !Array.isArray(val);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function addListener(eventTarget: any, name: string, fn: Function): void;
|
|
2
|
+
export declare function removeListener(eventTarget: any, name: string, fn: Function): void;
|
|
3
|
+
export declare function loadFrame(src: string): HTMLIFrameElement;
|
|
4
|
+
export declare function addPostMessageListener(state: string): Promise<unknown>;
|