@instantdb/core 0.22.167 → 0.22.168
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/__tests__/src/auth-extra-fields.e2e.test.ts +134 -0
- package/__tests__/src/utils/e2e.ts +23 -11
- package/dist/commonjs/Reactor.d.ts +12 -9
- package/dist/commonjs/Reactor.d.ts.map +1 -1
- package/dist/commonjs/Reactor.js +48 -11
- package/dist/commonjs/Reactor.js.map +1 -1
- package/dist/commonjs/authAPI.d.ts +19 -2
- package/dist/commonjs/authAPI.d.ts.map +1 -1
- package/dist/commonjs/authAPI.js +23 -2
- package/dist/commonjs/authAPI.js.map +1 -1
- package/dist/commonjs/index.d.ts +6 -5
- package/dist/commonjs/index.d.ts.map +1 -1
- package/dist/commonjs/index.js.map +1 -1
- package/dist/esm/Reactor.d.ts +12 -9
- package/dist/esm/Reactor.d.ts.map +1 -1
- package/dist/esm/Reactor.js +48 -11
- package/dist/esm/Reactor.js.map +1 -1
- package/dist/esm/authAPI.d.ts +19 -2
- package/dist/esm/authAPI.d.ts.map +1 -1
- package/dist/esm/authAPI.js +22 -2
- package/dist/esm/authAPI.js.map +1 -1
- package/dist/esm/index.d.ts +6 -5
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/standalone/index.js +891 -864
- package/dist/standalone/index.umd.cjs +3 -3
- package/package.json +3 -2
- package/src/Reactor.js +49 -11
- package/src/authAPI.ts +45 -2
- package/src/index.ts +11 -4
- package/vitest.config.ts +6 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { expect } from 'vitest';
|
|
2
|
+
import { i } from '../../src';
|
|
3
|
+
import { makeE2ETest, apiUrl } from './utils/e2e';
|
|
4
|
+
|
|
5
|
+
const schema = i.schema({
|
|
6
|
+
entities: {
|
|
7
|
+
$users: i.entity({
|
|
8
|
+
email: i.string().unique().indexed().optional(),
|
|
9
|
+
username: i.string().unique().indexed().optional(),
|
|
10
|
+
displayName: i.string().optional(),
|
|
11
|
+
}),
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
async function generateMagicCode(
|
|
16
|
+
appId: string,
|
|
17
|
+
adminToken: string,
|
|
18
|
+
email: string,
|
|
19
|
+
): Promise<string> {
|
|
20
|
+
const res = await fetch(`${apiUrl}/admin/magic_code`, {
|
|
21
|
+
method: 'POST',
|
|
22
|
+
headers: {
|
|
23
|
+
'Content-Type': 'application/json',
|
|
24
|
+
'app-id': appId,
|
|
25
|
+
authorization: `Bearer ${adminToken}`,
|
|
26
|
+
},
|
|
27
|
+
body: JSON.stringify({ email }),
|
|
28
|
+
});
|
|
29
|
+
const data = await res.json();
|
|
30
|
+
return data.code;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const authTest = makeE2ETest({ schema });
|
|
34
|
+
|
|
35
|
+
authTest(
|
|
36
|
+
'new user with extraFields gets fields written and created=true',
|
|
37
|
+
async ({ db, appId, adminToken }) => {
|
|
38
|
+
const email = `new-${Date.now()}@test.com`;
|
|
39
|
+
|
|
40
|
+
const code = await generateMagicCode(appId, adminToken, email);
|
|
41
|
+
const res = await db.auth.signInWithMagicCode({
|
|
42
|
+
email,
|
|
43
|
+
code,
|
|
44
|
+
extraFields: { username: 'cool_user', displayName: 'Cool User' },
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
expect(res.created).toBe(true);
|
|
48
|
+
|
|
49
|
+
const { data } = await db.queryOnce({ $users: {} });
|
|
50
|
+
const user = data.$users.find((u: any) => u.email === email);
|
|
51
|
+
expect(user).toBeDefined();
|
|
52
|
+
expect(user!.username).toBe('cool_user');
|
|
53
|
+
expect(user!.displayName).toBe('Cool User');
|
|
54
|
+
},
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
authTest(
|
|
58
|
+
'returning user gets created=false',
|
|
59
|
+
async ({ db, appId, adminToken }) => {
|
|
60
|
+
const email = `returning-${Date.now()}@test.com`;
|
|
61
|
+
|
|
62
|
+
// First sign in -- creates user
|
|
63
|
+
const code1 = await generateMagicCode(appId, adminToken, email);
|
|
64
|
+
const res1 = await db.auth.signInWithMagicCode({ email, code: code1 });
|
|
65
|
+
expect(res1.created).toBe(true);
|
|
66
|
+
|
|
67
|
+
// Second sign in -- existing user
|
|
68
|
+
const code2 = await generateMagicCode(appId, adminToken, email);
|
|
69
|
+
const res2 = await db.auth.signInWithMagicCode({ email, code: code2 });
|
|
70
|
+
expect(res2.created).toBe(false);
|
|
71
|
+
},
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
authTest(
|
|
75
|
+
'sign in without extraFields works (backwards compat)',
|
|
76
|
+
async ({ db, appId, adminToken }) => {
|
|
77
|
+
const email = `compat-${Date.now()}@test.com`;
|
|
78
|
+
|
|
79
|
+
const code = await generateMagicCode(appId, adminToken, email);
|
|
80
|
+
const res = await db.auth.signInWithMagicCode({ email, code });
|
|
81
|
+
|
|
82
|
+
expect(res.user).toBeDefined();
|
|
83
|
+
expect(res.user.email).toBe(email);
|
|
84
|
+
},
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
authTest(
|
|
88
|
+
'admin verify_magic_code returns { user, created } for checkMagicCode',
|
|
89
|
+
async ({ db: _db, appId, adminToken }) => {
|
|
90
|
+
const email = `admin-consume-${Date.now()}@test.com`;
|
|
91
|
+
const code = await generateMagicCode(appId, adminToken, email);
|
|
92
|
+
|
|
93
|
+
// Hit the admin endpoint directly (same as admin SDK checkMagicCode)
|
|
94
|
+
const res = await fetch(
|
|
95
|
+
`${apiUrl}/admin/verify_magic_code?app_id=${appId}`,
|
|
96
|
+
{
|
|
97
|
+
method: 'POST',
|
|
98
|
+
headers: {
|
|
99
|
+
'Content-Type': 'application/json',
|
|
100
|
+
authorization: `Bearer ${adminToken}`,
|
|
101
|
+
},
|
|
102
|
+
body: JSON.stringify({
|
|
103
|
+
email,
|
|
104
|
+
code,
|
|
105
|
+
'extra-fields': { username: 'admin_user' },
|
|
106
|
+
}),
|
|
107
|
+
},
|
|
108
|
+
);
|
|
109
|
+
const data = await res.json();
|
|
110
|
+
|
|
111
|
+
// Response should have user nested (not splatted) and created flag
|
|
112
|
+
expect(data.user).toBeDefined();
|
|
113
|
+
expect(data.user.email).toBe(email);
|
|
114
|
+
expect(data.created).toBe(true);
|
|
115
|
+
|
|
116
|
+
// Second call -- existing user
|
|
117
|
+
const code2 = await generateMagicCode(appId, adminToken, email);
|
|
118
|
+
const res2 = await fetch(
|
|
119
|
+
`${apiUrl}/admin/verify_magic_code?app_id=${appId}`,
|
|
120
|
+
{
|
|
121
|
+
method: 'POST',
|
|
122
|
+
headers: {
|
|
123
|
+
'Content-Type': 'application/json',
|
|
124
|
+
authorization: `Bearer ${adminToken}`,
|
|
125
|
+
},
|
|
126
|
+
body: JSON.stringify({ email, code: code2 }),
|
|
127
|
+
},
|
|
128
|
+
);
|
|
129
|
+
const data2 = await res2.json();
|
|
130
|
+
|
|
131
|
+
expect(data2.user).toBeDefined();
|
|
132
|
+
expect(data2.created).toBe(false);
|
|
133
|
+
},
|
|
134
|
+
);
|
|
@@ -6,18 +6,19 @@ import {
|
|
|
6
6
|
InstantSchemaDef,
|
|
7
7
|
} from '../../../src';
|
|
8
8
|
|
|
9
|
-
//
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
// __DEV_LOCAL_PORT__ is set by vitest.config.ts.
|
|
10
|
+
// This allows us to run tests against mulutple checkouts
|
|
11
|
+
// If CI=1 then __DEV_LOCAL_PORT__ will be falsey and tests will hit prod.
|
|
12
|
+
// Otherwise they will hit localhost at the specified port.
|
|
13
|
+
declare const __DEV_LOCAL_PORT__: number;
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
const apiUrl = __DEV_LOCAL_PORT__
|
|
16
|
+
? `http://localhost:${__DEV_LOCAL_PORT__}`
|
|
17
|
+
: 'https://api.instantdb.com';
|
|
18
|
+
|
|
19
|
+
const websocketURI = __DEV_LOCAL_PORT__
|
|
20
|
+
? `ws://localhost:${__DEV_LOCAL_PORT__}/runtime/session`
|
|
21
|
+
: 'wss://api.instantdb.com/runtime/session';
|
|
21
22
|
|
|
22
23
|
// Make a factory function that returns a typed test instance
|
|
23
24
|
export function makeE2ETest<Schema extends InstantSchemaDef<any, any, any>>({
|
|
@@ -31,6 +32,8 @@ export function makeE2ETest<Schema extends InstantSchemaDef<any, any, any>>({
|
|
|
31
32
|
}) {
|
|
32
33
|
return baseTest.extend<{
|
|
33
34
|
db: InstantCoreDatabase<Schema, false>;
|
|
35
|
+
appId: string;
|
|
36
|
+
adminToken: string;
|
|
34
37
|
}>({
|
|
35
38
|
db: async ({ task, signal }, use) => {
|
|
36
39
|
const response = await fetch(`${apiUrl}/dash/apps/ephemeral`, {
|
|
@@ -49,9 +52,18 @@ export function makeE2ETest<Schema extends InstantSchemaDef<any, any, any>>({
|
|
|
49
52
|
websocketURI,
|
|
50
53
|
schema,
|
|
51
54
|
});
|
|
55
|
+
(db as any)._testApp = app;
|
|
52
56
|
await use(db);
|
|
53
57
|
},
|
|
58
|
+
appId: async ({ db }, use) => {
|
|
59
|
+
await use((db as any)._testApp.id);
|
|
60
|
+
},
|
|
61
|
+
adminToken: async ({ db }, use) => {
|
|
62
|
+
await use((db as any)._testApp['admin-token']);
|
|
63
|
+
},
|
|
54
64
|
});
|
|
55
65
|
}
|
|
56
66
|
|
|
67
|
+
export { apiUrl };
|
|
68
|
+
|
|
57
69
|
export const e2eTest = makeE2ETest({});
|
|
@@ -291,10 +291,7 @@ export default class Reactor<RoomSchema extends import("./presence.ts").RoomSche
|
|
|
291
291
|
sendMagicCode({ email }: {
|
|
292
292
|
email: any;
|
|
293
293
|
}): Promise<authAPI.SendMagicCodeResponse>;
|
|
294
|
-
signInWithMagicCode(
|
|
295
|
-
email: any;
|
|
296
|
-
code: any;
|
|
297
|
-
}): Promise<authAPI.VerifyResponse>;
|
|
294
|
+
signInWithMagicCode(params: any): Promise<authAPI.CheckMagicCodeResponse>;
|
|
298
295
|
signInWithCustomToken(authToken: any): Promise<authAPI.VerifyResponse>;
|
|
299
296
|
signInAsGuest(): Promise<authAPI.VerifyResponse>;
|
|
300
297
|
potentiallyInvalidateToken(currentUser: any, opts: any): void;
|
|
@@ -305,33 +302,39 @@ export default class Reactor<RoomSchema extends import("./presence.ts").RoomSche
|
|
|
305
302
|
* @param {Object} params - The parameters to create the authorization URL.
|
|
306
303
|
* @param {string} params.clientName - The name of the client requesting authorization.
|
|
307
304
|
* @param {string} params.redirectURL - The URL to redirect users to after authorization.
|
|
305
|
+
* @param {Record<string, any>} [params.extraFields] - Extra fields to write to $users on creation
|
|
308
306
|
* @returns {string} The created authorization URL.
|
|
309
307
|
*/
|
|
310
|
-
createAuthorizationURL({ clientName, redirectURL }: {
|
|
308
|
+
createAuthorizationURL({ clientName, redirectURL, extraFields }: {
|
|
311
309
|
clientName: string;
|
|
312
310
|
redirectURL: string;
|
|
311
|
+
extraFields?: Record<string, any> | undefined;
|
|
313
312
|
}): string;
|
|
314
313
|
/**
|
|
315
314
|
* @param {Object} params
|
|
316
315
|
* @param {string} params.code - The code received from the OAuth service.
|
|
317
316
|
* @param {string} [params.codeVerifier] - The code verifier used to generate the code challenge.
|
|
317
|
+
* @param {Record<string, any>} [params.extraFields] - Extra fields to write to $users on creation
|
|
318
318
|
*/
|
|
319
|
-
exchangeCodeForToken({ code, codeVerifier }: {
|
|
319
|
+
exchangeCodeForToken({ code, codeVerifier, extraFields }: {
|
|
320
320
|
code: string;
|
|
321
321
|
codeVerifier?: string | undefined;
|
|
322
|
-
|
|
322
|
+
extraFields?: Record<string, any> | undefined;
|
|
323
|
+
}): Promise<authAPI.CheckMagicCodeResponse>;
|
|
323
324
|
issuerURI(): string;
|
|
324
325
|
/**
|
|
325
326
|
* @param {Object} params
|
|
326
327
|
* @param {string} params.clientName - The name of the client requesting authorization.
|
|
327
328
|
* @param {string} params.idToken - The id_token from the external service
|
|
328
329
|
* @param {string | null | undefined} [params.nonce] - The nonce used when requesting the id_token from the external service
|
|
330
|
+
* @param {Record<string, any>} [params.extraFields] - Extra fields to write to $users on creation
|
|
329
331
|
*/
|
|
330
|
-
signInWithIdToken(
|
|
332
|
+
signInWithIdToken(params: {
|
|
331
333
|
clientName: string;
|
|
332
334
|
idToken: string;
|
|
333
335
|
nonce?: string | null | undefined;
|
|
334
|
-
|
|
336
|
+
extraFields?: Record<string, any> | undefined;
|
|
337
|
+
}): Promise<authAPI.CheckMagicCodeResponse>;
|
|
335
338
|
/**
|
|
336
339
|
* @param {string} roomType
|
|
337
340
|
* @param {string} roomId
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Reactor.d.ts","sourceRoot":"","sources":["../../src/Reactor.js"],"names":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"Reactor.d.ts","sourceRoot":"","sources":["../../src/Reactor.js"],"names":[],"mappings":"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"}
|
package/dist/commonjs/Reactor.js
CHANGED
|
@@ -91,6 +91,8 @@ const defaultConfig = {
|
|
|
91
91
|
};
|
|
92
92
|
// Param that the backend adds if this is an oauth redirect
|
|
93
93
|
const OAUTH_REDIRECT_PARAM = '_instant_oauth_redirect';
|
|
94
|
+
const OAUTH_EXTRA_FIELDS_ID_PARAM = '_instant_extra_fields_id';
|
|
95
|
+
const oauthExtraFieldsKey = 'oauthExtraFields';
|
|
94
96
|
const currentUserKey = `currentUser`;
|
|
95
97
|
/**
|
|
96
98
|
* @param {Object} config
|
|
@@ -1552,6 +1554,7 @@ class Reactor {
|
|
|
1552
1554
|
if (url.searchParams.get(OAUTH_REDIRECT_PARAM)) {
|
|
1553
1555
|
const startUrl = url.toString();
|
|
1554
1556
|
url.searchParams.delete(OAUTH_REDIRECT_PARAM);
|
|
1557
|
+
url.searchParams.delete(OAUTH_EXTRA_FIELDS_ID_PARAM);
|
|
1555
1558
|
url.searchParams.delete('code');
|
|
1556
1559
|
url.searchParams.delete('error');
|
|
1557
1560
|
const newPath = url.pathname +
|
|
@@ -1614,8 +1617,20 @@ class Reactor {
|
|
|
1614
1617
|
if (!code) {
|
|
1615
1618
|
return null;
|
|
1616
1619
|
}
|
|
1620
|
+
const extraFieldsId = params.get(OAUTH_EXTRA_FIELDS_ID_PARAM);
|
|
1617
1621
|
this._replaceUrlAfterOAuth();
|
|
1618
1622
|
try {
|
|
1623
|
+
let extraFields;
|
|
1624
|
+
const stored = await this.kv.waitForKeyToLoad(oauthExtraFieldsKey);
|
|
1625
|
+
if (extraFieldsId && stored) {
|
|
1626
|
+
extraFields = stored[extraFieldsId];
|
|
1627
|
+
}
|
|
1628
|
+
// Clean up all stored extraFields after login
|
|
1629
|
+
if (stored) {
|
|
1630
|
+
this.kv.updateInPlace((prev) => {
|
|
1631
|
+
delete prev[oauthExtraFieldsKey];
|
|
1632
|
+
});
|
|
1633
|
+
}
|
|
1619
1634
|
const currentUser = await this._getCurrentUser();
|
|
1620
1635
|
const isGuest = currentUser?.type === 'guest';
|
|
1621
1636
|
const { user } = await authAPI.exchangeCodeForToken({
|
|
@@ -1623,6 +1638,7 @@ class Reactor {
|
|
|
1623
1638
|
appId: this.config.appId,
|
|
1624
1639
|
code,
|
|
1625
1640
|
refreshToken: isGuest ? currentUser.refresh_token : undefined,
|
|
1641
|
+
extraFields,
|
|
1626
1642
|
});
|
|
1627
1643
|
this.setCurrentUser(user);
|
|
1628
1644
|
return null;
|
|
@@ -1840,15 +1856,16 @@ class Reactor {
|
|
|
1840
1856
|
email: email,
|
|
1841
1857
|
});
|
|
1842
1858
|
}
|
|
1843
|
-
async signInWithMagicCode(
|
|
1859
|
+
async signInWithMagicCode(params) {
|
|
1844
1860
|
const currentUser = await this.getCurrentUser();
|
|
1845
1861
|
const isGuest = currentUser?.user?.type === 'guest';
|
|
1846
|
-
const res = await authAPI.
|
|
1862
|
+
const res = await authAPI.checkMagicCode({
|
|
1847
1863
|
apiURI: this.config.apiURI,
|
|
1848
1864
|
appId: this.config.appId,
|
|
1849
|
-
email,
|
|
1850
|
-
code,
|
|
1865
|
+
email: params.email,
|
|
1866
|
+
code: params.code,
|
|
1851
1867
|
refreshToken: isGuest ? currentUser?.user?.refresh_token : undefined,
|
|
1868
|
+
extraFields: params.extraFields,
|
|
1852
1869
|
});
|
|
1853
1870
|
await this.changeCurrentUser(res.user);
|
|
1854
1871
|
return res;
|
|
@@ -1902,18 +1919,35 @@ class Reactor {
|
|
|
1902
1919
|
* @param {Object} params - The parameters to create the authorization URL.
|
|
1903
1920
|
* @param {string} params.clientName - The name of the client requesting authorization.
|
|
1904
1921
|
* @param {string} params.redirectURL - The URL to redirect users to after authorization.
|
|
1922
|
+
* @param {Record<string, any>} [params.extraFields] - Extra fields to write to $users on creation
|
|
1905
1923
|
* @returns {string} The created authorization URL.
|
|
1906
1924
|
*/
|
|
1907
|
-
createAuthorizationURL({ clientName, redirectURL }) {
|
|
1925
|
+
createAuthorizationURL({ clientName, redirectURL, extraFields }) {
|
|
1908
1926
|
const { apiURI, appId } = this.config;
|
|
1909
|
-
|
|
1927
|
+
let finalRedirectURL = redirectURL;
|
|
1928
|
+
if (extraFields) {
|
|
1929
|
+
// Store extraFields under a unique ID so multiple
|
|
1930
|
+
// createAuthorizationURL calls don't overwrite each other.
|
|
1931
|
+
// The ID is passed through the redirect URL and used
|
|
1932
|
+
// by _oauthLoginInit to retrieve the right extraFields.
|
|
1933
|
+
// All entries are cleaned up after login.
|
|
1934
|
+
const extraFieldsId = `${Math.random().toString(36).slice(2)}`;
|
|
1935
|
+
this.kv.updateInPlace((prev) => {
|
|
1936
|
+
const stored = prev[oauthExtraFieldsKey] || {};
|
|
1937
|
+
stored[extraFieldsId] = extraFields;
|
|
1938
|
+
prev[oauthExtraFieldsKey] = stored;
|
|
1939
|
+
});
|
|
1940
|
+
finalRedirectURL = `${redirectURL}${redirectURL.includes('?') ? '&' : '?'}${OAUTH_EXTRA_FIELDS_ID_PARAM}=${extraFieldsId}`;
|
|
1941
|
+
}
|
|
1942
|
+
return `${apiURI}/runtime/oauth/start?app_id=${appId}&client_name=${clientName}&redirect_uri=${encodeURIComponent(finalRedirectURL)}`;
|
|
1910
1943
|
}
|
|
1911
1944
|
/**
|
|
1912
1945
|
* @param {Object} params
|
|
1913
1946
|
* @param {string} params.code - The code received from the OAuth service.
|
|
1914
1947
|
* @param {string} [params.codeVerifier] - The code verifier used to generate the code challenge.
|
|
1948
|
+
* @param {Record<string, any>} [params.extraFields] - Extra fields to write to $users on creation
|
|
1915
1949
|
*/
|
|
1916
|
-
async exchangeCodeForToken({ code, codeVerifier }) {
|
|
1950
|
+
async exchangeCodeForToken({ code, codeVerifier, extraFields }) {
|
|
1917
1951
|
const currentUser = await this.getCurrentUser();
|
|
1918
1952
|
const isGuest = currentUser?.user?.type === 'guest';
|
|
1919
1953
|
const res = await authAPI.exchangeCodeForToken({
|
|
@@ -1922,6 +1956,7 @@ class Reactor {
|
|
|
1922
1956
|
code: code,
|
|
1923
1957
|
codeVerifier,
|
|
1924
1958
|
refreshToken: isGuest ? currentUser?.user?.refresh_token : undefined,
|
|
1959
|
+
extraFields,
|
|
1925
1960
|
});
|
|
1926
1961
|
await this.changeCurrentUser(res.user);
|
|
1927
1962
|
return res;
|
|
@@ -1935,17 +1970,19 @@ class Reactor {
|
|
|
1935
1970
|
* @param {string} params.clientName - The name of the client requesting authorization.
|
|
1936
1971
|
* @param {string} params.idToken - The id_token from the external service
|
|
1937
1972
|
* @param {string | null | undefined} [params.nonce] - The nonce used when requesting the id_token from the external service
|
|
1973
|
+
* @param {Record<string, any>} [params.extraFields] - Extra fields to write to $users on creation
|
|
1938
1974
|
*/
|
|
1939
|
-
async signInWithIdToken(
|
|
1975
|
+
async signInWithIdToken(params) {
|
|
1940
1976
|
const currentUser = await this.getCurrentUser();
|
|
1941
1977
|
const refreshToken = currentUser?.user?.refresh_token;
|
|
1942
1978
|
const res = await authAPI.signInWithIdToken({
|
|
1943
1979
|
apiURI: this.config.apiURI,
|
|
1944
1980
|
appId: this.config.appId,
|
|
1945
|
-
idToken,
|
|
1946
|
-
clientName,
|
|
1947
|
-
nonce,
|
|
1981
|
+
idToken: params.idToken,
|
|
1982
|
+
clientName: params.clientName,
|
|
1983
|
+
nonce: params.nonce,
|
|
1948
1984
|
refreshToken,
|
|
1985
|
+
extraFields: params.extraFields,
|
|
1949
1986
|
});
|
|
1950
1987
|
await this.changeCurrentUser(res.user);
|
|
1951
1988
|
return res;
|