@turnkey/react-wallet-kit 1.11.0 → 2.0.0
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/dist/components/auth/OTP.d.ts +1 -0
- package/dist/components/auth/OTP.d.ts.map +1 -1
- package/dist/components/auth/OTP.js +8 -2
- package/dist/components/auth/OTP.js.map +1 -1
- package/dist/components/auth/OTP.mjs +21 -13
- package/dist/components/auth/OTP.mjs.map +1 -1
- package/dist/components/auth/index.d.ts.map +1 -1
- package/dist/components/auth/index.js +11 -3
- package/dist/components/auth/index.js.map +1 -1
- package/dist/components/auth/index.mjs +12 -5
- package/dist/components/auth/index.mjs.map +1 -1
- package/dist/components/user/UpdateEmail.js +6 -3
- package/dist/components/user/UpdateEmail.js.map +1 -1
- package/dist/components/user/UpdateEmail.mjs +6 -4
- package/dist/components/user/UpdateEmail.mjs.map +1 -1
- package/dist/components/user/UpdatePhoneNumber.js +6 -3
- package/dist/components/user/UpdatePhoneNumber.js.map +1 -1
- package/dist/components/user/UpdatePhoneNumber.mjs +6 -4
- package/dist/components/user/UpdatePhoneNumber.mjs.map +1 -1
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/providers/client/Provider.d.ts.map +1 -1
- package/dist/providers/client/Provider.js +611 -430
- package/dist/providers/client/Provider.js.map +1 -1
- package/dist/providers/client/Provider.mjs +2055 -1820
- package/dist/providers/client/Provider.mjs.map +1 -1
- package/dist/providers/client/Types.d.ts +14 -7
- package/dist/providers/client/Types.d.ts.map +1 -1
- package/dist/providers/client/Types.js.map +1 -1
- package/dist/providers/client/Types.mjs.map +1 -1
- package/dist/typedoc-entry/index.d.ts +1 -1
- package/dist/typedoc-entry/index.d.ts.map +1 -1
- package/dist/types/base.d.ts +38 -28
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/base.js.map +1 -1
- package/dist/types/base.mjs.map +1 -1
- package/dist/types/method-types.d.ts +12 -5
- package/dist/types/method-types.d.ts.map +1 -1
- package/dist/utils/oauth/completion.d.ts +132 -0
- package/dist/utils/oauth/completion.d.ts.map +1 -0
- package/dist/utils/oauth/completion.js +136 -0
- package/dist/utils/oauth/completion.js.map +1 -0
- package/dist/utils/oauth/completion.mjs +176 -0
- package/dist/utils/oauth/completion.mjs.map +1 -0
- package/dist/utils/oauth/config.d.ts +34 -0
- package/dist/utils/oauth/config.d.ts.map +1 -0
- package/dist/utils/oauth/config.js +69 -0
- package/dist/utils/oauth/config.js.map +1 -0
- package/dist/utils/oauth/config.mjs +54 -0
- package/dist/utils/oauth/config.mjs.map +1 -0
- package/dist/utils/oauth/helpers.d.ts +13 -0
- package/dist/utils/oauth/helpers.d.ts.map +1 -0
- package/dist/utils/oauth/helpers.js +38 -0
- package/dist/utils/oauth/helpers.js.map +1 -0
- package/dist/utils/oauth/helpers.mjs +35 -0
- package/dist/utils/oauth/helpers.mjs.map +1 -0
- package/dist/utils/oauth/index.d.ts +7 -0
- package/dist/utils/oauth/index.d.ts.map +1 -0
- package/dist/utils/oauth/pkce.d.ts +14 -0
- package/dist/utils/oauth/pkce.d.ts.map +1 -0
- package/dist/utils/oauth/pkce.js +48 -0
- package/dist/utils/oauth/pkce.js.map +1 -0
- package/dist/utils/oauth/pkce.mjs +85 -0
- package/dist/utils/oauth/pkce.mjs.map +1 -0
- package/dist/utils/oauth/storage.d.ts +59 -0
- package/dist/utils/oauth/storage.d.ts.map +1 -0
- package/dist/utils/oauth/storage.js +116 -0
- package/dist/utils/oauth/storage.js.map +1 -0
- package/dist/utils/oauth/storage.mjs +104 -0
- package/dist/utils/oauth/storage.mjs.map +1 -0
- package/dist/utils/oauth/url.d.ts +92 -0
- package/dist/utils/oauth/url.d.ts.map +1 -0
- package/dist/utils/oauth/url.js +231 -0
- package/dist/utils/oauth/url.js.map +1 -0
- package/dist/utils/oauth/url.mjs +237 -0
- package/dist/utils/oauth/url.mjs.map +1 -0
- package/package.json +3 -3
- package/dist/utils/oauth.d.ts +0 -323
- package/dist/utils/oauth.d.ts.map +0 -1
- package/dist/utils/oauth.js +0 -613
- package/dist/utils/oauth.js.map +0 -1
- package/dist/utils/oauth.mjs +0 -670
- package/dist/utils/oauth.mjs.map +0 -1
|
@@ -4,7 +4,12 @@
|
|
|
4
4
|
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
var sha2 = require('@noble/hashes/sha2');
|
|
6
6
|
var utils$1 = require('@noble/hashes/utils');
|
|
7
|
-
var
|
|
7
|
+
var storage = require('../../utils/oauth/storage.js');
|
|
8
|
+
require('../../utils/oauth/config.js');
|
|
9
|
+
var url = require('../../utils/oauth/url.js');
|
|
10
|
+
var completion = require('../../utils/oauth/completion.js');
|
|
11
|
+
var pkce = require('../../utils/oauth/pkce.js');
|
|
12
|
+
var helpers = require('../../utils/oauth/helpers.js');
|
|
8
13
|
var utils = require('../../utils/utils.js');
|
|
9
14
|
var timers = require('../../utils/timers.js');
|
|
10
15
|
var core = require('@turnkey/core');
|
|
@@ -33,7 +38,7 @@ var Verify = require('../../components/verify/Verify.js');
|
|
|
33
38
|
var OnRamp = require('../../components/onramp/OnRamp.js');
|
|
34
39
|
var Svg = require('../../components/design/Svg.js');
|
|
35
40
|
var SendTransaction = require('../../components/send-transaction/SendTransaction.js');
|
|
36
|
-
var helpers = require('../../components/send-transaction/helpers.js');
|
|
41
|
+
var helpers$1 = require('../../components/send-transaction/helpers.js');
|
|
37
42
|
|
|
38
43
|
/**
|
|
39
44
|
* Provides Turnkey client authentication, session management, wallet operations, and user profile management
|
|
@@ -89,302 +94,346 @@ const ClientProvider = ({
|
|
|
89
94
|
closeModal
|
|
90
95
|
} = Hook.useModal();
|
|
91
96
|
const completeRedirectOauth = async () => {
|
|
92
|
-
//
|
|
93
|
-
if
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
* This is the key difference between redirect and popup flows:
|
|
100
|
-
* - Popup: No modal needed (the popup window itself is the UI)
|
|
101
|
-
* - Redirect: Optional modal to show loading/success states on return
|
|
102
|
-
*/
|
|
103
|
-
const withModalWrapper = async params => {
|
|
104
|
-
const {
|
|
105
|
-
provider,
|
|
106
|
-
isAddProvider,
|
|
107
|
-
metadata,
|
|
108
|
-
openModal,
|
|
109
|
-
action
|
|
110
|
-
} = params;
|
|
111
|
-
const providerDisplayName = oauth.capitalizeProviderName(provider);
|
|
112
|
-
const icon = oauth.getProviderIcon(provider);
|
|
113
|
-
if (openModal === "true") {
|
|
114
|
-
// Show modal UI for the completion
|
|
115
|
-
await new Promise((resolve, reject) => {
|
|
116
|
-
pushPage({
|
|
117
|
-
key: `${providerDisplayName} OAuth`,
|
|
118
|
-
content: jsxRuntime.jsx(Action.ActionPage, {
|
|
119
|
-
closeOnComplete: isAddProvider ? false : true,
|
|
120
|
-
title: isAddProvider ? `Adding ${providerDisplayName} provider...` : `Authenticating with ${providerDisplayName}...`,
|
|
121
|
-
action: async () => {
|
|
122
|
-
try {
|
|
123
|
-
await action();
|
|
124
|
-
if (isAddProvider && metadata) {
|
|
125
|
-
// Don't show success for auth. Not needed
|
|
126
|
-
pushPage({
|
|
127
|
-
key: "OAuth Provider Added",
|
|
128
|
-
content: jsxRuntime.jsx(Success.SuccessPage, {
|
|
129
|
-
text: `Successfully added ${providerDisplayName} OAuth provider!`,
|
|
130
|
-
duration: metadata.successPageDuration ?? 2000,
|
|
131
|
-
onComplete: () => {
|
|
132
|
-
closeModal();
|
|
133
|
-
}
|
|
134
|
-
}),
|
|
135
|
-
preventBack: true,
|
|
136
|
-
showTitle: false
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
resolve();
|
|
140
|
-
} catch (err) {
|
|
141
|
-
if (isAddProvider) {
|
|
142
|
-
oauth.clearOAuthAddProviderMetadata();
|
|
143
|
-
}
|
|
144
|
-
reject(err);
|
|
145
|
-
popPage();
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
icon: jsxRuntime.jsx(reactFontawesome.FontAwesomeIcon, {
|
|
149
|
-
icon: icon,
|
|
150
|
-
size: "3x"
|
|
151
|
-
})
|
|
152
|
-
}),
|
|
153
|
-
showTitle: false,
|
|
154
|
-
onClose: () => {
|
|
155
|
-
if (isAddProvider) {
|
|
156
|
-
oauth.clearOAuthAddProviderMetadata();
|
|
157
|
-
}
|
|
158
|
-
reject(new sdkTypes.TurnkeyError(isAddProvider ? `User canceled the ${providerDisplayName} add provider process.` : `User canceled the ${providerDisplayName} authentication process.`, sdkTypes.TurnkeyErrorCodes.USER_CANCELED));
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
});
|
|
162
|
-
} else {
|
|
163
|
-
// No modal - execute directly
|
|
164
|
-
try {
|
|
165
|
-
await action();
|
|
166
|
-
} catch (err) {
|
|
167
|
-
if (isAddProvider) {
|
|
168
|
-
oauth.clearOAuthAddProviderMetadata();
|
|
169
|
-
}
|
|
170
|
-
throw err;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
};
|
|
174
|
-
// Handle PKCE-based OAuth redirects (Facebook, Discord, X) with code in search parameters
|
|
175
|
-
if (window.location.search && window.location.search.includes("code=") && window.location.search.includes("state=")) {
|
|
176
|
-
// Parse the URL using our unified helper
|
|
177
|
-
const result = oauth.parseOAuthResponse(window.location.href);
|
|
178
|
-
if (!result || !result.authCode || !result.publicKey) {
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
181
|
-
if (result.flow !== "redirect") {
|
|
182
|
-
// To complete OAuth we need redirect flow
|
|
97
|
+
// Since we use localStorage (see storage.ts), we always clean up OAuth data
|
|
98
|
+
// when this runs — even if there are no OAuth params in the URL (e.g. the
|
|
99
|
+
// user canceled at the provider and came back manually)
|
|
100
|
+
try {
|
|
101
|
+
// Check for either hash or search parameters that could indicate an OAuth redirect
|
|
102
|
+
if (!window.location.hash && !window.location.search) {
|
|
103
|
+
// No OAuth redirect parameters found, nothing to do
|
|
183
104
|
return;
|
|
184
105
|
}
|
|
185
|
-
const {
|
|
186
|
-
authCode: code,
|
|
187
|
-
provider,
|
|
188
|
-
publicKey,
|
|
189
|
-
oauthIntent,
|
|
190
|
-
sessionKey,
|
|
191
|
-
nonce,
|
|
192
|
-
openModal
|
|
193
|
-
} = result;
|
|
194
|
-
const isAddProvider = oauthIntent === oauth.OAUTH_INTENT_ADD_PROVIDER;
|
|
195
|
-
const metadata = isAddProvider ? oauth.getOAuthAddProviderMetadata() : null;
|
|
196
106
|
/**
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
107
|
+
* Wraps an OAuth completion action with optional modal UI.
|
|
108
|
+
* This is the key difference between redirect and popup flows:
|
|
109
|
+
* - Popup: No modal needed (the popup window itself is the UI)
|
|
110
|
+
* - Redirect: Optional modal to show loading/success states on return
|
|
200
111
|
*/
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
await oauth.handlePKCEFlow({
|
|
205
|
-
publicKey,
|
|
206
|
-
providerName,
|
|
207
|
-
sessionKey: sessionKey ?? undefined,
|
|
208
|
-
callbacks,
|
|
209
|
-
completeOauth,
|
|
210
|
-
onAddProvider:
|
|
211
|
-
// Only set onAddProvider if we are adding a provider and have metadata
|
|
212
|
-
isAddProvider && metadata ? async oidcToken => {
|
|
213
|
-
await addOauthProvider({
|
|
214
|
-
providerName: provider,
|
|
215
|
-
oidcToken,
|
|
216
|
-
organizationId: metadata.organizationId,
|
|
217
|
-
userId: metadata.userId,
|
|
218
|
-
...(metadata.stampWith && {
|
|
219
|
-
stampWith: metadata.stampWith
|
|
220
|
-
})
|
|
221
|
-
});
|
|
222
|
-
oauth.clearOAuthAddProviderMetadata();
|
|
223
|
-
} : undefined,
|
|
224
|
-
exchangeCodeForToken: exchangeCodeFn
|
|
225
|
-
});
|
|
226
|
-
} catch (err) {
|
|
227
|
-
if (callbacks?.onError) {
|
|
228
|
-
const providerDisplayName = oauth.capitalizeProviderName(providerName);
|
|
229
|
-
callbacks.onError(err instanceof sdkTypes.TurnkeyError ? err : new sdkTypes.TurnkeyError(`${providerDisplayName} authentication failed`, sdkTypes.TurnkeyErrorCodes.OAUTH_SIGNUP_ERROR, err));
|
|
230
|
-
}
|
|
231
|
-
throw err;
|
|
232
|
-
}
|
|
233
|
-
};
|
|
234
|
-
await withModalWrapper({
|
|
235
|
-
provider: providerName,
|
|
112
|
+
const withModalWrapper = async params => {
|
|
113
|
+
const {
|
|
114
|
+
provider,
|
|
236
115
|
isAddProvider,
|
|
237
116
|
metadata,
|
|
238
117
|
openModal,
|
|
239
118
|
action
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
119
|
+
} = params;
|
|
120
|
+
const providerDisplayName = helpers.capitalizeProviderName(provider);
|
|
121
|
+
const icon = helpers.getProviderIcon(provider);
|
|
122
|
+
if (openModal === "true") {
|
|
123
|
+
// Show modal UI for the completion
|
|
124
|
+
await new Promise((resolve, reject) => {
|
|
125
|
+
pushPage({
|
|
126
|
+
key: `${providerDisplayName} OAuth`,
|
|
127
|
+
content: jsxRuntime.jsx(Action.ActionPage, {
|
|
128
|
+
closeOnComplete: isAddProvider ? false : true,
|
|
129
|
+
title: isAddProvider ? `Adding ${providerDisplayName} provider...` : `Authenticating with ${providerDisplayName}...`,
|
|
130
|
+
action: async () => {
|
|
131
|
+
try {
|
|
132
|
+
await action();
|
|
133
|
+
if (isAddProvider && metadata) {
|
|
134
|
+
// Don't show success for auth. Not needed
|
|
135
|
+
pushPage({
|
|
136
|
+
key: "OAuth Provider Added",
|
|
137
|
+
content: jsxRuntime.jsx(Success.SuccessPage, {
|
|
138
|
+
text: `Successfully added ${providerDisplayName} OAuth provider!`,
|
|
139
|
+
duration: metadata.successPageDuration ?? 2000,
|
|
140
|
+
onComplete: () => {
|
|
141
|
+
closeModal();
|
|
142
|
+
}
|
|
143
|
+
}),
|
|
144
|
+
preventBack: true,
|
|
145
|
+
showTitle: false
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
resolve();
|
|
149
|
+
} catch (err) {
|
|
150
|
+
reject(err);
|
|
151
|
+
popPage();
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
icon: jsxRuntime.jsx(reactFontawesome.FontAwesomeIcon, {
|
|
155
|
+
icon: icon,
|
|
156
|
+
size: "3x"
|
|
157
|
+
})
|
|
158
|
+
}),
|
|
159
|
+
showTitle: false,
|
|
160
|
+
onClose: () => {
|
|
161
|
+
reject(new sdkTypes.TurnkeyError(isAddProvider ? `User canceled the ${providerDisplayName} add provider process.` : `User canceled the ${providerDisplayName} authentication process.`, sdkTypes.TurnkeyErrorCodes.USER_CANCELED));
|
|
162
|
+
}
|
|
275
163
|
});
|
|
276
|
-
const oidcToken = resp?.oidcToken;
|
|
277
|
-
if (!oidcToken) {
|
|
278
|
-
throw new sdkTypes.TurnkeyError("Missing OIDC token", sdkTypes.TurnkeyErrorCodes.OAUTH_LOGIN_ERROR);
|
|
279
|
-
}
|
|
280
|
-
return oidcToken;
|
|
281
164
|
});
|
|
165
|
+
} else {
|
|
166
|
+
// No modal - execute directly
|
|
167
|
+
await action();
|
|
282
168
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
169
|
+
};
|
|
170
|
+
// Handle PKCE-based OAuth redirects (Facebook, Discord, X) with code in search parameters
|
|
171
|
+
if (window.location.search && window.location.search.includes("code=") && window.location.search.includes("state=")) {
|
|
172
|
+
// Parse the URL using our unified helper
|
|
173
|
+
const result = url.parseOAuthResponse(window.location.href);
|
|
174
|
+
if (!result || !result.authCode || !result.publicKey) {
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (result.flow !== "redirect") {
|
|
178
|
+
// To complete OAuth we need redirect flow
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const {
|
|
182
|
+
authCode: code,
|
|
183
|
+
provider,
|
|
184
|
+
publicKey,
|
|
185
|
+
oauthIntent,
|
|
186
|
+
sessionKey,
|
|
187
|
+
nonce,
|
|
188
|
+
openModal
|
|
189
|
+
} = result;
|
|
190
|
+
const isAddProvider = oauthIntent === storage.OAUTH_INTENT_ADD_PROVIDER;
|
|
191
|
+
const metadata = isAddProvider ? storage.getOAuthAddProviderMetadata() : null;
|
|
192
|
+
/**
|
|
193
|
+
* Helper to complete PKCE redirect flow with optional modal wrapper.
|
|
194
|
+
* Uses handlePKCEFlow from oauth utils for the core logic.
|
|
195
|
+
* We put this in a separate function to avoid duplicating for each provider.
|
|
196
|
+
*/
|
|
197
|
+
const completePKCERedirect = async (providerName, exchangeCodeFn, secondaryClientIds) => {
|
|
198
|
+
const action = async () => {
|
|
199
|
+
try {
|
|
200
|
+
await completion.completePKCEFlow({
|
|
201
|
+
publicKey,
|
|
202
|
+
providerName,
|
|
203
|
+
sessionKey: sessionKey ?? undefined,
|
|
204
|
+
callbacks,
|
|
205
|
+
completeOauth: completionParams => {
|
|
206
|
+
const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
|
|
207
|
+
const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? providerName, secondaryClientIds);
|
|
208
|
+
return completeOauth({
|
|
209
|
+
...completionParams,
|
|
210
|
+
...(secondaryProviders.length > 0 && {
|
|
211
|
+
createSubOrgParams: {
|
|
212
|
+
...existingCreateSubOrgParams,
|
|
213
|
+
oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
|
|
214
|
+
}
|
|
215
|
+
})
|
|
216
|
+
});
|
|
217
|
+
},
|
|
218
|
+
onAddProvider:
|
|
219
|
+
// Only set onAddProvider if we are adding a provider and have metadata
|
|
220
|
+
isAddProvider && metadata ? async oidcToken => {
|
|
221
|
+
const oidcClaims = core.buildSecondaryOidcClaims(oidcToken, secondaryClientIds);
|
|
222
|
+
await addOauthProvider({
|
|
223
|
+
providerName: provider,
|
|
224
|
+
oidcToken,
|
|
225
|
+
...(oidcClaims.length > 0 && {
|
|
226
|
+
oidcClaims
|
|
227
|
+
}),
|
|
228
|
+
organizationId: metadata.organizationId,
|
|
229
|
+
userId: metadata.userId,
|
|
230
|
+
...(metadata.stampWith && {
|
|
231
|
+
stampWith: metadata.stampWith
|
|
232
|
+
})
|
|
233
|
+
});
|
|
234
|
+
} : undefined,
|
|
235
|
+
exchangeCodeForToken: exchangeCodeFn
|
|
236
|
+
});
|
|
237
|
+
} catch (err) {
|
|
238
|
+
if (callbacks?.onError) {
|
|
239
|
+
const providerDisplayName = helpers.capitalizeProviderName(providerName);
|
|
240
|
+
callbacks.onError(err instanceof sdkTypes.TurnkeyError ? err : new sdkTypes.TurnkeyError(`${providerDisplayName} authentication failed`, sdkTypes.TurnkeyErrorCodes.OAUTH_SIGNUP_ERROR, err));
|
|
241
|
+
}
|
|
242
|
+
throw err;
|
|
303
243
|
}
|
|
304
|
-
|
|
244
|
+
};
|
|
245
|
+
await withModalWrapper({
|
|
246
|
+
provider: providerName,
|
|
247
|
+
isAddProvider,
|
|
248
|
+
metadata,
|
|
249
|
+
openModal,
|
|
250
|
+
action
|
|
305
251
|
});
|
|
252
|
+
// Clean up URL after successful completion
|
|
253
|
+
url.cleanupOAuthUrl();
|
|
254
|
+
};
|
|
255
|
+
// FACEBOOK
|
|
256
|
+
if (provider === sdkTypes.OAuthProviders.FACEBOOK) {
|
|
257
|
+
const clientId = masterConfig?.auth?.oauthConfig?.facebook?.primaryClientId;
|
|
258
|
+
const secondaryClientIds = masterConfig?.auth?.oauthConfig?.facebook?.secondaryClientIds ?? [];
|
|
259
|
+
const redirectURI = masterConfig?.auth?.oauthConfig?.oauthRedirectUri;
|
|
260
|
+
const hasVerifier = storage.hasPKCEVerifier(sdkTypes.OAuthProviders.FACEBOOK);
|
|
261
|
+
if (clientId && redirectURI && hasVerifier) {
|
|
262
|
+
await completePKCERedirect(sdkTypes.OAuthProviders.FACEBOOK, async codeVerifier => {
|
|
263
|
+
const tokenResponse = await pkce.exchangeFacebookCodeForToken(clientId, redirectURI, code, codeVerifier);
|
|
264
|
+
const oidcToken = tokenResponse?.id_token;
|
|
265
|
+
if (!oidcToken) {
|
|
266
|
+
throw new sdkTypes.TurnkeyError("Missing OIDC token", sdkTypes.TurnkeyErrorCodes.OAUTH_LOGIN_ERROR);
|
|
267
|
+
}
|
|
268
|
+
return oidcToken;
|
|
269
|
+
}, secondaryClientIds);
|
|
270
|
+
}
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
// DISCORD
|
|
274
|
+
if (provider === sdkTypes.OAuthProviders.DISCORD) {
|
|
275
|
+
const clientId = masterConfig?.auth?.oauthConfig?.discord?.primaryClientId;
|
|
276
|
+
const secondaryClientIds = masterConfig?.auth?.oauthConfig?.discord?.secondaryClientIds ?? [];
|
|
277
|
+
const redirectURI = masterConfig?.auth?.oauthConfig?.oauthRedirectUri;
|
|
278
|
+
const hasVerifier = storage.hasPKCEVerifier(sdkTypes.OAuthProviders.DISCORD);
|
|
279
|
+
if (clientId && redirectURI && hasVerifier && nonce) {
|
|
280
|
+
await completePKCERedirect(sdkTypes.OAuthProviders.DISCORD, async codeVerifier => {
|
|
281
|
+
const resp = await client?.httpClient.proxyOAuth2Authenticate({
|
|
282
|
+
provider: "OAUTH2_PROVIDER_DISCORD",
|
|
283
|
+
authCode: code,
|
|
284
|
+
redirectUri: redirectURI,
|
|
285
|
+
codeVerifier,
|
|
286
|
+
clientId,
|
|
287
|
+
nonce
|
|
288
|
+
});
|
|
289
|
+
const oidcToken = resp?.oidcToken;
|
|
290
|
+
if (!oidcToken) {
|
|
291
|
+
throw new sdkTypes.TurnkeyError("Missing OIDC token", sdkTypes.TurnkeyErrorCodes.OAUTH_LOGIN_ERROR);
|
|
292
|
+
}
|
|
293
|
+
return oidcToken;
|
|
294
|
+
}, secondaryClientIds);
|
|
295
|
+
}
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
// X (Twitter)
|
|
299
|
+
if (provider === sdkTypes.OAuthProviders.X) {
|
|
300
|
+
const clientId = masterConfig?.auth?.oauthConfig?.x?.primaryClientId;
|
|
301
|
+
const secondaryClientIds = masterConfig?.auth?.oauthConfig?.x?.secondaryClientIds ?? [];
|
|
302
|
+
const redirectURI = masterConfig?.auth?.oauthConfig?.oauthRedirectUri;
|
|
303
|
+
const hasVerifier = storage.hasPKCEVerifier(sdkTypes.OAuthProviders.X);
|
|
304
|
+
if (clientId && redirectURI && hasVerifier && nonce) {
|
|
305
|
+
await completePKCERedirect(sdkTypes.OAuthProviders.X, async codeVerifier => {
|
|
306
|
+
const resp = await client?.httpClient.proxyOAuth2Authenticate({
|
|
307
|
+
provider: "OAUTH2_PROVIDER_X",
|
|
308
|
+
authCode: code,
|
|
309
|
+
redirectUri: redirectURI,
|
|
310
|
+
codeVerifier,
|
|
311
|
+
clientId,
|
|
312
|
+
nonce
|
|
313
|
+
});
|
|
314
|
+
const oidcToken = resp?.oidcToken;
|
|
315
|
+
if (!oidcToken) {
|
|
316
|
+
throw new sdkTypes.TurnkeyError("Missing OIDC token", sdkTypes.TurnkeyErrorCodes.OAUTH_LOGIN_ERROR);
|
|
317
|
+
}
|
|
318
|
+
return oidcToken;
|
|
319
|
+
}, secondaryClientIds);
|
|
320
|
+
}
|
|
321
|
+
return;
|
|
306
322
|
}
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
// Handle Google/Apple redirects (uses hash with idToken - non-PKCE)
|
|
311
|
-
if (window.location.hash) {
|
|
312
|
-
// Parse the URL using our unified helper
|
|
313
|
-
const result = oauth.parseOAuthResponse(window.location.href);
|
|
314
|
-
if (!result || !result.idToken || result.flow !== "redirect" || !result.publicKey) {
|
|
315
|
-
// idToken and publicKey are required to complete OAuth. These are both in the hash for non-PKCE providers
|
|
316
|
-
return;
|
|
317
323
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
// Use completeOAuthFlow from utils for the core completion logic
|
|
330
|
-
const action = async () => {
|
|
331
|
-
await oauth.completeOAuthFlow({
|
|
332
|
-
provider: resolvedProvider,
|
|
324
|
+
// Handle Google/Apple redirects (uses hash with idToken - non-PKCE)
|
|
325
|
+
if (window.location.hash) {
|
|
326
|
+
// Parse the URL using our unified helper
|
|
327
|
+
const result = url.parseOAuthResponse(window.location.href);
|
|
328
|
+
if (!result || !result.idToken || result.flow !== "redirect" || !result.publicKey) {
|
|
329
|
+
// idToken and publicKey are required to complete OAuth. These are both in the hash for non-PKCE providers
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
const {
|
|
333
|
+
idToken,
|
|
334
|
+
provider,
|
|
333
335
|
publicKey,
|
|
334
|
-
|
|
335
|
-
sessionKey
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
336
|
+
openModal,
|
|
337
|
+
sessionKey,
|
|
338
|
+
oauthIntent
|
|
339
|
+
} = result;
|
|
340
|
+
const isAddProvider = oauthIntent === storage.OAUTH_INTENT_ADD_PROVIDER;
|
|
341
|
+
const metadata = isAddProvider ? storage.getOAuthAddProviderMetadata() : null;
|
|
342
|
+
const resolvedProvider = provider || sdkTypes.OAuthProviders.GOOGLE;
|
|
343
|
+
// Grab Google/Apple secondary client IDs from config for use in completion
|
|
344
|
+
const secondaryClientIds = (resolvedProvider === sdkTypes.OAuthProviders.GOOGLE ? masterConfig?.auth?.oauthConfig?.google?.secondaryClientIds : resolvedProvider === sdkTypes.OAuthProviders.APPLE ? masterConfig?.auth?.oauthConfig?.apple?.secondaryClientIds : undefined) ?? [];
|
|
345
|
+
// Use completeOAuthFlow from utils for the core completion logic
|
|
346
|
+
const action = async () => {
|
|
347
|
+
await completion.completeOAuthFlow({
|
|
348
|
+
provider: resolvedProvider,
|
|
349
|
+
publicKey,
|
|
350
|
+
oidcToken: idToken,
|
|
351
|
+
sessionKey: sessionKey ?? undefined,
|
|
352
|
+
callbacks,
|
|
353
|
+
completeOauth: completionParams => {
|
|
354
|
+
const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
|
|
355
|
+
const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? resolvedProvider, secondaryClientIds);
|
|
356
|
+
return completeOauth({
|
|
357
|
+
...completionParams,
|
|
358
|
+
...(secondaryProviders.length > 0 && {
|
|
359
|
+
createSubOrgParams: {
|
|
360
|
+
...existingCreateSubOrgParams,
|
|
361
|
+
oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
|
|
362
|
+
}
|
|
363
|
+
})
|
|
364
|
+
});
|
|
365
|
+
},
|
|
366
|
+
onAddProvider: isAddProvider && metadata ? async oidcToken => {
|
|
367
|
+
const oidcClaims = core.buildSecondaryOidcClaims(oidcToken, secondaryClientIds);
|
|
368
|
+
await addOauthProvider({
|
|
369
|
+
providerName: resolvedProvider,
|
|
370
|
+
oidcToken,
|
|
371
|
+
...(oidcClaims.length > 0 && {
|
|
372
|
+
oidcClaims
|
|
373
|
+
}),
|
|
374
|
+
organizationId: metadata.organizationId,
|
|
375
|
+
userId: metadata.userId,
|
|
376
|
+
...(metadata.stampWith && {
|
|
377
|
+
stampWith: metadata.stampWith
|
|
378
|
+
})
|
|
379
|
+
});
|
|
380
|
+
} : undefined
|
|
381
|
+
});
|
|
382
|
+
};
|
|
383
|
+
await withModalWrapper({
|
|
384
|
+
provider: resolvedProvider,
|
|
385
|
+
isAddProvider,
|
|
386
|
+
metadata,
|
|
387
|
+
openModal: openModal ?? undefined,
|
|
388
|
+
action
|
|
350
389
|
});
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
openModal: openModal ?? undefined,
|
|
357
|
-
action
|
|
358
|
-
});
|
|
359
|
-
// Clean up the URL after processing
|
|
360
|
-
oauth.cleanupOAuthUrlPreserveSearch();
|
|
390
|
+
// Clean up the URL after processing
|
|
391
|
+
url.cleanupOAuthUrlPreserveSearch();
|
|
392
|
+
}
|
|
393
|
+
} finally {
|
|
394
|
+
storage.clearAllOAuthData();
|
|
361
395
|
}
|
|
362
396
|
};
|
|
363
397
|
const buildConfig = proxyAuthConfig => {
|
|
364
398
|
// Juggle the local overrides with the values set in the dashboard (proxyAuthConfig).
|
|
365
399
|
const resolvedMethods = {
|
|
366
|
-
emailOtpAuthEnabled: config.
|
|
367
|
-
smsOtpAuthEnabled: config.
|
|
368
|
-
passkeyAuthEnabled: config.
|
|
369
|
-
walletAuthEnabled: config.
|
|
370
|
-
googleOauthEnabled: config.
|
|
371
|
-
xOauthEnabled: config.
|
|
372
|
-
discordOauthEnabled: config.
|
|
373
|
-
appleOauthEnabled: config.
|
|
374
|
-
facebookOauthEnabled: config.
|
|
400
|
+
emailOtpAuthEnabled: config.ui?.authModal?.methods?.emailOtpAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("email"),
|
|
401
|
+
smsOtpAuthEnabled: config.ui?.authModal?.methods?.smsOtpAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("sms"),
|
|
402
|
+
passkeyAuthEnabled: config.ui?.authModal?.methods?.passkeyAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("passkey"),
|
|
403
|
+
walletAuthEnabled: config.ui?.authModal?.methods?.walletAuthEnabled ?? proxyAuthConfig?.enabledProviders.includes("wallet"),
|
|
404
|
+
googleOauthEnabled: config.ui?.authModal?.methods?.googleOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("google"),
|
|
405
|
+
xOauthEnabled: config.ui?.authModal?.methods?.xOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("x"),
|
|
406
|
+
discordOauthEnabled: config.ui?.authModal?.methods?.discordOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("discord"),
|
|
407
|
+
appleOauthEnabled: config.ui?.authModal?.methods?.appleOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("apple"),
|
|
408
|
+
facebookOauthEnabled: config.ui?.authModal?.methods?.facebookOauthEnabled ?? proxyAuthConfig?.enabledProviders.includes("facebook")
|
|
375
409
|
};
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
410
|
+
const resolvedOauthProviders = {
|
|
411
|
+
google: {
|
|
412
|
+
primaryClientId: config.auth?.oauthConfig?.google?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.google,
|
|
413
|
+
secondaryClientIds: config.auth?.oauthConfig?.google?.secondaryClientIds ?? []
|
|
414
|
+
},
|
|
415
|
+
apple: {
|
|
416
|
+
primaryClientId: config.auth?.oauthConfig?.apple?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.apple,
|
|
417
|
+
secondaryClientIds: config.auth?.oauthConfig?.apple?.secondaryClientIds ?? []
|
|
418
|
+
},
|
|
419
|
+
facebook: {
|
|
420
|
+
primaryClientId: config.auth?.oauthConfig?.facebook?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.facebook,
|
|
421
|
+
secondaryClientIds: config.auth?.oauthConfig?.facebook?.secondaryClientIds ?? []
|
|
422
|
+
},
|
|
423
|
+
x: {
|
|
424
|
+
primaryClientId: config.auth?.oauthConfig?.x?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.x,
|
|
425
|
+
secondaryClientIds: config.auth?.oauthConfig?.x?.secondaryClientIds ?? []
|
|
426
|
+
},
|
|
427
|
+
discord: {
|
|
428
|
+
primaryClientId: config.auth?.oauthConfig?.discord?.primaryClientId ?? proxyAuthConfig?.oauthClientIds?.discord,
|
|
429
|
+
secondaryClientIds: config.auth?.oauthConfig?.discord?.secondaryClientIds ?? []
|
|
430
|
+
}
|
|
382
431
|
};
|
|
383
432
|
const redirectUrl = config.auth?.oauthConfig?.oauthRedirectUri ?? proxyAuthConfig?.oauthRedirectUrl;
|
|
384
433
|
// Set a default ordering for the oAuth methods
|
|
385
|
-
const oauthOrder = config.
|
|
434
|
+
const oauthOrder = config.ui?.authModal?.oauthOrder ?? ["google", "apple", "x", "discord", "facebook"].filter(provider => resolvedMethods[`${provider}OauthEnabled`]);
|
|
386
435
|
// Set a default ordering for the overall auth methods
|
|
387
|
-
const methodOrder = config.
|
|
436
|
+
const methodOrder = config.ui?.authModal?.methodOrder ?? [oauthOrder.length > 0 ? "socials" : null, resolvedMethods.emailOtpAuthEnabled ? "email" : null, resolvedMethods.smsOtpAuthEnabled ? "sms" : null, resolvedMethods.passkeyAuthEnabled ? "passkey" : null, resolvedMethods.walletAuthEnabled ? "wallet" : null].filter(Boolean);
|
|
388
437
|
// Warn if they are trying to set auth proxy only settings directly
|
|
389
438
|
if (proxyAuthConfig) {
|
|
390
439
|
if (config.auth?.sessionExpirationSeconds) {
|
|
@@ -403,24 +452,33 @@ const ClientProvider = ({
|
|
|
403
452
|
otpAlphanumeric: proxyAuthConfig?.otpAlphanumeric ?? config.auth?.otpAlphanumeric ?? true,
|
|
404
453
|
otpLength: proxyAuthConfig?.otpLength ?? config.auth?.otpLength ?? "6"
|
|
405
454
|
};
|
|
455
|
+
const scopePasskeyToUser = config.auth?.scopePasskeyToUser ?? true;
|
|
406
456
|
return {
|
|
407
457
|
...config,
|
|
458
|
+
scopePasskeyToUser,
|
|
408
459
|
// Overrides:
|
|
409
460
|
auth: {
|
|
410
461
|
...config.auth,
|
|
411
462
|
...authProxyPrioSettings,
|
|
412
|
-
methods: resolvedMethods,
|
|
413
463
|
oauthConfig: {
|
|
414
464
|
...config.auth?.oauthConfig,
|
|
415
|
-
...
|
|
465
|
+
...resolvedOauthProviders,
|
|
416
466
|
oauthRedirectUri: redirectUrl,
|
|
417
467
|
// on mobile we default to true since many mobile browsers
|
|
418
468
|
// (e.g. Safari) block popups
|
|
419
469
|
openOauthInPage: isMobile ? true : config.auth?.oauthConfig?.openOauthInPage
|
|
420
470
|
},
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
471
|
+
autoRefreshSession: config.auth?.autoRefreshSession ?? true,
|
|
472
|
+
scopePasskeyToUser
|
|
473
|
+
},
|
|
474
|
+
ui: {
|
|
475
|
+
...config.ui,
|
|
476
|
+
authModal: {
|
|
477
|
+
...config.ui?.authModal,
|
|
478
|
+
methods: resolvedMethods,
|
|
479
|
+
methodOrder,
|
|
480
|
+
oauthOrder
|
|
481
|
+
}
|
|
424
482
|
},
|
|
425
483
|
autoRefreshManagedState: config.autoRefreshManagedState ?? true,
|
|
426
484
|
walletConfig: {
|
|
@@ -485,7 +543,8 @@ const ClientProvider = ({
|
|
|
485
543
|
walletConnect: masterConfig.walletConfig.walletConnect
|
|
486
544
|
})
|
|
487
545
|
},
|
|
488
|
-
defaultStamperType: masterConfig.defaultStamperType
|
|
546
|
+
defaultStamperType: masterConfig.defaultStamperType,
|
|
547
|
+
scopePasskeyToUser: masterConfig.scopePasskeyToUser ?? true
|
|
489
548
|
});
|
|
490
549
|
await turnkeyClient.init();
|
|
491
550
|
setClient(turnkeyClient);
|
|
@@ -538,7 +597,7 @@ const ClientProvider = ({
|
|
|
538
597
|
// specifically, if WalletConnect finishes initializing before this promise resolves,
|
|
539
598
|
// `maybeRefreshWallets()` could overwrite the WalletConnect wallet state with an outdated
|
|
540
599
|
// list of wallets that doesn’t yet include the WalletConnect wallets
|
|
541
|
-
const [, wallets] = await Promise.all([maybeRefreshUser(), (() => {
|
|
600
|
+
const [user, wallets] = await Promise.all([maybeRefreshUser(), (() => {
|
|
542
601
|
if (!masterConfig?.autoRefreshManagedState) return [];
|
|
543
602
|
return fetchWallets();
|
|
544
603
|
})()]);
|
|
@@ -546,6 +605,7 @@ const ClientProvider = ({
|
|
|
546
605
|
if (wallets) {
|
|
547
606
|
setWallets(prev => utils.mergeWalletsWithoutDuplicates(prev, wallets));
|
|
548
607
|
}
|
|
608
|
+
if (client) await core.applyPasskeyScope(client, client.config.passkeyConfig, user, masterConfig?.auth?.scopePasskeyToUser);
|
|
549
609
|
return;
|
|
550
610
|
}
|
|
551
611
|
} catch (error) {
|
|
@@ -733,7 +793,8 @@ const ClientProvider = ({
|
|
|
733
793
|
const allSessions = await client.getAllSessions();
|
|
734
794
|
setSession(session);
|
|
735
795
|
setAllSessions(allSessions);
|
|
736
|
-
await Promise.all([maybeRefreshWallets(), maybeRefreshUser()]);
|
|
796
|
+
const [, user] = await Promise.all([maybeRefreshWallets(), maybeRefreshUser()]);
|
|
797
|
+
if (client) await core.applyPasskeyScope(client, client.config.passkeyConfig, user, masterConfig?.auth?.scopePasskeyToUser);
|
|
737
798
|
if (masterConfig?.auth?.verifyWalletOnSignup === true && appProofs && appProofs.length > 0 && action === sdkTypes.AuthAction.SIGNUP) {
|
|
738
799
|
// On signup, if we have appProofs, verify them
|
|
739
800
|
await handleVerifyAppProofs({
|
|
@@ -767,9 +828,10 @@ const ClientProvider = ({
|
|
|
767
828
|
* @returns void
|
|
768
829
|
* @throws {TurnkeyError} If there is an error during the post-logout process.
|
|
769
830
|
*/
|
|
770
|
-
const handlePostLogout = sessionKey => {
|
|
831
|
+
const handlePostLogout = react.useCallback(async sessionKey => {
|
|
771
832
|
try {
|
|
772
|
-
|
|
833
|
+
const timeoutKeys = sessionKey ? [sessionKey, `${sessionKey}-warning`] : undefined;
|
|
834
|
+
clearSessionTimeouts(timeoutKeys);
|
|
773
835
|
setAllSessions(prev => {
|
|
774
836
|
if (!prev) return prev;
|
|
775
837
|
if (sessionKey) {
|
|
@@ -784,16 +846,29 @@ const ClientProvider = ({
|
|
|
784
846
|
setSession(undefined);
|
|
785
847
|
setUser(undefined);
|
|
786
848
|
setWallets([]);
|
|
849
|
+
if (client) await core.resetPasskeyScope(client, client.config.passkeyConfig);
|
|
787
850
|
} catch (error) {
|
|
788
|
-
callbacks?.onError?.(new sdkTypes.TurnkeyError(`Failed to
|
|
851
|
+
callbacks?.onError?.(new sdkTypes.TurnkeyError(`Failed to handle post logout`, sdkTypes.TurnkeyErrorCodes.HANDLE_POST_LOGOUT_ERROR, error));
|
|
789
852
|
}
|
|
790
|
-
};
|
|
853
|
+
}, [callbacks, clearSessionTimeouts, client, masterConfig?.passkeyConfig]);
|
|
791
854
|
const createHttpClient = react.useCallback(params => {
|
|
792
855
|
if (!client) {
|
|
793
856
|
throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
794
857
|
}
|
|
795
858
|
return client.createHttpClient(params);
|
|
796
859
|
}, [client]);
|
|
860
|
+
const overrideApiKeyStamper = react.useCallback(params => {
|
|
861
|
+
if (!client) {
|
|
862
|
+
throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
863
|
+
}
|
|
864
|
+
return client.overrideApiKeyStamper(params);
|
|
865
|
+
}, [client]);
|
|
866
|
+
const overridePasskeyStamper = react.useCallback(params => {
|
|
867
|
+
if (!client) {
|
|
868
|
+
throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
869
|
+
}
|
|
870
|
+
return client.overridePasskeyStamper(params);
|
|
871
|
+
}, [client]);
|
|
797
872
|
const getActiveSessionKey = react.useCallback(async () => {
|
|
798
873
|
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
799
874
|
return utils.withTurnkeyErrorHandling(() => client.getActiveSessionKey(), undefined, callbacks, "Failed to get active session key");
|
|
@@ -808,10 +883,10 @@ const ClientProvider = ({
|
|
|
808
883
|
if (!sessionKey) sessionKey = await getActiveSessionKey();
|
|
809
884
|
await client.logout(params);
|
|
810
885
|
// We only handle post logout if the sessionKey is defined since that means we actually logged out of a session.
|
|
811
|
-
if (sessionKey) handlePostLogout(sessionKey);
|
|
886
|
+
if (sessionKey) await handlePostLogout(sessionKey);
|
|
812
887
|
}, undefined, callbacks, "Failed to logout");
|
|
813
888
|
return;
|
|
814
|
-
}, [client, callbacks, getActiveSessionKey]);
|
|
889
|
+
}, [client, callbacks, getActiveSessionKey, handlePostLogout]);
|
|
815
890
|
const getSession = react.useCallback(async params => {
|
|
816
891
|
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
817
892
|
return utils.withTurnkeyErrorHandling(() => client.getSession(params), undefined, callbacks, "Failed to get session");
|
|
@@ -871,6 +946,7 @@ const ClientProvider = ({
|
|
|
871
946
|
if (user) {
|
|
872
947
|
setUser(user);
|
|
873
948
|
}
|
|
949
|
+
return user;
|
|
874
950
|
}, [client, callbacks, fetchUser, logout]);
|
|
875
951
|
/**
|
|
876
952
|
* @internal
|
|
@@ -882,7 +958,7 @@ const ClientProvider = ({
|
|
|
882
958
|
* @returns A promise that resolves when the user is refreshed, or does nothing if auto-refresh is disabled
|
|
883
959
|
*/
|
|
884
960
|
const maybeRefreshUser = react.useCallback(async params => {
|
|
885
|
-
if (!masterConfig?.autoRefreshManagedState) return;
|
|
961
|
+
if (!masterConfig?.autoRefreshManagedState) return undefined;
|
|
886
962
|
return refreshUser(params);
|
|
887
963
|
}, [masterConfig, refreshUser]);
|
|
888
964
|
const refreshWallets = react.useCallback(async params => {
|
|
@@ -923,11 +999,15 @@ const ClientProvider = ({
|
|
|
923
999
|
}, [masterConfig, refreshWallets]);
|
|
924
1000
|
const clearSession = react.useCallback(async params => {
|
|
925
1001
|
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1002
|
+
const activeSessionKey = await getActiveSessionKey();
|
|
926
1003
|
await utils.withTurnkeyErrorHandling(async () => client.clearSession(params), undefined, callbacks, "Failed to clear session");
|
|
927
|
-
const sessionKey = params?.sessionKey ??
|
|
1004
|
+
const sessionKey = params?.sessionKey ?? activeSessionKey;
|
|
928
1005
|
if (!sessionKey) return;
|
|
929
|
-
if (!params?.sessionKey) {
|
|
1006
|
+
if (!params?.sessionKey || params.sessionKey === activeSessionKey) {
|
|
930
1007
|
setSession(undefined);
|
|
1008
|
+
setUser(undefined);
|
|
1009
|
+
setWallets([]);
|
|
1010
|
+
if (client) await core.resetPasskeyScope(client, client.config.passkeyConfig);
|
|
931
1011
|
}
|
|
932
1012
|
clearSessionTimeouts([sessionKey]);
|
|
933
1013
|
// clear only the cleared session from allSessions
|
|
@@ -939,7 +1019,7 @@ const ClientProvider = ({
|
|
|
939
1019
|
}
|
|
940
1020
|
setAllSessions(newAllSessions);
|
|
941
1021
|
return;
|
|
942
|
-
}, [client, callbacks, getActiveSessionKey, allSessions]);
|
|
1022
|
+
}, [client, callbacks, getActiveSessionKey, allSessions, masterConfig?.passkeyConfig]);
|
|
943
1023
|
/**
|
|
944
1024
|
* @internal
|
|
945
1025
|
* Schedules a session expiration and warning timer for the given session key.
|
|
@@ -1609,17 +1689,20 @@ const ClientProvider = ({
|
|
|
1609
1689
|
const addPasskey = react.useCallback(async params => {
|
|
1610
1690
|
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1611
1691
|
const res = await utils.withTurnkeyErrorHandling(() => client.addPasskey(params), () => logout(), callbacks, "Failed to add passkey");
|
|
1612
|
-
if (res)
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
organizationId
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
userId
|
|
1619
|
-
|
|
1620
|
-
|
|
1692
|
+
if (res) {
|
|
1693
|
+
const updatedUser = await maybeRefreshUser({
|
|
1694
|
+
stampWith: params?.stampWith,
|
|
1695
|
+
...(params?.organizationId && {
|
|
1696
|
+
organizationId: params.organizationId
|
|
1697
|
+
}),
|
|
1698
|
+
...(params?.userId && {
|
|
1699
|
+
userId: params.userId
|
|
1700
|
+
})
|
|
1701
|
+
});
|
|
1702
|
+
await core.applyPasskeyScope(client, client.config.passkeyConfig, updatedUser, masterConfig?.auth?.scopePasskeyToUser);
|
|
1703
|
+
}
|
|
1621
1704
|
return res;
|
|
1622
|
-
}, [client, callbacks, logout, maybeRefreshUser]);
|
|
1705
|
+
}, [client, callbacks, logout, maybeRefreshUser, masterConfig?.passkeyConfig, masterConfig?.auth?.scopePasskeyToUser]);
|
|
1623
1706
|
const removePasskeys = react.useCallback(async params => {
|
|
1624
1707
|
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1625
1708
|
const res = await utils.withTurnkeyErrorHandling(() => client.removePasskeys(params), () => logout(), callbacks, "Failed to remove passkeys");
|
|
@@ -1727,15 +1810,20 @@ const ClientProvider = ({
|
|
|
1727
1810
|
const allSessions = await getAllSessions();
|
|
1728
1811
|
setSession(session);
|
|
1729
1812
|
setAllSessions(allSessions);
|
|
1730
|
-
await
|
|
1731
|
-
|
|
1813
|
+
const nextUser = await maybeRefreshUser();
|
|
1814
|
+
await maybeRefreshWallets();
|
|
1815
|
+
if (client) await core.applyPasskeyScope(client, client.config.passkeyConfig, nextUser, masterConfig?.auth?.scopePasskeyToUser);
|
|
1816
|
+
}, [client, callbacks, logout, getActiveSessionKey, getSession, scheduleSessionExpiration, getAllSessions, masterConfig?.passkeyConfig, masterConfig?.auth?.scopePasskeyToUser, maybeRefreshWallets, maybeRefreshUser]);
|
|
1732
1817
|
const clearAllSessions = react.useCallback(async () => {
|
|
1733
1818
|
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1734
1819
|
setSession(undefined);
|
|
1735
1820
|
setAllSessions(undefined);
|
|
1821
|
+
setUser(undefined);
|
|
1822
|
+
setWallets([]);
|
|
1736
1823
|
clearSessionTimeouts();
|
|
1737
|
-
|
|
1738
|
-
|
|
1824
|
+
await utils.withTurnkeyErrorHandling(() => client.clearAllSessions(), () => logout(), callbacks, "Failed to clear all sessions");
|
|
1825
|
+
await core.resetPasskeyScope(client, client.config.passkeyConfig);
|
|
1826
|
+
}, [client, callbacks, logout, clearSessionTimeouts, masterConfig?.passkeyConfig]);
|
|
1739
1827
|
const setActiveSession = react.useCallback(async params => {
|
|
1740
1828
|
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1741
1829
|
const session = await utils.withTurnkeyErrorHandling(() => client.getSession({
|
|
@@ -1748,10 +1836,12 @@ const ClientProvider = ({
|
|
|
1748
1836
|
await utils.withTurnkeyErrorHandling(() => client.setActiveSession(params), () => logout(), callbacks, "Failed to set active session");
|
|
1749
1837
|
setSession(session);
|
|
1750
1838
|
await utils.withTurnkeyErrorHandling(async () => {
|
|
1751
|
-
await
|
|
1839
|
+
const nextUser = await maybeRefreshUser();
|
|
1840
|
+
await maybeRefreshWallets();
|
|
1841
|
+
if (client) await core.applyPasskeyScope(client, client.config.passkeyConfig, nextUser, masterConfig?.auth?.scopePasskeyToUser);
|
|
1752
1842
|
}, () => logout(), callbacks, "Failed to refresh data after setting active session");
|
|
1753
1843
|
return;
|
|
1754
|
-
}, [client, callbacks, logout, getSession, maybeRefreshWallets, maybeRefreshUser]);
|
|
1844
|
+
}, [client, callbacks, logout, getSession, masterConfig?.passkeyConfig, masterConfig?.auth?.scopePasskeyToUser, maybeRefreshWallets, maybeRefreshUser]);
|
|
1755
1845
|
const clearUnusedKeyPairs = react.useCallback(async () => {
|
|
1756
1846
|
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1757
1847
|
return utils.withTurnkeyErrorHandling(() => client.clearUnusedKeyPairs(), undefined, callbacks, "Failed to clear unused key pairs");
|
|
@@ -1760,6 +1850,14 @@ const ClientProvider = ({
|
|
|
1760
1850
|
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1761
1851
|
return utils.withTurnkeyErrorHandling(() => client.createApiKeyPair(params), undefined, callbacks, "Failed to create API key pair");
|
|
1762
1852
|
}, [client, callbacks]);
|
|
1853
|
+
const deleteApiKeyPair = react.useCallback(async params => {
|
|
1854
|
+
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1855
|
+
return utils.withTurnkeyErrorHandling(() => client.deleteApiKeyPair(params), undefined, callbacks, "Failed to delete API key pair");
|
|
1856
|
+
}, [client, callbacks]);
|
|
1857
|
+
const signWithApiKey = react.useCallback(async params => {
|
|
1858
|
+
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1859
|
+
return utils.withTurnkeyErrorHandling(() => client.signWithApiKey(params), undefined, callbacks, "Failed to sign with API key");
|
|
1860
|
+
}, [client, callbacks]);
|
|
1763
1861
|
const getProxyAuthConfig = react.useCallback(async () => {
|
|
1764
1862
|
if (!client) throw new sdkTypes.TurnkeyError("Client is not initialized.", sdkTypes.TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
|
|
1765
1863
|
return utils.withTurnkeyErrorHandling(() => client.getProxyAuthConfig(), undefined, callbacks, "Failed to get proxy auth config");
|
|
@@ -1774,10 +1872,12 @@ const ClientProvider = ({
|
|
|
1774
1872
|
}, [client, callbacks, logout]);
|
|
1775
1873
|
const handleDiscordOauth = react.useCallback(async params => {
|
|
1776
1874
|
const {
|
|
1777
|
-
|
|
1875
|
+
primaryClientId = masterConfig?.auth?.oauthConfig?.discord?.primaryClientId,
|
|
1876
|
+
secondaryClientIds = masterConfig?.auth?.oauthConfig?.discord?.secondaryClientIds ?? [],
|
|
1778
1877
|
openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false,
|
|
1779
1878
|
additionalState: additionalParameters
|
|
1780
1879
|
} = params || {};
|
|
1880
|
+
const clientId = primaryClientId;
|
|
1781
1881
|
const provider = sdkTypes.OAuthProviders.DISCORD;
|
|
1782
1882
|
if (!masterConfig) {
|
|
1783
1883
|
throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
|
|
@@ -1800,10 +1900,10 @@ const ClientProvider = ({
|
|
|
1800
1900
|
const {
|
|
1801
1901
|
verifier,
|
|
1802
1902
|
codeChallenge
|
|
1803
|
-
} = await
|
|
1804
|
-
|
|
1903
|
+
} = await pkce.generateChallengePair();
|
|
1904
|
+
storage.storePKCEVerifier(provider, verifier);
|
|
1805
1905
|
// Build OAuth URL
|
|
1806
|
-
const authUrl =
|
|
1906
|
+
const authUrl = url.buildOAuthUrl({
|
|
1807
1907
|
provider,
|
|
1808
1908
|
clientId,
|
|
1809
1909
|
redirectUri,
|
|
@@ -1815,12 +1915,12 @@ const ClientProvider = ({
|
|
|
1815
1915
|
});
|
|
1816
1916
|
if (openInPage) {
|
|
1817
1917
|
// Remainder of logic will occur in completeRedirectOauth
|
|
1818
|
-
return
|
|
1918
|
+
return url.redirectToOAuthProvider(authUrl);
|
|
1819
1919
|
}
|
|
1820
1920
|
// Popup flow
|
|
1821
|
-
const authWindow =
|
|
1921
|
+
const authWindow = url.openOAuthPopup();
|
|
1822
1922
|
if (!authWindow) {
|
|
1823
|
-
throw new Error(`Failed to open ${
|
|
1923
|
+
throw new Error(`Failed to open ${helpers.capitalizeProviderName(provider)} login window.`);
|
|
1824
1924
|
}
|
|
1825
1925
|
authWindow.location.href = authUrl;
|
|
1826
1926
|
return new Promise((resolve, reject) => {
|
|
@@ -1831,18 +1931,30 @@ const ClientProvider = ({
|
|
|
1831
1931
|
reject(new Error("Authentication window was closed."));
|
|
1832
1932
|
return;
|
|
1833
1933
|
}
|
|
1834
|
-
const url = authWindow.location.href || "";
|
|
1835
|
-
if (url.startsWith(window.location.origin)) {
|
|
1836
|
-
const result =
|
|
1934
|
+
const url$1 = authWindow.location.href || "";
|
|
1935
|
+
if (url$1.startsWith(window.location.origin)) {
|
|
1936
|
+
const result = url.parseOAuthResponse(url$1, provider);
|
|
1837
1937
|
if (result) {
|
|
1838
1938
|
authWindow.close();
|
|
1839
1939
|
clearInterval(interval);
|
|
1840
|
-
|
|
1940
|
+
completion.completeOAuthPopup({
|
|
1841
1941
|
provider,
|
|
1842
1942
|
publicKey,
|
|
1843
1943
|
result,
|
|
1844
1944
|
callbacks,
|
|
1845
|
-
completeOauth
|
|
1945
|
+
completeOauth: completionParams => {
|
|
1946
|
+
const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
|
|
1947
|
+
const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? provider, secondaryClientIds);
|
|
1948
|
+
return completeOauth({
|
|
1949
|
+
...completionParams,
|
|
1950
|
+
...(secondaryProviders.length > 0 && {
|
|
1951
|
+
createSubOrgParams: {
|
|
1952
|
+
...existingCreateSubOrgParams,
|
|
1953
|
+
oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
|
|
1954
|
+
}
|
|
1955
|
+
})
|
|
1956
|
+
});
|
|
1957
|
+
},
|
|
1846
1958
|
onOauthSuccess: params?.onOauthSuccess,
|
|
1847
1959
|
exchangeCodeForToken: async codeVerifier => {
|
|
1848
1960
|
const resp = await client?.httpClient.proxyOAuth2Authenticate({
|
|
@@ -1869,10 +1981,12 @@ const ClientProvider = ({
|
|
|
1869
1981
|
}, [client, callbacks, completeOauth, createApiKeyPair, masterConfig]);
|
|
1870
1982
|
const handleXOauth = react.useCallback(async params => {
|
|
1871
1983
|
const {
|
|
1872
|
-
|
|
1984
|
+
primaryClientId = masterConfig?.auth?.oauthConfig?.x?.primaryClientId,
|
|
1985
|
+
secondaryClientIds = masterConfig?.auth?.oauthConfig?.x?.secondaryClientIds ?? [],
|
|
1873
1986
|
openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false,
|
|
1874
1987
|
additionalState: additionalParameters
|
|
1875
1988
|
} = params || {};
|
|
1989
|
+
const clientId = primaryClientId;
|
|
1876
1990
|
const provider = sdkTypes.OAuthProviders.X;
|
|
1877
1991
|
if (!masterConfig) {
|
|
1878
1992
|
throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
|
|
@@ -1895,10 +2009,10 @@ const ClientProvider = ({
|
|
|
1895
2009
|
const {
|
|
1896
2010
|
verifier,
|
|
1897
2011
|
codeChallenge
|
|
1898
|
-
} = await
|
|
1899
|
-
|
|
2012
|
+
} = await pkce.generateChallengePair();
|
|
2013
|
+
storage.storePKCEVerifier(provider, verifier);
|
|
1900
2014
|
// Build OAuth URL
|
|
1901
|
-
const authUrl =
|
|
2015
|
+
const authUrl = url.buildOAuthUrl({
|
|
1902
2016
|
provider,
|
|
1903
2017
|
clientId,
|
|
1904
2018
|
redirectUri,
|
|
@@ -1910,12 +2024,12 @@ const ClientProvider = ({
|
|
|
1910
2024
|
});
|
|
1911
2025
|
if (openInPage) {
|
|
1912
2026
|
// Remainder of logic will occur in completeRedirectOauth
|
|
1913
|
-
return
|
|
2027
|
+
return url.redirectToOAuthProvider(authUrl);
|
|
1914
2028
|
}
|
|
1915
2029
|
// Popup flow
|
|
1916
|
-
const authWindow =
|
|
2030
|
+
const authWindow = url.openOAuthPopup();
|
|
1917
2031
|
if (!authWindow) {
|
|
1918
|
-
throw new Error(`Failed to open ${
|
|
2032
|
+
throw new Error(`Failed to open ${helpers.capitalizeProviderName(provider)} login window.`);
|
|
1919
2033
|
}
|
|
1920
2034
|
authWindow.location.href = authUrl;
|
|
1921
2035
|
return new Promise((resolve, reject) => {
|
|
@@ -1926,18 +2040,30 @@ const ClientProvider = ({
|
|
|
1926
2040
|
reject(new Error("Authentication window was closed."));
|
|
1927
2041
|
return;
|
|
1928
2042
|
}
|
|
1929
|
-
const url = authWindow.location.href || "";
|
|
1930
|
-
if (url.startsWith(window.location.origin)) {
|
|
1931
|
-
const result =
|
|
2043
|
+
const url$1 = authWindow.location.href || "";
|
|
2044
|
+
if (url$1.startsWith(window.location.origin)) {
|
|
2045
|
+
const result = url.parseOAuthResponse(url$1, provider);
|
|
1932
2046
|
if (result) {
|
|
1933
2047
|
authWindow.close();
|
|
1934
2048
|
clearInterval(interval);
|
|
1935
|
-
|
|
2049
|
+
completion.completeOAuthPopup({
|
|
1936
2050
|
provider,
|
|
1937
2051
|
publicKey,
|
|
1938
2052
|
result,
|
|
1939
2053
|
callbacks,
|
|
1940
|
-
completeOauth
|
|
2054
|
+
completeOauth: completionParams => {
|
|
2055
|
+
const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
|
|
2056
|
+
const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? provider, secondaryClientIds);
|
|
2057
|
+
return completeOauth({
|
|
2058
|
+
...completionParams,
|
|
2059
|
+
...(secondaryProviders.length > 0 && {
|
|
2060
|
+
createSubOrgParams: {
|
|
2061
|
+
...existingCreateSubOrgParams,
|
|
2062
|
+
oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
|
|
2063
|
+
}
|
|
2064
|
+
})
|
|
2065
|
+
});
|
|
2066
|
+
},
|
|
1941
2067
|
onOauthSuccess: params?.onOauthSuccess,
|
|
1942
2068
|
exchangeCodeForToken: async codeVerifier => {
|
|
1943
2069
|
const resp = await client?.httpClient.proxyOAuth2Authenticate({
|
|
@@ -1964,10 +2090,12 @@ const ClientProvider = ({
|
|
|
1964
2090
|
}, [client, callbacks, completeOauth, createApiKeyPair, masterConfig]);
|
|
1965
2091
|
const handleGoogleOauth = react.useCallback(async params => {
|
|
1966
2092
|
const {
|
|
1967
|
-
|
|
2093
|
+
primaryClientId = masterConfig?.auth?.oauthConfig?.google?.primaryClientId,
|
|
2094
|
+
secondaryClientIds = masterConfig?.auth?.oauthConfig?.google?.secondaryClientIds ?? [],
|
|
1968
2095
|
openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false,
|
|
1969
2096
|
additionalState: additionalParameters
|
|
1970
2097
|
} = params || {};
|
|
2098
|
+
const clientId = primaryClientId;
|
|
1971
2099
|
const provider = sdkTypes.OAuthProviders.GOOGLE;
|
|
1972
2100
|
if (!masterConfig) {
|
|
1973
2101
|
throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
|
|
@@ -1988,7 +2116,7 @@ const ClientProvider = ({
|
|
|
1988
2116
|
}
|
|
1989
2117
|
const nonce = utils$1.bytesToHex(sha2.sha256(publicKey));
|
|
1990
2118
|
// Build OAuth URL
|
|
1991
|
-
const authUrl =
|
|
2119
|
+
const authUrl = url.buildOAuthUrl({
|
|
1992
2120
|
provider,
|
|
1993
2121
|
clientId,
|
|
1994
2122
|
redirectUri,
|
|
@@ -1999,12 +2127,12 @@ const ClientProvider = ({
|
|
|
1999
2127
|
});
|
|
2000
2128
|
if (openInPage) {
|
|
2001
2129
|
// Remainder of logic will occur in completeRedirectOauth
|
|
2002
|
-
return
|
|
2130
|
+
return url.redirectToOAuthProvider(authUrl);
|
|
2003
2131
|
}
|
|
2004
2132
|
// Popup flow
|
|
2005
|
-
const authWindow =
|
|
2133
|
+
const authWindow = url.openOAuthPopup();
|
|
2006
2134
|
if (!authWindow) {
|
|
2007
|
-
throw new Error(`Failed to open ${
|
|
2135
|
+
throw new Error(`Failed to open ${helpers.capitalizeProviderName(provider)} login window.`);
|
|
2008
2136
|
}
|
|
2009
2137
|
authWindow.location.href = authUrl;
|
|
2010
2138
|
return new Promise((resolve, reject) => {
|
|
@@ -2015,18 +2143,30 @@ const ClientProvider = ({
|
|
|
2015
2143
|
reject(new Error("Authentication window was closed."));
|
|
2016
2144
|
return;
|
|
2017
2145
|
}
|
|
2018
|
-
const url = authWindow.location.href || "";
|
|
2019
|
-
if (url.startsWith(window.location.origin)) {
|
|
2020
|
-
const result =
|
|
2146
|
+
const url$1 = authWindow.location.href || "";
|
|
2147
|
+
if (url$1.startsWith(window.location.origin)) {
|
|
2148
|
+
const result = url.parseOAuthResponse(url$1, provider);
|
|
2021
2149
|
if (result) {
|
|
2022
2150
|
authWindow.close();
|
|
2023
2151
|
clearInterval(interval);
|
|
2024
|
-
|
|
2152
|
+
completion.completeOAuthPopup({
|
|
2025
2153
|
provider,
|
|
2026
2154
|
publicKey,
|
|
2027
2155
|
result,
|
|
2028
2156
|
callbacks,
|
|
2029
|
-
completeOauth
|
|
2157
|
+
completeOauth: completionParams => {
|
|
2158
|
+
const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
|
|
2159
|
+
const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? provider, secondaryClientIds);
|
|
2160
|
+
return completeOauth({
|
|
2161
|
+
...completionParams,
|
|
2162
|
+
...(secondaryProviders.length > 0 && {
|
|
2163
|
+
createSubOrgParams: {
|
|
2164
|
+
...existingCreateSubOrgParams,
|
|
2165
|
+
oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
|
|
2166
|
+
}
|
|
2167
|
+
})
|
|
2168
|
+
});
|
|
2169
|
+
},
|
|
2030
2170
|
onOauthSuccess: params?.onOauthSuccess
|
|
2031
2171
|
}).then(() => resolve()).catch(reject);
|
|
2032
2172
|
}
|
|
@@ -2042,10 +2182,12 @@ const ClientProvider = ({
|
|
|
2042
2182
|
}, [callbacks, completeOauth, createApiKeyPair, masterConfig]);
|
|
2043
2183
|
const handleAppleOauth = react.useCallback(async params => {
|
|
2044
2184
|
const {
|
|
2045
|
-
|
|
2185
|
+
primaryClientId = masterConfig?.auth?.oauthConfig?.apple?.primaryClientId,
|
|
2186
|
+
secondaryClientIds = masterConfig?.auth?.oauthConfig?.apple?.secondaryClientIds ?? [],
|
|
2046
2187
|
openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false,
|
|
2047
2188
|
additionalState: additionalParameters
|
|
2048
2189
|
} = params || {};
|
|
2190
|
+
const clientId = primaryClientId;
|
|
2049
2191
|
const provider = sdkTypes.OAuthProviders.APPLE;
|
|
2050
2192
|
if (!masterConfig) {
|
|
2051
2193
|
throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
|
|
@@ -2066,7 +2208,7 @@ const ClientProvider = ({
|
|
|
2066
2208
|
}
|
|
2067
2209
|
const nonce = utils$1.bytesToHex(sha2.sha256(publicKey));
|
|
2068
2210
|
// Build OAuth URL
|
|
2069
|
-
const authUrl =
|
|
2211
|
+
const authUrl = url.buildOAuthUrl({
|
|
2070
2212
|
provider,
|
|
2071
2213
|
clientId,
|
|
2072
2214
|
redirectUri,
|
|
@@ -2077,12 +2219,12 @@ const ClientProvider = ({
|
|
|
2077
2219
|
});
|
|
2078
2220
|
if (openInPage) {
|
|
2079
2221
|
// Remainder of logic will occur in completeRedirectOauth
|
|
2080
|
-
return
|
|
2222
|
+
return url.redirectToOAuthProvider(authUrl);
|
|
2081
2223
|
}
|
|
2082
2224
|
// Popup flow
|
|
2083
|
-
const authWindow =
|
|
2225
|
+
const authWindow = url.openOAuthPopup();
|
|
2084
2226
|
if (!authWindow) {
|
|
2085
|
-
throw new Error(`Failed to open ${
|
|
2227
|
+
throw new Error(`Failed to open ${helpers.capitalizeProviderName(provider)} login window.`);
|
|
2086
2228
|
}
|
|
2087
2229
|
authWindow.location.href = authUrl;
|
|
2088
2230
|
return new Promise((resolve, reject) => {
|
|
@@ -2093,18 +2235,30 @@ const ClientProvider = ({
|
|
|
2093
2235
|
reject(new Error("Authentication window was closed."));
|
|
2094
2236
|
return;
|
|
2095
2237
|
}
|
|
2096
|
-
const url = authWindow.location.href || "";
|
|
2097
|
-
if (url.startsWith(window.location.origin)) {
|
|
2098
|
-
const result =
|
|
2238
|
+
const url$1 = authWindow.location.href || "";
|
|
2239
|
+
if (url$1.startsWith(window.location.origin)) {
|
|
2240
|
+
const result = url.parseOAuthResponse(url$1, provider);
|
|
2099
2241
|
if (result) {
|
|
2100
2242
|
authWindow.close();
|
|
2101
2243
|
clearInterval(interval);
|
|
2102
|
-
|
|
2244
|
+
completion.completeOAuthPopup({
|
|
2103
2245
|
provider,
|
|
2104
2246
|
publicKey,
|
|
2105
2247
|
result,
|
|
2106
2248
|
callbacks,
|
|
2107
|
-
completeOauth
|
|
2249
|
+
completeOauth: completionParams => {
|
|
2250
|
+
const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
|
|
2251
|
+
const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? provider, secondaryClientIds);
|
|
2252
|
+
return completeOauth({
|
|
2253
|
+
...completionParams,
|
|
2254
|
+
...(secondaryProviders.length > 0 && {
|
|
2255
|
+
createSubOrgParams: {
|
|
2256
|
+
...existingCreateSubOrgParams,
|
|
2257
|
+
oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
|
|
2258
|
+
}
|
|
2259
|
+
})
|
|
2260
|
+
});
|
|
2261
|
+
},
|
|
2108
2262
|
onOauthSuccess: params?.onOauthSuccess
|
|
2109
2263
|
}).then(() => resolve()).catch(reject);
|
|
2110
2264
|
}
|
|
@@ -2120,10 +2274,12 @@ const ClientProvider = ({
|
|
|
2120
2274
|
}, [callbacks, completeOauth, createApiKeyPair, masterConfig]);
|
|
2121
2275
|
const handleFacebookOauth = react.useCallback(async params => {
|
|
2122
2276
|
const {
|
|
2123
|
-
|
|
2277
|
+
primaryClientId = masterConfig?.auth?.oauthConfig?.facebook?.primaryClientId,
|
|
2278
|
+
secondaryClientIds = masterConfig?.auth?.oauthConfig?.facebook?.secondaryClientIds ?? [],
|
|
2124
2279
|
openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false,
|
|
2125
2280
|
additionalState: additionalParameters
|
|
2126
2281
|
} = params || {};
|
|
2282
|
+
const clientId = primaryClientId;
|
|
2127
2283
|
const provider = sdkTypes.OAuthProviders.FACEBOOK;
|
|
2128
2284
|
if (!masterConfig) {
|
|
2129
2285
|
throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.INVALID_CONFIGURATION);
|
|
@@ -2146,10 +2302,10 @@ const ClientProvider = ({
|
|
|
2146
2302
|
const {
|
|
2147
2303
|
verifier,
|
|
2148
2304
|
codeChallenge
|
|
2149
|
-
} = await
|
|
2150
|
-
|
|
2305
|
+
} = await pkce.generateChallengePair();
|
|
2306
|
+
storage.storePKCEVerifier(provider, verifier);
|
|
2151
2307
|
// Build OAuth URL
|
|
2152
|
-
const authUrl =
|
|
2308
|
+
const authUrl = url.buildOAuthUrl({
|
|
2153
2309
|
provider,
|
|
2154
2310
|
clientId,
|
|
2155
2311
|
redirectUri,
|
|
@@ -2161,12 +2317,12 @@ const ClientProvider = ({
|
|
|
2161
2317
|
});
|
|
2162
2318
|
if (openInPage) {
|
|
2163
2319
|
// Remainder of logic will occur in completeRedirectOauth
|
|
2164
|
-
return
|
|
2320
|
+
return url.redirectToOAuthProvider(authUrl);
|
|
2165
2321
|
}
|
|
2166
2322
|
// Popup flow
|
|
2167
|
-
const authWindow =
|
|
2323
|
+
const authWindow = url.openOAuthPopup();
|
|
2168
2324
|
if (!authWindow) {
|
|
2169
|
-
throw new Error(`Failed to open ${
|
|
2325
|
+
throw new Error(`Failed to open ${helpers.capitalizeProviderName(provider)} login window.`);
|
|
2170
2326
|
}
|
|
2171
2327
|
authWindow.location.href = authUrl;
|
|
2172
2328
|
return new Promise((resolve, reject) => {
|
|
@@ -2177,21 +2333,33 @@ const ClientProvider = ({
|
|
|
2177
2333
|
reject(new Error("Authentication window was closed."));
|
|
2178
2334
|
return;
|
|
2179
2335
|
}
|
|
2180
|
-
const url = authWindow.location.href || "";
|
|
2181
|
-
if (url.startsWith(window.location.origin)) {
|
|
2182
|
-
const result =
|
|
2336
|
+
const url$1 = authWindow.location.href || "";
|
|
2337
|
+
if (url$1.startsWith(window.location.origin)) {
|
|
2338
|
+
const result = url.parseOAuthResponse(url$1, provider);
|
|
2183
2339
|
if (result) {
|
|
2184
2340
|
authWindow.close();
|
|
2185
2341
|
clearInterval(interval);
|
|
2186
|
-
|
|
2342
|
+
completion.completeOAuthPopup({
|
|
2187
2343
|
provider,
|
|
2188
2344
|
publicKey,
|
|
2189
2345
|
result,
|
|
2190
2346
|
callbacks,
|
|
2191
|
-
completeOauth
|
|
2347
|
+
completeOauth: completionParams => {
|
|
2348
|
+
const existingCreateSubOrgParams = masterConfig?.auth?.createSuborgParams?.oauth;
|
|
2349
|
+
const secondaryProviders = core.buildSecondaryOauthProviders(completionParams.oidcToken, completionParams.providerName ?? provider, secondaryClientIds);
|
|
2350
|
+
return completeOauth({
|
|
2351
|
+
...completionParams,
|
|
2352
|
+
...(secondaryProviders.length > 0 && {
|
|
2353
|
+
createSubOrgParams: {
|
|
2354
|
+
...existingCreateSubOrgParams,
|
|
2355
|
+
oauthProviders: [...(existingCreateSubOrgParams?.oauthProviders ?? []), ...secondaryProviders]
|
|
2356
|
+
}
|
|
2357
|
+
})
|
|
2358
|
+
});
|
|
2359
|
+
},
|
|
2192
2360
|
onOauthSuccess: params?.onOauthSuccess,
|
|
2193
2361
|
exchangeCodeForToken: async codeVerifier => {
|
|
2194
|
-
const tokenData = await
|
|
2362
|
+
const tokenData = await pkce.exchangeFacebookCodeForToken(clientId, redirectUri, result.authCode, codeVerifier);
|
|
2195
2363
|
return tokenData.id_token;
|
|
2196
2364
|
}
|
|
2197
2365
|
}).then(() => resolve()).catch(reject);
|
|
@@ -2492,9 +2660,6 @@ const ClientProvider = ({
|
|
|
2492
2660
|
if (!masterConfig) {
|
|
2493
2661
|
throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.CONFIG_NOT_INITIALIZED);
|
|
2494
2662
|
}
|
|
2495
|
-
if (!masterConfig.auth?.methods?.smsOtpAuthEnabled) {
|
|
2496
|
-
throw new sdkTypes.TurnkeyError("SMS OTP authentication is not enabled in the configuration.", sdkTypes.TurnkeyErrorCodes.AUTH_METHOD_NOT_ENABLED);
|
|
2497
|
-
}
|
|
2498
2663
|
const s = await getSession();
|
|
2499
2664
|
const organizationId = params?.organizationId || s?.organizationId;
|
|
2500
2665
|
if (!organizationId) {
|
|
@@ -2544,7 +2709,10 @@ const ClientProvider = ({
|
|
|
2544
2709
|
});
|
|
2545
2710
|
}), () => logout());
|
|
2546
2711
|
} else {
|
|
2547
|
-
const
|
|
2712
|
+
const {
|
|
2713
|
+
otpId,
|
|
2714
|
+
otpEncryptionTargetBundle
|
|
2715
|
+
} = await initOtp({
|
|
2548
2716
|
otpType: core.OtpType.Sms,
|
|
2549
2717
|
contact: params.phoneNumber
|
|
2550
2718
|
});
|
|
@@ -2555,6 +2723,7 @@ const ClientProvider = ({
|
|
|
2555
2723
|
otpType: core.OtpType.Sms,
|
|
2556
2724
|
contact: params.phoneNumber,
|
|
2557
2725
|
otpId: otpId,
|
|
2726
|
+
otpEncryptionTargetBundle: otpEncryptionTargetBundle,
|
|
2558
2727
|
otpLength: masterConfig.auth?.otpLength !== undefined ? Number(masterConfig.auth.otpLength) : undefined,
|
|
2559
2728
|
alphanumeric: masterConfig.auth?.otpAlphanumeric,
|
|
2560
2729
|
onContinue: async otpCode => {
|
|
@@ -2564,8 +2733,7 @@ const ClientProvider = ({
|
|
|
2564
2733
|
} = await verifyOtp({
|
|
2565
2734
|
otpId,
|
|
2566
2735
|
otpCode,
|
|
2567
|
-
|
|
2568
|
-
otpType: core.OtpType.Sms
|
|
2736
|
+
otpEncryptionTargetBundle
|
|
2569
2737
|
});
|
|
2570
2738
|
const res = await updateUserPhoneNumber({
|
|
2571
2739
|
phoneNumber: params.phoneNumber,
|
|
@@ -2662,7 +2830,10 @@ const ClientProvider = ({
|
|
|
2662
2830
|
});
|
|
2663
2831
|
}), () => logout());
|
|
2664
2832
|
} else {
|
|
2665
|
-
const
|
|
2833
|
+
const {
|
|
2834
|
+
otpId,
|
|
2835
|
+
otpEncryptionTargetBundle
|
|
2836
|
+
} = await initOtp({
|
|
2666
2837
|
otpType: core.OtpType.Email,
|
|
2667
2838
|
contact: params.email
|
|
2668
2839
|
});
|
|
@@ -2673,6 +2844,7 @@ const ClientProvider = ({
|
|
|
2673
2844
|
otpType: core.OtpType.Email,
|
|
2674
2845
|
contact: params.email,
|
|
2675
2846
|
otpId: otpId,
|
|
2847
|
+
otpEncryptionTargetBundle: otpEncryptionTargetBundle,
|
|
2676
2848
|
otpLength: masterConfig?.auth?.otpLength !== undefined ? Number(masterConfig.auth.otpLength) : undefined,
|
|
2677
2849
|
alphanumeric: masterConfig?.auth?.otpAlphanumeric,
|
|
2678
2850
|
onContinue: async otpCode => {
|
|
@@ -2682,8 +2854,7 @@ const ClientProvider = ({
|
|
|
2682
2854
|
} = await verifyOtp({
|
|
2683
2855
|
otpId,
|
|
2684
2856
|
otpCode,
|
|
2685
|
-
|
|
2686
|
-
otpType: core.OtpType.Email
|
|
2857
|
+
otpEncryptionTargetBundle
|
|
2687
2858
|
});
|
|
2688
2859
|
const res = await updateUserEmail({
|
|
2689
2860
|
email: params.email,
|
|
@@ -2777,7 +2948,10 @@ const ClientProvider = ({
|
|
|
2777
2948
|
});
|
|
2778
2949
|
}), () => logout());
|
|
2779
2950
|
} else {
|
|
2780
|
-
const
|
|
2951
|
+
const {
|
|
2952
|
+
otpId,
|
|
2953
|
+
otpEncryptionTargetBundle
|
|
2954
|
+
} = await initOtp({
|
|
2781
2955
|
otpType: core.OtpType.Email,
|
|
2782
2956
|
contact: params.email
|
|
2783
2957
|
});
|
|
@@ -2788,6 +2962,7 @@ const ClientProvider = ({
|
|
|
2788
2962
|
otpType: core.OtpType.Email,
|
|
2789
2963
|
contact: params.email,
|
|
2790
2964
|
otpId: otpId,
|
|
2965
|
+
otpEncryptionTargetBundle: otpEncryptionTargetBundle,
|
|
2791
2966
|
otpLength: masterConfig?.auth?.otpLength !== undefined ? Number(masterConfig.auth.otpLength) : undefined,
|
|
2792
2967
|
alphanumeric: masterConfig?.auth?.otpAlphanumeric,
|
|
2793
2968
|
onContinue: async otpCode => {
|
|
@@ -2797,8 +2972,7 @@ const ClientProvider = ({
|
|
|
2797
2972
|
} = await verifyOtp({
|
|
2798
2973
|
otpId,
|
|
2799
2974
|
otpCode,
|
|
2800
|
-
|
|
2801
|
-
otpType: core.OtpType.Email
|
|
2975
|
+
otpEncryptionTargetBundle
|
|
2802
2976
|
});
|
|
2803
2977
|
const res = await updateUserEmail({
|
|
2804
2978
|
email: params.email,
|
|
@@ -2842,9 +3016,6 @@ const ClientProvider = ({
|
|
|
2842
3016
|
if (!masterConfig) {
|
|
2843
3017
|
throw new sdkTypes.TurnkeyError("Config is not ready yet!", sdkTypes.TurnkeyErrorCodes.CONFIG_NOT_INITIALIZED);
|
|
2844
3018
|
}
|
|
2845
|
-
if (!masterConfig.auth?.methods?.smsOtpAuthEnabled) {
|
|
2846
|
-
throw new sdkTypes.TurnkeyError("SMS OTP authentication is not enabled in the configuration.", sdkTypes.TurnkeyErrorCodes.AUTH_METHOD_NOT_ENABLED);
|
|
2847
|
-
}
|
|
2848
3019
|
const s = await getSession();
|
|
2849
3020
|
const organizationId = params?.organizationId || s?.organizationId;
|
|
2850
3021
|
if (!organizationId) {
|
|
@@ -2896,7 +3067,10 @@ const ClientProvider = ({
|
|
|
2896
3067
|
});
|
|
2897
3068
|
}), () => logout(), callbacks, "Failed to add phone number");
|
|
2898
3069
|
} else {
|
|
2899
|
-
const
|
|
3070
|
+
const {
|
|
3071
|
+
otpId,
|
|
3072
|
+
otpEncryptionTargetBundle
|
|
3073
|
+
} = await initOtp({
|
|
2900
3074
|
otpType: core.OtpType.Sms,
|
|
2901
3075
|
contact: params.phoneNumber
|
|
2902
3076
|
});
|
|
@@ -2907,6 +3081,7 @@ const ClientProvider = ({
|
|
|
2907
3081
|
otpType: core.OtpType.Sms,
|
|
2908
3082
|
contact: params.phoneNumber,
|
|
2909
3083
|
otpId: otpId,
|
|
3084
|
+
otpEncryptionTargetBundle: otpEncryptionTargetBundle,
|
|
2910
3085
|
otpLength: masterConfig.auth?.otpLength !== undefined ? Number(masterConfig.auth.otpLength) : undefined,
|
|
2911
3086
|
alphanumeric: masterConfig?.auth?.otpAlphanumeric,
|
|
2912
3087
|
onContinue: async otpCode => {
|
|
@@ -2916,8 +3091,7 @@ const ClientProvider = ({
|
|
|
2916
3091
|
} = await verifyOtp({
|
|
2917
3092
|
otpId,
|
|
2918
3093
|
otpCode,
|
|
2919
|
-
|
|
2920
|
-
otpType: core.OtpType.Sms
|
|
3094
|
+
otpEncryptionTargetBundle
|
|
2921
3095
|
});
|
|
2922
3096
|
const res = await updateUserPhoneNumber({
|
|
2923
3097
|
phoneNumber: params.phoneNumber,
|
|
@@ -3110,6 +3284,29 @@ const ClientProvider = ({
|
|
|
3110
3284
|
successPageDuration = 2000,
|
|
3111
3285
|
openInPage = masterConfig?.auth?.oauthConfig?.openOauthInPage ?? false
|
|
3112
3286
|
} = params;
|
|
3287
|
+
// Resolve the provider's per-provider config, then apply per-call overrides.
|
|
3288
|
+
let providerConfig;
|
|
3289
|
+
switch (providerName) {
|
|
3290
|
+
case sdkTypes.OAuthProviders.DISCORD:
|
|
3291
|
+
providerConfig = masterConfig?.auth?.oauthConfig?.discord;
|
|
3292
|
+
break;
|
|
3293
|
+
case sdkTypes.OAuthProviders.X:
|
|
3294
|
+
providerConfig = masterConfig?.auth?.oauthConfig?.x;
|
|
3295
|
+
break;
|
|
3296
|
+
case sdkTypes.OAuthProviders.GOOGLE:
|
|
3297
|
+
providerConfig = masterConfig?.auth?.oauthConfig?.google;
|
|
3298
|
+
break;
|
|
3299
|
+
case sdkTypes.OAuthProviders.APPLE:
|
|
3300
|
+
providerConfig = masterConfig?.auth?.oauthConfig?.apple;
|
|
3301
|
+
break;
|
|
3302
|
+
case sdkTypes.OAuthProviders.FACEBOOK:
|
|
3303
|
+
providerConfig = masterConfig?.auth?.oauthConfig?.facebook;
|
|
3304
|
+
break;
|
|
3305
|
+
default:
|
|
3306
|
+
providerConfig = undefined;
|
|
3307
|
+
}
|
|
3308
|
+
const primaryClientId = params.primaryClientId ?? providerConfig?.primaryClientId;
|
|
3309
|
+
const secondaryClientIds = params.secondaryClientIds ?? providerConfig?.secondaryClientIds ?? [];
|
|
3113
3310
|
const s = await getSession();
|
|
3114
3311
|
const organizationId = params?.organizationId || s?.organizationId;
|
|
3115
3312
|
if (!organizationId) {
|
|
@@ -3122,9 +3319,13 @@ const ClientProvider = ({
|
|
|
3122
3319
|
return new Promise(async (resolve, reject) => {
|
|
3123
3320
|
try {
|
|
3124
3321
|
const onOauthSuccess = async params => {
|
|
3322
|
+
const oidcClaims = core.buildSecondaryOidcClaims(params.oidcToken, secondaryClientIds);
|
|
3125
3323
|
await addOauthProvider({
|
|
3126
3324
|
providerName: params.providerName,
|
|
3127
3325
|
oidcToken: params.oidcToken,
|
|
3326
|
+
...(oidcClaims.length > 0 && {
|
|
3327
|
+
oidcClaims
|
|
3328
|
+
}),
|
|
3128
3329
|
stampWith,
|
|
3129
3330
|
organizationId,
|
|
3130
3331
|
userId
|
|
@@ -3144,7 +3345,7 @@ const ClientProvider = ({
|
|
|
3144
3345
|
});
|
|
3145
3346
|
};
|
|
3146
3347
|
if (openInPage) {
|
|
3147
|
-
|
|
3348
|
+
storage.storeOAuthAddProviderMetadata({
|
|
3148
3349
|
organizationId,
|
|
3149
3350
|
userId,
|
|
3150
3351
|
...(stampWith && {
|
|
@@ -3154,71 +3355,47 @@ const ClientProvider = ({
|
|
|
3154
3355
|
});
|
|
3155
3356
|
}
|
|
3156
3357
|
const additionalState = openInPage ? {
|
|
3157
|
-
oauthIntent:
|
|
3358
|
+
oauthIntent: storage.OAUTH_INTENT_ADD_PROVIDER,
|
|
3158
3359
|
...(successPageDuration > 0 && {
|
|
3159
3360
|
openModal: "true"
|
|
3160
3361
|
})
|
|
3161
3362
|
} : undefined;
|
|
3363
|
+
// Forward overrides so the inner handler uses the same client IDs.
|
|
3364
|
+
const sharedOauthParams = {
|
|
3365
|
+
openInPage,
|
|
3366
|
+
...(primaryClientId && {
|
|
3367
|
+
primaryClientId
|
|
3368
|
+
}),
|
|
3369
|
+
...(secondaryClientIds.length > 0 && {
|
|
3370
|
+
secondaryClientIds
|
|
3371
|
+
}),
|
|
3372
|
+
...(additionalState && {
|
|
3373
|
+
additionalState
|
|
3374
|
+
}),
|
|
3375
|
+
...(!openInPage && {
|
|
3376
|
+
onOauthSuccess
|
|
3377
|
+
})
|
|
3378
|
+
};
|
|
3162
3379
|
switch (providerName) {
|
|
3163
3380
|
case sdkTypes.OAuthProviders.DISCORD:
|
|
3164
3381
|
{
|
|
3165
|
-
return await handleDiscordOauth(
|
|
3166
|
-
openInPage,
|
|
3167
|
-
...(additionalState && {
|
|
3168
|
-
additionalState
|
|
3169
|
-
}),
|
|
3170
|
-
...(!openInPage && {
|
|
3171
|
-
onOauthSuccess
|
|
3172
|
-
})
|
|
3173
|
-
});
|
|
3382
|
+
return await handleDiscordOauth(sharedOauthParams);
|
|
3174
3383
|
}
|
|
3175
3384
|
case sdkTypes.OAuthProviders.X:
|
|
3176
3385
|
{
|
|
3177
|
-
return await handleXOauth(
|
|
3178
|
-
openInPage,
|
|
3179
|
-
...(additionalState && {
|
|
3180
|
-
additionalState
|
|
3181
|
-
}),
|
|
3182
|
-
...(!openInPage && {
|
|
3183
|
-
onOauthSuccess
|
|
3184
|
-
})
|
|
3185
|
-
});
|
|
3386
|
+
return await handleXOauth(sharedOauthParams);
|
|
3186
3387
|
}
|
|
3187
3388
|
case sdkTypes.OAuthProviders.GOOGLE:
|
|
3188
3389
|
{
|
|
3189
|
-
return await handleGoogleOauth(
|
|
3190
|
-
openInPage,
|
|
3191
|
-
...(additionalState && {
|
|
3192
|
-
additionalState
|
|
3193
|
-
}),
|
|
3194
|
-
...(!openInPage && {
|
|
3195
|
-
onOauthSuccess
|
|
3196
|
-
})
|
|
3197
|
-
});
|
|
3390
|
+
return await handleGoogleOauth(sharedOauthParams);
|
|
3198
3391
|
}
|
|
3199
3392
|
case sdkTypes.OAuthProviders.APPLE:
|
|
3200
3393
|
{
|
|
3201
|
-
return await handleAppleOauth(
|
|
3202
|
-
openInPage,
|
|
3203
|
-
...(additionalState && {
|
|
3204
|
-
additionalState
|
|
3205
|
-
}),
|
|
3206
|
-
...(!openInPage && {
|
|
3207
|
-
onOauthSuccess
|
|
3208
|
-
})
|
|
3209
|
-
});
|
|
3394
|
+
return await handleAppleOauth(sharedOauthParams);
|
|
3210
3395
|
}
|
|
3211
3396
|
case sdkTypes.OAuthProviders.FACEBOOK:
|
|
3212
3397
|
{
|
|
3213
|
-
return await handleFacebookOauth(
|
|
3214
|
-
openInPage,
|
|
3215
|
-
...(additionalState && {
|
|
3216
|
-
additionalState
|
|
3217
|
-
}),
|
|
3218
|
-
...(!openInPage && {
|
|
3219
|
-
onOauthSuccess
|
|
3220
|
-
})
|
|
3221
|
-
});
|
|
3398
|
+
return await handleFacebookOauth(sharedOauthParams);
|
|
3222
3399
|
}
|
|
3223
3400
|
default:
|
|
3224
3401
|
{
|
|
@@ -3382,7 +3559,7 @@ const ClientProvider = ({
|
|
|
3382
3559
|
const tx = {
|
|
3383
3560
|
from,
|
|
3384
3561
|
to,
|
|
3385
|
-
caip2,
|
|
3562
|
+
caip2: caip2,
|
|
3386
3563
|
sponsor: sponsor ?? false,
|
|
3387
3564
|
...(value ? {
|
|
3388
3565
|
value
|
|
@@ -3428,7 +3605,7 @@ const ClientProvider = ({
|
|
|
3428
3605
|
preventBack: true,
|
|
3429
3606
|
onClose: () => reject(new sdkTypes.TurnkeyError("User canceled the transaction.", sdkTypes.TurnkeyErrorCodes.USER_CANCELED)),
|
|
3430
3607
|
content: jsxRuntime.jsx(SendTransaction.SendTransactionPage, {
|
|
3431
|
-
icon: icon ?? helpers.getChainLogo(caip2),
|
|
3608
|
+
icon: icon ?? helpers$1.getChainLogo(caip2),
|
|
3432
3609
|
action: action,
|
|
3433
3610
|
caip2: caip2,
|
|
3434
3611
|
successPageDuration: successPageDuration,
|
|
@@ -3478,7 +3655,7 @@ const ClientProvider = ({
|
|
|
3478
3655
|
preventBack: true,
|
|
3479
3656
|
onClose: () => reject(new sdkTypes.TurnkeyError("User canceled the transaction.", sdkTypes.TurnkeyErrorCodes.USER_CANCELED)),
|
|
3480
3657
|
content: jsxRuntime.jsx(SendTransaction.SendTransactionPage, {
|
|
3481
|
-
icon: icon ?? helpers.getChainLogo(caip2),
|
|
3658
|
+
icon: icon ?? helpers$1.getChainLogo(caip2),
|
|
3482
3659
|
action: action,
|
|
3483
3660
|
caip2: caip2,
|
|
3484
3661
|
successPageDuration: successPageDuration,
|
|
@@ -3815,6 +3992,8 @@ const ClientProvider = ({
|
|
|
3815
3992
|
config: masterConfig,
|
|
3816
3993
|
httpClient: client?.httpClient,
|
|
3817
3994
|
createHttpClient,
|
|
3995
|
+
overrideApiKeyStamper,
|
|
3996
|
+
overridePasskeyStamper,
|
|
3818
3997
|
createPasskey,
|
|
3819
3998
|
logout,
|
|
3820
3999
|
loginWithPasskey,
|
|
@@ -3877,6 +4056,8 @@ const ClientProvider = ({
|
|
|
3877
4056
|
clearUnusedKeyPairs,
|
|
3878
4057
|
getActiveSessionKey,
|
|
3879
4058
|
createApiKeyPair,
|
|
4059
|
+
deleteApiKeyPair,
|
|
4060
|
+
signWithApiKey,
|
|
3880
4061
|
getProxyAuthConfig,
|
|
3881
4062
|
fetchBootProofForAppProof,
|
|
3882
4063
|
verifyAppProofs,
|