@supabase/gotrue-js 2.108.2 → 2.112.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/dist/main/GoTrueAdminApi.d.ts +1 -4
- package/dist/main/GoTrueAdminApi.d.ts.map +1 -1
- package/dist/main/GoTrueAdminApi.js +1 -4
- package/dist/main/GoTrueAdminApi.js.map +1 -1
- package/dist/main/GoTrueClient.d.ts +67 -21
- package/dist/main/GoTrueClient.d.ts.map +1 -1
- package/dist/main/GoTrueClient.js +217 -68
- package/dist/main/GoTrueClient.js.map +1 -1
- package/dist/main/lib/constants.d.ts +13 -0
- package/dist/main/lib/constants.d.ts.map +1 -1
- package/dist/main/lib/constants.js +14 -1
- package/dist/main/lib/constants.js.map +1 -1
- package/dist/main/lib/errors.d.ts +1 -1
- package/dist/main/lib/fetch.d.ts.map +1 -1
- package/dist/main/lib/fetch.js +12 -6
- package/dist/main/lib/fetch.js.map +1 -1
- package/dist/main/lib/helpers.d.ts +50 -1
- package/dist/main/lib/helpers.d.ts.map +1 -1
- package/dist/main/lib/helpers.js +161 -5
- package/dist/main/lib/helpers.js.map +1 -1
- package/dist/main/lib/locks.d.ts +1 -1
- package/dist/main/lib/locks.js +1 -1
- package/dist/main/lib/types.d.ts +71 -9
- package/dist/main/lib/types.d.ts.map +1 -1
- package/dist/main/lib/types.js.map +1 -1
- package/dist/main/lib/version.d.ts +1 -1
- package/dist/main/lib/version.js +1 -1
- package/dist/module/GoTrueAdminApi.d.ts +1 -4
- package/dist/module/GoTrueAdminApi.d.ts.map +1 -1
- package/dist/module/GoTrueAdminApi.js +1 -4
- package/dist/module/GoTrueAdminApi.js.map +1 -1
- package/dist/module/GoTrueClient.d.ts +67 -21
- package/dist/module/GoTrueClient.d.ts.map +1 -1
- package/dist/module/GoTrueClient.js +219 -70
- package/dist/module/GoTrueClient.js.map +1 -1
- package/dist/module/lib/constants.d.ts +13 -0
- package/dist/module/lib/constants.d.ts.map +1 -1
- package/dist/module/lib/constants.js +13 -0
- package/dist/module/lib/constants.js.map +1 -1
- package/dist/module/lib/errors.d.ts +1 -1
- package/dist/module/lib/fetch.d.ts.map +1 -1
- package/dist/module/lib/fetch.js +12 -6
- package/dist/module/lib/fetch.js.map +1 -1
- package/dist/module/lib/helpers.d.ts +50 -1
- package/dist/module/lib/helpers.d.ts.map +1 -1
- package/dist/module/lib/helpers.js +153 -5
- package/dist/module/lib/helpers.js.map +1 -1
- package/dist/module/lib/locks.d.ts +1 -1
- package/dist/module/lib/locks.js +1 -1
- package/dist/module/lib/types.d.ts +71 -9
- package/dist/module/lib/types.d.ts.map +1 -1
- package/dist/module/lib/types.js.map +1 -1
- package/dist/module/lib/version.d.ts +1 -1
- package/dist/module/lib/version.js +1 -1
- package/dist/tsconfig.module.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/GoTrueAdminApi.ts +1 -4
- package/src/GoTrueClient.ts +268 -91
- package/src/lib/constants.ts +15 -0
- package/src/lib/errors.ts +1 -1
- package/src/lib/fetch.ts +13 -8
- package/src/lib/helpers.ts +198 -6
- package/src/lib/locks.ts +1 -1
- package/src/lib/types.ts +71 -9
- package/src/lib/version.ts +1 -1
|
@@ -129,6 +129,19 @@ class GoTrueClient {
|
|
|
129
129
|
* Keep extra care to never reject or throw uncaught errors
|
|
130
130
|
*/
|
|
131
131
|
this.initializePromise = null;
|
|
132
|
+
/**
|
|
133
|
+
* Non-null only while `initialize()` is running. While open,
|
|
134
|
+
* `_notifyAllSubscribers` enqueues init-chain notifications (those fired with
|
|
135
|
+
* `broadcast = true`, i.e. from `_recoverAndRefresh`) into this array instead
|
|
136
|
+
* of firing directly, so that `initializePromise` is guaranteed to be
|
|
137
|
+
* resolved before any subscriber callback runs. Callbacks that call
|
|
138
|
+
* `getSession()` / `getUser()` etc. would otherwise deadlock because those
|
|
139
|
+
* methods await `initializePromise`. Notifications from the incoming
|
|
140
|
+
* BroadcastChannel handler (`broadcast = false`) are not enqueued — they fire
|
|
141
|
+
* immediately. Flushed (in order) by `initialize()` after `initializePromise`
|
|
142
|
+
* settles.
|
|
143
|
+
*/
|
|
144
|
+
this._pendingInitNotifications = null;
|
|
132
145
|
this.detectSessionInUrl = true;
|
|
133
146
|
this.hasCustomAuthorizationHeader = false;
|
|
134
147
|
this.suppressGetSessionWarning = false;
|
|
@@ -318,9 +331,19 @@ class GoTrueClient {
|
|
|
318
331
|
* @category Auth
|
|
319
332
|
*/
|
|
320
333
|
async initialize() {
|
|
334
|
+
var _a;
|
|
321
335
|
if (this.initializePromise) {
|
|
322
336
|
return await this.initializePromise;
|
|
323
337
|
}
|
|
338
|
+
// Open the notification queue before _initialize() runs so that every
|
|
339
|
+
// _notifyAllSubscribers call inside the init chain enqueues instead of
|
|
340
|
+
// firing. Without this, a callback receiving SIGNED_IN (or TOKEN_REFRESHED
|
|
341
|
+
// / SIGNED_OUT) during _recoverAndRefresh would deadlock if it called
|
|
342
|
+
// getSession() / getUser() — those methods await initializePromise, which
|
|
343
|
+
// can only resolve after the callback returns, which can only return after
|
|
344
|
+
// getSession() resolves. The queue is flushed below after initializePromise
|
|
345
|
+
// has settled, so callbacks run with a fully resolved initializePromise.
|
|
346
|
+
this._pendingInitNotifications = [];
|
|
324
347
|
this.initializePromise = (async () => {
|
|
325
348
|
if (this.lock != null) {
|
|
326
349
|
// TODO(v3): remove legacy lock path
|
|
@@ -330,7 +353,15 @@ class GoTrueClient {
|
|
|
330
353
|
}
|
|
331
354
|
return await this._initialize();
|
|
332
355
|
})();
|
|
333
|
-
|
|
356
|
+
const result = await this.initializePromise;
|
|
357
|
+
// initializePromise is now resolved — flush queued notifications in order.
|
|
358
|
+
// Callbacks can safely call getSession() / getUser() / signOut() etc.
|
|
359
|
+
const queue = (_a = this._pendingInitNotifications) !== null && _a !== void 0 ? _a : [];
|
|
360
|
+
this._pendingInitNotifications = null;
|
|
361
|
+
for (const n of queue) {
|
|
362
|
+
await this._notifyAllSubscribers(n.event, n.session, n.broadcast);
|
|
363
|
+
}
|
|
364
|
+
return result;
|
|
334
365
|
}
|
|
335
366
|
/**
|
|
336
367
|
* IMPORTANT:
|
|
@@ -686,6 +717,7 @@ class GoTrueClient {
|
|
|
686
717
|
*/
|
|
687
718
|
async signUp(credentials) {
|
|
688
719
|
var _a, _b, _c;
|
|
720
|
+
let flowId = null;
|
|
689
721
|
try {
|
|
690
722
|
let res;
|
|
691
723
|
if ('email' in credentials) {
|
|
@@ -694,11 +726,11 @@ class GoTrueClient {
|
|
|
694
726
|
let codeChallengeMethod = null;
|
|
695
727
|
if (this.flowType === 'pkce') {
|
|
696
728
|
;
|
|
697
|
-
[codeChallenge, codeChallengeMethod] = await
|
|
729
|
+
[codeChallenge, codeChallengeMethod, flowId] = await this._getCodeChallengeAndMethod();
|
|
698
730
|
}
|
|
699
731
|
res = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/signup`, {
|
|
700
732
|
headers: this.headers,
|
|
701
|
-
redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
|
|
733
|
+
redirectTo: this._maybeAppendFlowIdToRedirect(options === null || options === void 0 ? void 0 : options.emailRedirectTo, flowId),
|
|
702
734
|
body: {
|
|
703
735
|
email,
|
|
704
736
|
password,
|
|
@@ -729,7 +761,7 @@ class GoTrueClient {
|
|
|
729
761
|
}
|
|
730
762
|
const { data, error } = res;
|
|
731
763
|
if (error || !data) {
|
|
732
|
-
await (0, helpers_1.
|
|
764
|
+
await (0, helpers_1.removePKCEVerifier)(this.storage, this.storageKey, flowId);
|
|
733
765
|
return this._returnResult({ data: { user: null, session: null }, error: error });
|
|
734
766
|
}
|
|
735
767
|
const session = data.session;
|
|
@@ -741,7 +773,7 @@ class GoTrueClient {
|
|
|
741
773
|
return this._returnResult({ data: { user, session }, error: null });
|
|
742
774
|
}
|
|
743
775
|
catch (error) {
|
|
744
|
-
await (0, helpers_1.
|
|
776
|
+
await (0, helpers_1.removePKCEVerifier)(this.storage, this.storageKey, flowId);
|
|
745
777
|
if ((0, errors_1.isAuthError)(error)) {
|
|
746
778
|
return this._returnResult({ data: { user: null, session: null }, error });
|
|
747
779
|
}
|
|
@@ -956,7 +988,8 @@ class GoTrueClient {
|
|
|
956
988
|
* {
|
|
957
989
|
* data: {
|
|
958
990
|
* provider: 'github',
|
|
959
|
-
* url: <PROVIDER_URL_TO_REDIRECT_TO
|
|
991
|
+
* url: <PROVIDER_URL_TO_REDIRECT_TO>,
|
|
992
|
+
* flowId: <PKCE_FLOW_ID_OR_NULL>
|
|
960
993
|
* },
|
|
961
994
|
* error: null
|
|
962
995
|
* }
|
|
@@ -1029,12 +1062,29 @@ class GoTrueClient {
|
|
|
1029
1062
|
*
|
|
1030
1063
|
* @remarks
|
|
1031
1064
|
* - Used when `flowType` is set to `pkce` in client options.
|
|
1065
|
+
* - When several PKCE flows are in flight at once, pass `options.flowId` so
|
|
1066
|
+
* the code is exchanged with the verifier created by that specific flow.
|
|
1067
|
+
* The flow id is returned by `signInWithOAuth`, and with
|
|
1068
|
+
* `experimental.appendPkceFlowIdToRedirects` enabled it also arrives on
|
|
1069
|
+
* your callback URL as the reserved `sb_flow_id` query parameter (read
|
|
1070
|
+
* automatically in a browser).
|
|
1071
|
+
* - When a flow id is present but its stored verifier is gone (evicted,
|
|
1072
|
+
* already used, or from another device), the call fails with a verifier
|
|
1073
|
+
* missing error instead of trying another flow's verifier — a mismatched
|
|
1074
|
+
* verifier would consume the single-use code. Without any flow id the
|
|
1075
|
+
* most recently stored verifier is used, as before.
|
|
1032
1076
|
*
|
|
1033
1077
|
* @example Exchange Auth Code
|
|
1034
1078
|
* ```js
|
|
1035
1079
|
* supabase.auth.exchangeCodeForSession('34e770dd-9ff9-416c-87fa-43b31d7ef225')
|
|
1036
1080
|
* ```
|
|
1037
1081
|
*
|
|
1082
|
+
* @example Exchange Auth Code for a specific flow (e.g. in a server-side callback handler)
|
|
1083
|
+
* ```js
|
|
1084
|
+
* const flowId = requestUrl.searchParams.get('sb_flow_id')
|
|
1085
|
+
* supabase.auth.exchangeCodeForSession(code, flowId ? { flowId } : undefined)
|
|
1086
|
+
* ```
|
|
1087
|
+
*
|
|
1038
1088
|
* @exampleResponse Exchange Auth Code
|
|
1039
1089
|
* ```json
|
|
1040
1090
|
* {
|
|
@@ -1192,15 +1242,15 @@ class GoTrueClient {
|
|
|
1192
1242
|
* }
|
|
1193
1243
|
* ```
|
|
1194
1244
|
*/
|
|
1195
|
-
async exchangeCodeForSession(authCode) {
|
|
1245
|
+
async exchangeCodeForSession(authCode, options) {
|
|
1196
1246
|
await this.initializePromise;
|
|
1197
1247
|
if (this.lock != null) {
|
|
1198
1248
|
// TODO(v3): remove legacy lock path
|
|
1199
1249
|
return this._acquireLock(this.lockAcquireTimeout, async () => {
|
|
1200
|
-
return this._exchangeCodeForSession(authCode);
|
|
1250
|
+
return this._exchangeCodeForSession(authCode, options);
|
|
1201
1251
|
});
|
|
1202
1252
|
}
|
|
1203
|
-
return this._exchangeCodeForSession(authCode);
|
|
1253
|
+
return this._exchangeCodeForSession(authCode, options);
|
|
1204
1254
|
}
|
|
1205
1255
|
/**
|
|
1206
1256
|
* Signs in a user by verifying a message signed by the user's private key.
|
|
@@ -1542,8 +1592,23 @@ class GoTrueClient {
|
|
|
1542
1592
|
throw error;
|
|
1543
1593
|
}
|
|
1544
1594
|
}
|
|
1545
|
-
async _exchangeCodeForSession(authCode) {
|
|
1546
|
-
const
|
|
1595
|
+
async _exchangeCodeForSession(authCode, options) {
|
|
1596
|
+
const hasExplicitFlowId = (options === null || options === void 0 ? void 0 : options.flowId) != null;
|
|
1597
|
+
const requestedFlowId = hasExplicitFlowId
|
|
1598
|
+
? (0, helpers_1.validatePKCEFlowId)(options === null || options === void 0 ? void 0 : options.flowId)
|
|
1599
|
+
: (0, helpers_1.isBrowser)()
|
|
1600
|
+
? (0, helpers_1.validatePKCEFlowId)((0, helpers_1.parseParametersFromURL)(window.location.href)[constants_1.PKCE_FLOW_ID_PARAM])
|
|
1601
|
+
: null;
|
|
1602
|
+
if (hasExplicitFlowId && !requestedFlowId) {
|
|
1603
|
+
this._debug('#_exchangeCodeForSession()', 'provided flowId is not a valid flow id', options === null || options === void 0 ? void 0 : options.flowId);
|
|
1604
|
+
}
|
|
1605
|
+
// With a flow id (explicit or from the callback URL) the lookup is
|
|
1606
|
+
// slot-only and a miss fails fast — see retrievePKCEVerifier. An invalid
|
|
1607
|
+
// explicit flow id also fails fast rather than borrowing another flow's
|
|
1608
|
+
// verifier.
|
|
1609
|
+
const { verifier: storageItem, flowId } = hasExplicitFlowId && !requestedFlowId
|
|
1610
|
+
? { verifier: null, flowId: null }
|
|
1611
|
+
: await (0, helpers_1.retrievePKCEVerifier)(this.storage, this.storageKey, requestedFlowId);
|
|
1547
1612
|
const [codeVerifier, redirectType] = (storageItem !== null && storageItem !== void 0 ? storageItem : '').split('/');
|
|
1548
1613
|
try {
|
|
1549
1614
|
if (!codeVerifier && this.flowType === 'pkce') {
|
|
@@ -1557,7 +1622,7 @@ class GoTrueClient {
|
|
|
1557
1622
|
},
|
|
1558
1623
|
xform: fetch_1._sessionResponse,
|
|
1559
1624
|
});
|
|
1560
|
-
await (0, helpers_1.
|
|
1625
|
+
await (0, helpers_1.removePKCEVerifier)(this.storage, this.storageKey, flowId);
|
|
1561
1626
|
if (error) {
|
|
1562
1627
|
throw error;
|
|
1563
1628
|
}
|
|
@@ -1575,7 +1640,7 @@ class GoTrueClient {
|
|
|
1575
1640
|
return this._returnResult({ data: Object.assign(Object.assign({}, data), { redirectType: redirectType !== null && redirectType !== void 0 ? redirectType : null }), error });
|
|
1576
1641
|
}
|
|
1577
1642
|
catch (error) {
|
|
1578
|
-
await (0, helpers_1.
|
|
1643
|
+
await (0, helpers_1.removePKCEVerifier)(this.storage, this.storageKey, flowId);
|
|
1579
1644
|
if ((0, errors_1.isAuthError)(error)) {
|
|
1580
1645
|
return this._returnResult({
|
|
1581
1646
|
data: { user: null, session: null, redirectType: null },
|
|
@@ -1774,6 +1839,7 @@ class GoTrueClient {
|
|
|
1774
1839
|
*/
|
|
1775
1840
|
async signInWithOtp(credentials) {
|
|
1776
1841
|
var _a, _b, _c, _d, _f;
|
|
1842
|
+
let flowId = null;
|
|
1777
1843
|
try {
|
|
1778
1844
|
if ('email' in credentials) {
|
|
1779
1845
|
const { email, options } = credentials;
|
|
@@ -1781,7 +1847,7 @@ class GoTrueClient {
|
|
|
1781
1847
|
let codeChallengeMethod = null;
|
|
1782
1848
|
if (this.flowType === 'pkce') {
|
|
1783
1849
|
;
|
|
1784
|
-
[codeChallenge, codeChallengeMethod] = await
|
|
1850
|
+
[codeChallenge, codeChallengeMethod, flowId] = await this._getCodeChallengeAndMethod();
|
|
1785
1851
|
}
|
|
1786
1852
|
const { error } = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/otp`, {
|
|
1787
1853
|
headers: this.headers,
|
|
@@ -1793,7 +1859,7 @@ class GoTrueClient {
|
|
|
1793
1859
|
code_challenge: codeChallenge,
|
|
1794
1860
|
code_challenge_method: codeChallengeMethod,
|
|
1795
1861
|
},
|
|
1796
|
-
redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
|
|
1862
|
+
redirectTo: this._maybeAppendFlowIdToRedirect(options === null || options === void 0 ? void 0 : options.emailRedirectTo, flowId),
|
|
1797
1863
|
});
|
|
1798
1864
|
return this._returnResult({ data: { user: null, session: null }, error });
|
|
1799
1865
|
}
|
|
@@ -1817,7 +1883,7 @@ class GoTrueClient {
|
|
|
1817
1883
|
throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number.');
|
|
1818
1884
|
}
|
|
1819
1885
|
catch (error) {
|
|
1820
|
-
await (0, helpers_1.
|
|
1886
|
+
await (0, helpers_1.removePKCEVerifier)(this.storage, this.storageKey, flowId);
|
|
1821
1887
|
if ((0, errors_1.isAuthError)(error)) {
|
|
1822
1888
|
return this._returnResult({ data: { user: null, session: null }, error });
|
|
1823
1889
|
}
|
|
@@ -2052,29 +2118,30 @@ class GoTrueClient {
|
|
|
2052
2118
|
* ```
|
|
2053
2119
|
*/
|
|
2054
2120
|
async signInWithSSO(params) {
|
|
2055
|
-
var _a, _b, _c, _d
|
|
2121
|
+
var _a, _b, _c, _d;
|
|
2122
|
+
let flowId = null;
|
|
2056
2123
|
try {
|
|
2057
2124
|
let codeChallenge = null;
|
|
2058
2125
|
let codeChallengeMethod = null;
|
|
2059
2126
|
if (this.flowType === 'pkce') {
|
|
2060
2127
|
;
|
|
2061
|
-
[codeChallenge, codeChallengeMethod] = await
|
|
2128
|
+
[codeChallenge, codeChallengeMethod, flowId] = await this._getCodeChallengeAndMethod();
|
|
2062
2129
|
}
|
|
2063
2130
|
const result = await (0, fetch_1._request)(this.fetch, 'POST', `${this.url}/sso`, {
|
|
2064
|
-
body: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, ('providerId' in params ? { provider_id: params.providerId } : null)), ('domain' in params ? { domain: params.domain } : null)), { redirect_to: (
|
|
2131
|
+
body: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, ('providerId' in params ? { provider_id: params.providerId } : null)), ('domain' in params ? { domain: params.domain } : null)), { redirect_to: this._maybeAppendFlowIdToRedirect((_a = params.options) === null || _a === void 0 ? void 0 : _a.redirectTo, flowId) }), (((_b = params === null || params === void 0 ? void 0 : params.options) === null || _b === void 0 ? void 0 : _b.captchaToken)
|
|
2065
2132
|
? { gotrue_meta_security: { captcha_token: params.options.captchaToken } }
|
|
2066
2133
|
: null)), { skip_http_redirect: true, code_challenge: codeChallenge, code_challenge_method: codeChallengeMethod }),
|
|
2067
2134
|
headers: this.headers,
|
|
2068
2135
|
xform: fetch_1._ssoResponse,
|
|
2069
2136
|
});
|
|
2070
2137
|
// Automatically redirect in browser unless skipBrowserRedirect is true
|
|
2071
|
-
if (((
|
|
2138
|
+
if (((_c = result.data) === null || _c === void 0 ? void 0 : _c.url) && (0, helpers_1.isBrowser)() && !((_d = params.options) === null || _d === void 0 ? void 0 : _d.skipBrowserRedirect)) {
|
|
2072
2139
|
window.location.assign(result.data.url);
|
|
2073
2140
|
}
|
|
2074
2141
|
return this._returnResult(result);
|
|
2075
2142
|
}
|
|
2076
2143
|
catch (error) {
|
|
2077
|
-
await (0, helpers_1.
|
|
2144
|
+
await (0, helpers_1.removePKCEVerifier)(this.storage, this.storageKey, flowId);
|
|
2078
2145
|
if ((0, errors_1.isAuthError)(error)) {
|
|
2079
2146
|
return this._returnResult({ data: null, error });
|
|
2080
2147
|
}
|
|
@@ -2194,6 +2261,7 @@ class GoTrueClient {
|
|
|
2194
2261
|
* ```
|
|
2195
2262
|
*/
|
|
2196
2263
|
async resend(credentials) {
|
|
2264
|
+
let flowId = null;
|
|
2197
2265
|
try {
|
|
2198
2266
|
const endpoint = `${this.url}/resend`;
|
|
2199
2267
|
if ('email' in credentials) {
|
|
@@ -2202,7 +2270,7 @@ class GoTrueClient {
|
|
|
2202
2270
|
let codeChallengeMethod = null;
|
|
2203
2271
|
if (this.flowType === 'pkce') {
|
|
2204
2272
|
;
|
|
2205
|
-
[codeChallenge, codeChallengeMethod] = await
|
|
2273
|
+
[codeChallenge, codeChallengeMethod, flowId] = await this._getCodeChallengeAndMethod();
|
|
2206
2274
|
}
|
|
2207
2275
|
const { error } = await (0, fetch_1._request)(this.fetch, 'POST', endpoint, {
|
|
2208
2276
|
headers: this.headers,
|
|
@@ -2213,10 +2281,10 @@ class GoTrueClient {
|
|
|
2213
2281
|
code_challenge: codeChallenge,
|
|
2214
2282
|
code_challenge_method: codeChallengeMethod,
|
|
2215
2283
|
},
|
|
2216
|
-
redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
|
|
2284
|
+
redirectTo: this._maybeAppendFlowIdToRedirect(options === null || options === void 0 ? void 0 : options.emailRedirectTo, flowId),
|
|
2217
2285
|
});
|
|
2218
2286
|
if (error) {
|
|
2219
|
-
await (0, helpers_1.
|
|
2287
|
+
await (0, helpers_1.removePKCEVerifier)(this.storage, this.storageKey, flowId);
|
|
2220
2288
|
}
|
|
2221
2289
|
return this._returnResult({ data: { user: null, session: null }, error });
|
|
2222
2290
|
}
|
|
@@ -2238,7 +2306,7 @@ class GoTrueClient {
|
|
|
2238
2306
|
throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number and a type');
|
|
2239
2307
|
}
|
|
2240
2308
|
catch (error) {
|
|
2241
|
-
await (0, helpers_1.
|
|
2309
|
+
await (0, helpers_1.removePKCEVerifier)(this.storage, this.storageKey, flowId);
|
|
2242
2310
|
if ((0, errors_1.isAuthError)(error)) {
|
|
2243
2311
|
return this._returnResult({ data: { user: null, session: null }, error });
|
|
2244
2312
|
}
|
|
@@ -2254,7 +2322,7 @@ class GoTrueClient {
|
|
|
2254
2322
|
* to the client. If that storage is based on request cookies for example,
|
|
2255
2323
|
* the values in it may not be authentic and therefore it's strongly advised
|
|
2256
2324
|
* against using this method and its results in such circumstances. A warning
|
|
2257
|
-
* will be emitted if this is detected. Use {@link
|
|
2325
|
+
* will be emitted if this is detected. Use {@link GoTrueClient.getUser} instead.
|
|
2258
2326
|
*
|
|
2259
2327
|
* @category Auth
|
|
2260
2328
|
*
|
|
@@ -2405,7 +2473,7 @@ class GoTrueClient {
|
|
|
2405
2473
|
}
|
|
2406
2474
|
}
|
|
2407
2475
|
/**
|
|
2408
|
-
* Use instead of {@link
|
|
2476
|
+
* Use instead of {@link GoTrueClient.getSession} inside the library. Loads the session
|
|
2409
2477
|
* via `__loadSession` (which may trigger a refresh if the access token is
|
|
2410
2478
|
* within the expiry margin) and runs `fn` with the result.
|
|
2411
2479
|
*/
|
|
@@ -2426,7 +2494,7 @@ class GoTrueClient {
|
|
|
2426
2494
|
/**
|
|
2427
2495
|
* NEVER USE DIRECTLY!
|
|
2428
2496
|
*
|
|
2429
|
-
* Always use
|
|
2497
|
+
* Always use `_useSession`.
|
|
2430
2498
|
*/
|
|
2431
2499
|
async __loadSession() {
|
|
2432
2500
|
this._debug('#__loadSession()', 'begin');
|
|
@@ -2640,7 +2708,6 @@ class GoTrueClient {
|
|
|
2640
2708
|
// JWT contains a `session_id` which does not correspond to an active
|
|
2641
2709
|
// session in the database, indicating the user is signed out.
|
|
2642
2710
|
await this._removeSession();
|
|
2643
|
-
await (0, helpers_1.removeItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
|
|
2644
2711
|
}
|
|
2645
2712
|
return this._returnResult({ data: { user: null }, error });
|
|
2646
2713
|
}
|
|
@@ -2772,6 +2839,7 @@ class GoTrueClient {
|
|
|
2772
2839
|
return await this._updateUser(attributes, options);
|
|
2773
2840
|
}
|
|
2774
2841
|
async _updateUser(attributes, options = {}) {
|
|
2842
|
+
let flowId = null;
|
|
2775
2843
|
try {
|
|
2776
2844
|
return await this._useSession(async (result) => {
|
|
2777
2845
|
const { data: sessionData, error: sessionError } = result;
|
|
@@ -2786,11 +2854,11 @@ class GoTrueClient {
|
|
|
2786
2854
|
let codeChallengeMethod = null;
|
|
2787
2855
|
if (this.flowType === 'pkce' && attributes.email != null) {
|
|
2788
2856
|
;
|
|
2789
|
-
[codeChallenge, codeChallengeMethod] = await
|
|
2857
|
+
[codeChallenge, codeChallengeMethod, flowId] = await this._getCodeChallengeAndMethod();
|
|
2790
2858
|
}
|
|
2791
2859
|
const { data, error: userError } = await (0, fetch_1._request)(this.fetch, 'PUT', `${this.url}/user`, {
|
|
2792
2860
|
headers: this.headers,
|
|
2793
|
-
redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
|
|
2861
|
+
redirectTo: this._maybeAppendFlowIdToRedirect(options === null || options === void 0 ? void 0 : options.emailRedirectTo, flowId),
|
|
2794
2862
|
body: Object.assign(Object.assign({}, attributes), { code_challenge: codeChallenge, code_challenge_method: codeChallengeMethod }),
|
|
2795
2863
|
jwt: session.access_token,
|
|
2796
2864
|
xform: fetch_1._userResponse,
|
|
@@ -2805,7 +2873,7 @@ class GoTrueClient {
|
|
|
2805
2873
|
});
|
|
2806
2874
|
}
|
|
2807
2875
|
catch (error) {
|
|
2808
|
-
await (0, helpers_1.
|
|
2876
|
+
await (0, helpers_1.removePKCEVerifier)(this.storage, this.storageKey, flowId);
|
|
2809
2877
|
if ((0, errors_1.isAuthError)(error)) {
|
|
2810
2878
|
return this._returnResult({ data: { user: null }, error });
|
|
2811
2879
|
}
|
|
@@ -3198,11 +3266,14 @@ class GoTrueClient {
|
|
|
3198
3266
|
this._debug('#_initialize()', 'begin', 'is PKCE flow', true);
|
|
3199
3267
|
if (!params.code)
|
|
3200
3268
|
throw new errors_1.AuthPKCEGrantCodeExchangeError('No code detected.');
|
|
3201
|
-
const { data, error } = await this._exchangeCodeForSession(params.code
|
|
3269
|
+
const { data, error } = await this._exchangeCodeForSession(params.code, {
|
|
3270
|
+
flowId: params[constants_1.PKCE_FLOW_ID_PARAM],
|
|
3271
|
+
});
|
|
3202
3272
|
if (error)
|
|
3203
3273
|
throw error;
|
|
3204
3274
|
const url = new URL(window.location.href);
|
|
3205
3275
|
url.searchParams.delete('code');
|
|
3276
|
+
url.searchParams.delete(constants_1.PKCE_FLOW_ID_PARAM);
|
|
3206
3277
|
window.history.replaceState(window.history.state, '', url.toString());
|
|
3207
3278
|
return {
|
|
3208
3279
|
data: { session: data.session, redirectType: (_a = data.redirectType) !== null && _a !== void 0 ? _a : null },
|
|
@@ -3272,8 +3343,16 @@ class GoTrueClient {
|
|
|
3272
3343
|
* Checks if the current URL and backing storage contain parameters given by a PKCE flow
|
|
3273
3344
|
*/
|
|
3274
3345
|
async _isPKCECallback(params) {
|
|
3346
|
+
if (!params.code) {
|
|
3347
|
+
return false;
|
|
3348
|
+
}
|
|
3349
|
+
const flowId = (0, helpers_1.validatePKCEFlowId)(params[constants_1.PKCE_FLOW_ID_PARAM]);
|
|
3350
|
+
if (flowId &&
|
|
3351
|
+
(await (0, helpers_1.getItemAsync)(this.storage, (0, helpers_1.pkceVerifierSlotKey)(this.storageKey, flowId)))) {
|
|
3352
|
+
return true;
|
|
3353
|
+
}
|
|
3275
3354
|
const currentStorageContent = await (0, helpers_1.getItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
|
|
3276
|
-
return !!
|
|
3355
|
+
return !!currentStorageContent;
|
|
3277
3356
|
}
|
|
3278
3357
|
/**
|
|
3279
3358
|
* Inside a browser context, `signOut()` will remove the logged in user from the browser session and log them out - removing all items from localstorage and then trigger a `"SIGNED_OUT"` event.
|
|
@@ -3329,6 +3408,9 @@ class GoTrueClient {
|
|
|
3329
3408
|
async _signOut({ scope } = { scope: 'global' }) {
|
|
3330
3409
|
return await this._useSession(async (result) => {
|
|
3331
3410
|
var _a;
|
|
3411
|
+
const removeCurrentSession = async () => {
|
|
3412
|
+
await this._removeSession();
|
|
3413
|
+
};
|
|
3332
3414
|
const { data, error: sessionError } = result;
|
|
3333
3415
|
if (sessionError && !(0, errors_1.isAuthSessionMissingError)(sessionError)) {
|
|
3334
3416
|
return this._returnResult({ error: sessionError });
|
|
@@ -3342,13 +3424,15 @@ class GoTrueClient {
|
|
|
3342
3424
|
if (!(((0, errors_1.isAuthApiError)(error) &&
|
|
3343
3425
|
(error.status === 404 || error.status === 401 || error.status === 403)) ||
|
|
3344
3426
|
(0, errors_1.isAuthSessionMissingError)(error))) {
|
|
3427
|
+
if (scope !== 'others') {
|
|
3428
|
+
await removeCurrentSession();
|
|
3429
|
+
}
|
|
3345
3430
|
return this._returnResult({ error });
|
|
3346
3431
|
}
|
|
3347
3432
|
}
|
|
3348
3433
|
}
|
|
3349
3434
|
if (scope !== 'others') {
|
|
3350
|
-
await
|
|
3351
|
-
await (0, helpers_1.removeItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
|
|
3435
|
+
await removeCurrentSession();
|
|
3352
3436
|
}
|
|
3353
3437
|
return this._returnResult({ error: null });
|
|
3354
3438
|
});
|
|
@@ -3569,7 +3653,16 @@ class GoTrueClient {
|
|
|
3569
3653
|
catch (err) {
|
|
3570
3654
|
await ((_b = this.stateChangeEmitters.get(id)) === null || _b === void 0 ? void 0 : _b.callback('INITIAL_SESSION', null));
|
|
3571
3655
|
this._debug('INITIAL_SESSION', 'callback id', id, 'error', err);
|
|
3572
|
-
if ((0, errors_1.isAuthSessionMissingError)(err)
|
|
3656
|
+
if ((0, errors_1.isAuthSessionMissingError)(err) ||
|
|
3657
|
+
(0, errors_1.isAuthRetryableFetchError)(err) ||
|
|
3658
|
+
((0, errors_1.isAuthApiError)(err) &&
|
|
3659
|
+
(err.code === 'refresh_token_not_found' ||
|
|
3660
|
+
err.code === 'refresh_token_already_used' ||
|
|
3661
|
+
err.code === 'session_expired'))) {
|
|
3662
|
+
// A missing session, a transient/aborted network failure (e.g. a
|
|
3663
|
+
// superseded page navigation cancelling the in-flight request), or
|
|
3664
|
+
// a dead refresh token (e.g. stale SSR cookies) is not an
|
|
3665
|
+
// application error — warn rather than surface it raw.
|
|
3573
3666
|
console.warn(err);
|
|
3574
3667
|
}
|
|
3575
3668
|
else {
|
|
@@ -3648,9 +3741,10 @@ class GoTrueClient {
|
|
|
3648
3741
|
async resetPasswordForEmail(email, options = {}) {
|
|
3649
3742
|
let codeChallenge = null;
|
|
3650
3743
|
let codeChallengeMethod = null;
|
|
3744
|
+
let flowId = null;
|
|
3651
3745
|
if (this.flowType === 'pkce') {
|
|
3652
3746
|
;
|
|
3653
|
-
[codeChallenge, codeChallengeMethod] = await
|
|
3747
|
+
[codeChallenge, codeChallengeMethod, flowId] = await this._getCodeChallengeAndMethod(true // isPasswordRecovery
|
|
3654
3748
|
);
|
|
3655
3749
|
}
|
|
3656
3750
|
try {
|
|
@@ -3662,11 +3756,11 @@ class GoTrueClient {
|
|
|
3662
3756
|
gotrue_meta_security: { captcha_token: options.captchaToken },
|
|
3663
3757
|
},
|
|
3664
3758
|
headers: this.headers,
|
|
3665
|
-
redirectTo: options.redirectTo,
|
|
3759
|
+
redirectTo: this._maybeAppendFlowIdToRedirect(options.redirectTo, flowId),
|
|
3666
3760
|
});
|
|
3667
3761
|
}
|
|
3668
3762
|
catch (error) {
|
|
3669
|
-
await (0, helpers_1.
|
|
3763
|
+
await (0, helpers_1.removePKCEVerifier)(this.storage, this.storageKey, flowId);
|
|
3670
3764
|
if ((0, errors_1.isAuthError)(error)) {
|
|
3671
3765
|
return this._returnResult({ data: null, error });
|
|
3672
3766
|
}
|
|
@@ -3749,7 +3843,8 @@ class GoTrueClient {
|
|
|
3749
3843
|
* {
|
|
3750
3844
|
* data: {
|
|
3751
3845
|
* provider: 'github',
|
|
3752
|
-
* url: <PROVIDER_URL_TO_REDIRECT_TO
|
|
3846
|
+
* url: <PROVIDER_URL_TO_REDIRECT_TO>,
|
|
3847
|
+
* flowId: <PKCE_FLOW_ID_OR_NULL>
|
|
3753
3848
|
* },
|
|
3754
3849
|
* error: null
|
|
3755
3850
|
* }
|
|
@@ -3763,18 +3858,20 @@ class GoTrueClient {
|
|
|
3763
3858
|
}
|
|
3764
3859
|
async linkIdentityOAuth(credentials) {
|
|
3765
3860
|
var _a;
|
|
3861
|
+
let flowId = null;
|
|
3766
3862
|
try {
|
|
3767
3863
|
const { data, error } = await this._useSession(async (result) => {
|
|
3768
3864
|
var _a, _b, _c, _d, _f;
|
|
3769
3865
|
const { data, error } = result;
|
|
3770
3866
|
if (error)
|
|
3771
3867
|
throw error;
|
|
3772
|
-
const url = await this._getUrlForProvider(`${this.url}/user/identities/authorize`, credentials.provider, {
|
|
3868
|
+
const { url, flowId: urlFlowId } = await this._getUrlForProvider(`${this.url}/user/identities/authorize`, credentials.provider, {
|
|
3773
3869
|
redirectTo: (_a = credentials.options) === null || _a === void 0 ? void 0 : _a.redirectTo,
|
|
3774
3870
|
scopes: (_b = credentials.options) === null || _b === void 0 ? void 0 : _b.scopes,
|
|
3775
3871
|
queryParams: (_c = credentials.options) === null || _c === void 0 ? void 0 : _c.queryParams,
|
|
3776
3872
|
skipBrowserRedirect: true,
|
|
3777
3873
|
});
|
|
3874
|
+
flowId = urlFlowId;
|
|
3778
3875
|
return await (0, fetch_1._request)(this.fetch, 'GET', url, {
|
|
3779
3876
|
headers: this.headers,
|
|
3780
3877
|
jwt: (_f = (_d = data.session) === null || _d === void 0 ? void 0 : _d.access_token) !== null && _f !== void 0 ? _f : undefined,
|
|
@@ -3786,13 +3883,16 @@ class GoTrueClient {
|
|
|
3786
3883
|
window.location.assign(data === null || data === void 0 ? void 0 : data.url);
|
|
3787
3884
|
}
|
|
3788
3885
|
return this._returnResult({
|
|
3789
|
-
data: { provider: credentials.provider, url: data === null || data === void 0 ? void 0 : data.url },
|
|
3886
|
+
data: { provider: credentials.provider, url: data === null || data === void 0 ? void 0 : data.url, flowId },
|
|
3790
3887
|
error: null,
|
|
3791
3888
|
});
|
|
3792
3889
|
}
|
|
3793
3890
|
catch (error) {
|
|
3794
3891
|
if ((0, errors_1.isAuthError)(error)) {
|
|
3795
|
-
return this._returnResult({
|
|
3892
|
+
return this._returnResult({
|
|
3893
|
+
data: { provider: credentials.provider, url: null, flowId },
|
|
3894
|
+
error,
|
|
3895
|
+
});
|
|
3796
3896
|
}
|
|
3797
3897
|
throw error;
|
|
3798
3898
|
}
|
|
@@ -3835,7 +3935,7 @@ class GoTrueClient {
|
|
|
3835
3935
|
return this._returnResult({ data, error });
|
|
3836
3936
|
}
|
|
3837
3937
|
catch (error) {
|
|
3838
|
-
await (0, helpers_1.
|
|
3938
|
+
await (0, helpers_1.removePKCEVerifier)(this.storage, this.storageKey, null);
|
|
3839
3939
|
if ((0, errors_1.isAuthError)(error)) {
|
|
3840
3940
|
return this._returnResult({ data: { user: null, session: null }, error });
|
|
3841
3941
|
}
|
|
@@ -3940,7 +4040,7 @@ class GoTrueClient {
|
|
|
3940
4040
|
return isValidSession;
|
|
3941
4041
|
}
|
|
3942
4042
|
async _handleProviderSignIn(provider, options) {
|
|
3943
|
-
const url = await this._getUrlForProvider(`${this.url}/authorize`, provider, {
|
|
4043
|
+
const { url, flowId } = await this._getUrlForProvider(`${this.url}/authorize`, provider, {
|
|
3944
4044
|
redirectTo: options.redirectTo,
|
|
3945
4045
|
scopes: options.scopes,
|
|
3946
4046
|
queryParams: options.queryParams,
|
|
@@ -3950,7 +4050,7 @@ class GoTrueClient {
|
|
|
3950
4050
|
if ((0, helpers_1.isBrowser)() && !options.skipBrowserRedirect) {
|
|
3951
4051
|
window.location.assign(url);
|
|
3952
4052
|
}
|
|
3953
|
-
return { data: { provider, url }, error: null };
|
|
4053
|
+
return { data: { provider, url, flowId }, error: null };
|
|
3954
4054
|
}
|
|
3955
4055
|
/**
|
|
3956
4056
|
* Recovers the session from LocalStorage and refreshes the token
|
|
@@ -4047,7 +4147,16 @@ class GoTrueClient {
|
|
|
4047
4147
|
}
|
|
4048
4148
|
catch (err) {
|
|
4049
4149
|
this._debug(debugName, 'error', err);
|
|
4050
|
-
|
|
4150
|
+
if ((0, errors_1.isAuthRetryableFetchError)(err)) {
|
|
4151
|
+
// Transient/aborted network failure during session recovery (e.g. a
|
|
4152
|
+
// superseded page navigation cancelling the in-flight request). Warn
|
|
4153
|
+
// rather than surface it raw; the session is untouched and recovery
|
|
4154
|
+
// will run again on the next load.
|
|
4155
|
+
console.warn(err);
|
|
4156
|
+
}
|
|
4157
|
+
else {
|
|
4158
|
+
console.error(err);
|
|
4159
|
+
}
|
|
4051
4160
|
return;
|
|
4052
4161
|
}
|
|
4053
4162
|
finally {
|
|
@@ -4197,6 +4306,19 @@ class GoTrueClient {
|
|
|
4197
4306
|
}
|
|
4198
4307
|
}
|
|
4199
4308
|
async _notifyAllSubscribers(event, session, broadcast = true) {
|
|
4309
|
+
if (this._pendingInitNotifications !== null && broadcast) {
|
|
4310
|
+
// We're inside initialize() before initializePromise has resolved, and
|
|
4311
|
+
// this notification originates from the init chain (_recoverAndRefresh),
|
|
4312
|
+
// which always fires with broadcast = true. Enqueue instead of firing so
|
|
4313
|
+
// that callbacks can safely call getSession() / getUser() without
|
|
4314
|
+
// deadlocking on initializePromise.
|
|
4315
|
+
//
|
|
4316
|
+
// Notifications with broadcast = false come from the incoming
|
|
4317
|
+
// BroadcastChannel handler (a cross-tab event), not the init chain, so
|
|
4318
|
+
// they are fired immediately to preserve multi-tab ordering.
|
|
4319
|
+
this._pendingInitNotifications.push({ event, session, broadcast });
|
|
4320
|
+
return;
|
|
4321
|
+
}
|
|
4200
4322
|
const debugName = `#_notifyAllSubscribers(${event})`;
|
|
4201
4323
|
this._debug(debugName, 'begin', session, `broadcast = ${broadcast}`);
|
|
4202
4324
|
try {
|
|
@@ -4233,7 +4355,6 @@ class GoTrueClient {
|
|
|
4233
4355
|
// _saveSession is always called whenever a new session has been acquired
|
|
4234
4356
|
// so we can safely suppress the warning returned by future getSession calls
|
|
4235
4357
|
this.suppressGetSessionWarning = true;
|
|
4236
|
-
await (0, helpers_1.removeItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
|
|
4237
4358
|
// Create a shallow copy to work with, to avoid mutating the original session object if it's used elsewhere
|
|
4238
4359
|
const sessionToProcess = Object.assign({}, session);
|
|
4239
4360
|
const userIsProxy = sessionToProcess.user && sessionToProcess.user.__isUserNotAvailableProxy === true;
|
|
@@ -4277,7 +4398,7 @@ class GoTrueClient {
|
|
|
4277
4398
|
this.lastRefreshFailure = null;
|
|
4278
4399
|
this.suppressGetSessionWarning = false;
|
|
4279
4400
|
await (0, helpers_1.removeItemAsync)(this.storage, this.storageKey);
|
|
4280
|
-
await (0, helpers_1.
|
|
4401
|
+
await (0, helpers_1.removeAllPKCEVerifiers)(this.storage, this.storageKey);
|
|
4281
4402
|
await (0, helpers_1.removeItemAsync)(this.storage, this.storageKey + '-user');
|
|
4282
4403
|
if (this.userStorage) {
|
|
4283
4404
|
await (0, helpers_1.removeItemAsync)(this.userStorage, this.storageKey + '-user');
|
|
@@ -4287,8 +4408,8 @@ class GoTrueClient {
|
|
|
4287
4408
|
/**
|
|
4288
4409
|
* Removes any registered visibilitychange callback.
|
|
4289
4410
|
*
|
|
4290
|
-
* {@
|
|
4291
|
-
* {@
|
|
4411
|
+
* {@link GoTrueClient.startAutoRefresh}
|
|
4412
|
+
* {@link GoTrueClient.stopAutoRefresh}
|
|
4292
4413
|
*/
|
|
4293
4414
|
_removeVisibilityChangedCallback() {
|
|
4294
4415
|
this._debug('#_removeVisibilityChangedCallback()');
|
|
@@ -4304,7 +4425,7 @@ class GoTrueClient {
|
|
|
4304
4425
|
}
|
|
4305
4426
|
}
|
|
4306
4427
|
/**
|
|
4307
|
-
* This is the private implementation of {@link
|
|
4428
|
+
* This is the private implementation of {@link GoTrueClient.startAutoRefresh}. Use this
|
|
4308
4429
|
* within the library.
|
|
4309
4430
|
*/
|
|
4310
4431
|
async _startAutoRefresh() {
|
|
@@ -4346,7 +4467,7 @@ class GoTrueClient {
|
|
|
4346
4467
|
}
|
|
4347
4468
|
}
|
|
4348
4469
|
/**
|
|
4349
|
-
* This is the private implementation of {@link
|
|
4470
|
+
* This is the private implementation of {@link GoTrueClient.stopAutoRefresh}. Use this
|
|
4350
4471
|
* within the library.
|
|
4351
4472
|
*/
|
|
4352
4473
|
async _stopAutoRefresh() {
|
|
@@ -4382,7 +4503,7 @@ class GoTrueClient {
|
|
|
4382
4503
|
* platform's foreground indication mechanism and call these methods
|
|
4383
4504
|
* appropriately to conserve resources.
|
|
4384
4505
|
*
|
|
4385
|
-
* {@
|
|
4506
|
+
* {@link GoTrueClient.stopAutoRefresh}
|
|
4386
4507
|
*
|
|
4387
4508
|
* @category Auth
|
|
4388
4509
|
*
|
|
@@ -4416,7 +4537,7 @@ class GoTrueClient {
|
|
|
4416
4537
|
* If you call this method any managed visibility change callback will be
|
|
4417
4538
|
* removed and you must manage visibility changes on your own.
|
|
4418
4539
|
*
|
|
4419
|
-
* See {@link
|
|
4540
|
+
* See {@link GoTrueClient.startAutoRefresh} for more details.
|
|
4420
4541
|
*
|
|
4421
4542
|
* @category Auth
|
|
4422
4543
|
*
|
|
@@ -4643,15 +4764,23 @@ class GoTrueClient {
|
|
|
4643
4764
|
* @param options.queryParams An object of key-value pairs containing query parameters granted to the OAuth application.
|
|
4644
4765
|
*/
|
|
4645
4766
|
async _getUrlForProvider(url, provider, options) {
|
|
4767
|
+
let redirectTo = options === null || options === void 0 ? void 0 : options.redirectTo;
|
|
4768
|
+
let codeChallenge = null;
|
|
4769
|
+
let codeChallengeMethod = null;
|
|
4770
|
+
let flowId = null;
|
|
4771
|
+
if (this.flowType === 'pkce') {
|
|
4772
|
+
;
|
|
4773
|
+
[codeChallenge, codeChallengeMethod, flowId] = await this._getCodeChallengeAndMethod();
|
|
4774
|
+
redirectTo = this._maybeAppendFlowIdToRedirect(redirectTo, flowId);
|
|
4775
|
+
}
|
|
4646
4776
|
const urlParams = [`provider=${encodeURIComponent(provider)}`];
|
|
4647
|
-
if (
|
|
4648
|
-
urlParams.push(`redirect_to=${encodeURIComponent(
|
|
4777
|
+
if (redirectTo) {
|
|
4778
|
+
urlParams.push(`redirect_to=${encodeURIComponent(redirectTo)}`);
|
|
4649
4779
|
}
|
|
4650
4780
|
if (options === null || options === void 0 ? void 0 : options.scopes) {
|
|
4651
4781
|
urlParams.push(`scopes=${encodeURIComponent(options.scopes)}`);
|
|
4652
4782
|
}
|
|
4653
|
-
if (
|
|
4654
|
-
const [codeChallenge, codeChallengeMethod] = await (0, helpers_1.getCodeChallengeAndMethod)(this.storage, this.storageKey);
|
|
4783
|
+
if (codeChallenge != null && codeChallengeMethod != null) {
|
|
4655
4784
|
const flowParams = new URLSearchParams({
|
|
4656
4785
|
code_challenge: `${encodeURIComponent(codeChallenge)}`,
|
|
4657
4786
|
code_challenge_method: `${encodeURIComponent(codeChallengeMethod)}`,
|
|
@@ -4665,7 +4794,27 @@ class GoTrueClient {
|
|
|
4665
4794
|
if (options === null || options === void 0 ? void 0 : options.skipBrowserRedirect) {
|
|
4666
4795
|
urlParams.push(`skip_http_redirect=${options.skipBrowserRedirect}`);
|
|
4667
4796
|
}
|
|
4668
|
-
return `${url}?${urlParams.join('&')}
|
|
4797
|
+
return { url: `${url}?${urlParams.join('&')}`, flowId };
|
|
4798
|
+
}
|
|
4799
|
+
/**
|
|
4800
|
+
* Appends the reserved flow id parameter to a redirect URL so the callback
|
|
4801
|
+
* can be matched to the verifier stored for its flow. Opt-in via
|
|
4802
|
+
* `experimental.appendPkceFlowIdToRedirects`: redirect URLs are validated
|
|
4803
|
+
* against the project's allow list including the query string, so an extra
|
|
4804
|
+
* parameter can stop exact (non-wildcard) entries from matching.
|
|
4805
|
+
*/
|
|
4806
|
+
_maybeAppendFlowIdToRedirect(redirectTo, flowId) {
|
|
4807
|
+
if (!redirectTo || !flowId || !this.experimental.appendPkceFlowIdToRedirects) {
|
|
4808
|
+
return redirectTo !== null && redirectTo !== void 0 ? redirectTo : undefined;
|
|
4809
|
+
}
|
|
4810
|
+
return (0, helpers_1.appendFlowIdToRedirectTo)(redirectTo, flowId);
|
|
4811
|
+
}
|
|
4812
|
+
/**
|
|
4813
|
+
* Generates and stores a PKCE challenge/verifier pair for a new flow,
|
|
4814
|
+
* logging any pending verifier the bounded slot ring evicts.
|
|
4815
|
+
*/
|
|
4816
|
+
async _getCodeChallengeAndMethod(isPasswordRecovery = false) {
|
|
4817
|
+
return (0, helpers_1.getCodeChallengeAndMethod)(this.storage, this.storageKey, isPasswordRecovery, (evictedFlowId) => this._debug('#_getCodeChallengeAndMethod()', 'evicted oldest pending PKCE verifier slot', evictedFlowId));
|
|
4669
4818
|
}
|
|
4670
4819
|
async _unenroll(params) {
|
|
4671
4820
|
try {
|
|
@@ -4813,7 +4962,7 @@ class GoTrueClient {
|
|
|
4813
4962
|
return run();
|
|
4814
4963
|
}
|
|
4815
4964
|
/**
|
|
4816
|
-
* {@
|
|
4965
|
+
* {@link GoTrueMFAApi#challengeAndVerify}
|
|
4817
4966
|
*/
|
|
4818
4967
|
async _challengeAndVerify(params) {
|
|
4819
4968
|
const { data: challengeData, error: challengeError } = await this._challenge({
|
|
@@ -4829,7 +4978,7 @@ class GoTrueClient {
|
|
|
4829
4978
|
});
|
|
4830
4979
|
}
|
|
4831
4980
|
/**
|
|
4832
|
-
* {@
|
|
4981
|
+
* {@link GoTrueMFAApi#listFactors}
|
|
4833
4982
|
*/
|
|
4834
4983
|
async _listFactors() {
|
|
4835
4984
|
var _a;
|
|
@@ -4857,7 +5006,7 @@ class GoTrueClient {
|
|
|
4857
5006
|
};
|
|
4858
5007
|
}
|
|
4859
5008
|
/**
|
|
4860
|
-
* {@
|
|
5009
|
+
* {@link GoTrueMFAApi#getAuthenticatorAssuranceLevel}
|
|
4861
5010
|
*/
|
|
4862
5011
|
async _getAuthenticatorAssuranceLevel(jwt) {
|
|
4863
5012
|
var _a, _b, _c, _d;
|
|
@@ -5108,15 +5257,15 @@ class GoTrueClient {
|
|
|
5108
5257
|
* Extracts the JWT claims present in the access token by first verifying the
|
|
5109
5258
|
* JWT against the server's JSON Web Key Set endpoint
|
|
5110
5259
|
* `/.well-known/jwks.json` which is often cached, resulting in significantly
|
|
5111
|
-
* faster responses. Prefer this method over {@link
|
|
5260
|
+
* faster responses. Prefer this method over {@link GoTrueClient.getUser} which always
|
|
5112
5261
|
* sends a request to the Auth server for each JWT.
|
|
5113
5262
|
*
|
|
5114
5263
|
* If the project is not using an asymmetric JWT signing key (like ECC or
|
|
5115
|
-
* RSA) it always sends a request to the Auth server (similar to
|
|
5116
|
-
*
|
|
5264
|
+
* RSA) it always sends a request to the Auth server (similar to
|
|
5265
|
+
* {@link GoTrueClient.getUser}) to verify the JWT.
|
|
5117
5266
|
*
|
|
5118
5267
|
* @param jwt An optional specific JWT you wish to verify, not the one you
|
|
5119
|
-
* can obtain from {@link
|
|
5268
|
+
* can obtain from {@link GoTrueClient.getSession}.
|
|
5120
5269
|
* @param options Various additional options that allow you to customize the
|
|
5121
5270
|
* behavior of this method.
|
|
5122
5271
|
*
|