@supabase/gotrue-js 2.46.2 → 2.47.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/main/GoTrueClient.d.ts +19 -1
- package/dist/main/GoTrueClient.d.ts.map +1 -1
- package/dist/main/GoTrueClient.js +179 -103
- package/dist/main/GoTrueClient.js.map +1 -1
- package/dist/main/lib/helpers.d.ts +0 -29
- package/dist/main/lib/helpers.d.ts.map +1 -1
- package/dist/main/lib/helpers.js +1 -117
- package/dist/main/lib/helpers.js.map +1 -1
- package/dist/main/lib/locks.d.ts.map +1 -1
- package/dist/main/lib/locks.js +16 -58
- package/dist/main/lib/locks.js.map +1 -1
- package/dist/main/lib/version.d.ts +1 -1
- package/dist/main/lib/version.js +1 -1
- package/dist/module/GoTrueClient.d.ts +19 -1
- package/dist/module/GoTrueClient.d.ts.map +1 -1
- package/dist/module/GoTrueClient.js +180 -104
- package/dist/module/GoTrueClient.js.map +1 -1
- package/dist/module/lib/helpers.d.ts +0 -29
- package/dist/module/lib/helpers.d.ts.map +1 -1
- package/dist/module/lib/helpers.js +0 -113
- package/dist/module/lib/helpers.js.map +1 -1
- package/dist/module/lib/locks.d.ts.map +1 -1
- package/dist/module/lib/locks.js +16 -58
- package/dist/module/lib/locks.js.map +1 -1
- package/dist/module/lib/version.d.ts +1 -1
- package/dist/module/lib/version.js +1 -1
- package/package.json +1 -1
- package/src/GoTrueClient.ts +235 -135
- package/src/lib/helpers.ts +0 -140
- package/src/lib/locks.ts +17 -73
- package/src/lib/version.ts +1 -1
|
@@ -46,6 +46,8 @@ export default class GoTrueClient {
|
|
|
46
46
|
};
|
|
47
47
|
protected fetch: Fetch;
|
|
48
48
|
protected lock: LockFunc;
|
|
49
|
+
protected lockAcquired: boolean;
|
|
50
|
+
protected pendingInLock: Promise<any>[];
|
|
49
51
|
/**
|
|
50
52
|
* Used to broadcast state change events to other tabs listening.
|
|
51
53
|
*/
|
|
@@ -98,6 +100,7 @@ export default class GoTrueClient {
|
|
|
98
100
|
* Log in an existing user by exchanging an Auth Code issued during the PKCE flow.
|
|
99
101
|
*/
|
|
100
102
|
exchangeCodeForSession(authCode: string): Promise<AuthTokenResponse>;
|
|
103
|
+
private _exchangeCodeForSession;
|
|
101
104
|
/**
|
|
102
105
|
* Allows signing in with an OIDC ID token. The authentication provider used
|
|
103
106
|
* should be enabled and configured.
|
|
@@ -145,6 +148,7 @@ export default class GoTrueClient {
|
|
|
145
148
|
* Requires the user to be signed-in.
|
|
146
149
|
*/
|
|
147
150
|
reauthenticate(): Promise<AuthResponse>;
|
|
151
|
+
private _reauthenticate;
|
|
148
152
|
/**
|
|
149
153
|
* Resends an existing signup confirmation email, email change email, SMS OTP or phone change OTP.
|
|
150
154
|
*/
|
|
@@ -191,12 +195,16 @@ export default class GoTrueClient {
|
|
|
191
195
|
* @param jwt Takes in an optional access token jwt. If no jwt is provided, getUser() will attempt to get the jwt from the current session.
|
|
192
196
|
*/
|
|
193
197
|
getUser(jwt?: string): Promise<UserResponse>;
|
|
198
|
+
private _getUser;
|
|
194
199
|
/**
|
|
195
200
|
* Updates user data for a logged in user.
|
|
196
201
|
*/
|
|
197
202
|
updateUser(attributes: UserAttributes, options?: {
|
|
198
203
|
emailRedirectTo?: string | undefined;
|
|
199
204
|
}): Promise<UserResponse>;
|
|
205
|
+
protected _updateUser(attributes: UserAttributes, options?: {
|
|
206
|
+
emailRedirectTo?: string | undefined;
|
|
207
|
+
}): Promise<UserResponse>;
|
|
200
208
|
/**
|
|
201
209
|
* Decodes a JWT (without performing any validation).
|
|
202
210
|
*/
|
|
@@ -210,6 +218,10 @@ export default class GoTrueClient {
|
|
|
210
218
|
access_token: string;
|
|
211
219
|
refresh_token: string;
|
|
212
220
|
}): Promise<AuthResponse>;
|
|
221
|
+
protected _setSession(currentSession: {
|
|
222
|
+
access_token: string;
|
|
223
|
+
refresh_token: string;
|
|
224
|
+
}): Promise<AuthResponse>;
|
|
213
225
|
/**
|
|
214
226
|
* Returns a new session, regardless of expiry status.
|
|
215
227
|
* Takes in an optional current session. If not passed in, then refreshSession() will attempt to retrieve it from getSession().
|
|
@@ -219,6 +231,9 @@ export default class GoTrueClient {
|
|
|
219
231
|
refreshSession(currentSession?: {
|
|
220
232
|
refresh_token: string;
|
|
221
233
|
}): Promise<AuthResponse>;
|
|
234
|
+
protected _refreshSession(currentSession?: {
|
|
235
|
+
refresh_token: string;
|
|
236
|
+
}): Promise<AuthResponse>;
|
|
222
237
|
/**
|
|
223
238
|
* Gets the session data from a URL string
|
|
224
239
|
*/
|
|
@@ -240,7 +255,10 @@ export default class GoTrueClient {
|
|
|
240
255
|
*
|
|
241
256
|
* If using others scope, no `SIGNED_OUT` event is fired!
|
|
242
257
|
*/
|
|
243
|
-
signOut(
|
|
258
|
+
signOut(options?: SignOut): Promise<{
|
|
259
|
+
error: AuthError | null;
|
|
260
|
+
}>;
|
|
261
|
+
protected _signOut({ scope }?: SignOut): Promise<{
|
|
244
262
|
error: AuthError | null;
|
|
245
263
|
}>;
|
|
246
264
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GoTrueClient.d.ts","sourceRoot":"","sources":["../../src/GoTrueClient.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EACL,SAAS,EAWV,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,KAAK,EAA2D,MAAM,aAAa,CAAA;AAC5F,OAAO,EAEL,QAAQ,
|
|
1
|
+
{"version":3,"file":"GoTrueClient.d.ts","sourceRoot":"","sources":["../../src/GoTrueClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import GoTrueAdminApi from './GoTrueAdminApi';
|
|
|
2
2
|
import { DEFAULT_HEADERS, EXPIRY_MARGIN, GOTRUE_URL, STORAGE_KEY } from './lib/constants';
|
|
3
3
|
import { AuthImplicitGrantRedirectError, AuthPKCEGrantCodeExchangeError, AuthInvalidCredentialsError, AuthSessionMissingError, AuthInvalidTokenResponseError, AuthUnknownError, isAuthApiError, isAuthError, isAuthRetryableFetchError, } from './lib/errors';
|
|
4
4
|
import { _request, _sessionResponse, _userResponse, _ssoResponse } from './lib/fetch';
|
|
5
|
-
import { decodeJWTPayload, Deferred, getItemAsync, isBrowser, removeItemAsync, resolveFetch, setItemAsync, uuid, retryable, sleep, generatePKCEVerifier, generatePKCEChallenge, supportsLocalStorage,
|
|
5
|
+
import { decodeJWTPayload, Deferred, getItemAsync, isBrowser, removeItemAsync, resolveFetch, setItemAsync, uuid, retryable, sleep, generatePKCEVerifier, generatePKCEChallenge, supportsLocalStorage, parseParametersFromURL, } from './lib/helpers';
|
|
6
6
|
import localStorageAdapter from './lib/local-storage';
|
|
7
7
|
import { polyfillGlobalThis } from './lib/polyfills';
|
|
8
8
|
import { version } from './lib/version';
|
|
@@ -43,6 +43,8 @@ export default class GoTrueClient {
|
|
|
43
43
|
*/
|
|
44
44
|
this.initializePromise = null;
|
|
45
45
|
this.detectSessionInUrl = true;
|
|
46
|
+
this.lockAcquired = false;
|
|
47
|
+
this.pendingInLock = [];
|
|
46
48
|
/**
|
|
47
49
|
* Used to broadcast state change events to other tabs listening.
|
|
48
50
|
*/
|
|
@@ -108,11 +110,16 @@ export default class GoTrueClient {
|
|
|
108
110
|
* This method is automatically called when instantiating the client, but should also be called
|
|
109
111
|
* manually when checking for an error from an auth redirect (oauth, magiclink, password recovery, etc).
|
|
110
112
|
*/
|
|
111
|
-
initialize() {
|
|
113
|
+
async initialize() {
|
|
112
114
|
if (this.initializePromise) {
|
|
113
|
-
return this.initializePromise;
|
|
115
|
+
return await this.initializePromise;
|
|
114
116
|
}
|
|
115
|
-
|
|
117
|
+
this.initializePromise = (async () => {
|
|
118
|
+
return await this._acquireLock(-1, async () => {
|
|
119
|
+
return await this._initialize();
|
|
120
|
+
});
|
|
121
|
+
})();
|
|
122
|
+
return await this.initializePromise;
|
|
116
123
|
}
|
|
117
124
|
/**
|
|
118
125
|
* IMPORTANT:
|
|
@@ -121,53 +128,47 @@ export default class GoTrueClient {
|
|
|
121
128
|
* the whole lifetime of the client
|
|
122
129
|
*/
|
|
123
130
|
async _initialize() {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
this._debug('#_initialize()', 'error detecting session from URL', error);
|
|
135
|
-
// failed login attempt via url,
|
|
136
|
-
// remove old session as in verifyOtp, signUp and signInWith*
|
|
137
|
-
await this._removeSession();
|
|
138
|
-
return { error };
|
|
139
|
-
}
|
|
140
|
-
const { session, redirectType } = data;
|
|
141
|
-
this._debug('#_initialize()', 'detected session in URL', session, 'redirect type', redirectType);
|
|
142
|
-
await this._saveSession(session);
|
|
143
|
-
setTimeout(async () => {
|
|
144
|
-
if (redirectType === 'recovery') {
|
|
145
|
-
await this._notifyAllSubscribers('PASSWORD_RECOVERY', session);
|
|
146
|
-
}
|
|
147
|
-
else {
|
|
148
|
-
await this._notifyAllSubscribers('SIGNED_IN', session);
|
|
149
|
-
}
|
|
150
|
-
}, 0);
|
|
151
|
-
return { error: null };
|
|
152
|
-
}
|
|
153
|
-
// no login attempt via callback url try to recover session from storage
|
|
154
|
-
await this._recoverAndRefresh();
|
|
155
|
-
return { error: null };
|
|
156
|
-
}
|
|
157
|
-
catch (error) {
|
|
158
|
-
if (isAuthError(error)) {
|
|
131
|
+
try {
|
|
132
|
+
const isPKCEFlow = isBrowser() ? await this._isPKCEFlow() : false;
|
|
133
|
+
this._debug('#_initialize()', 'begin', 'is PKCE flow', isPKCEFlow);
|
|
134
|
+
if (isPKCEFlow || (this.detectSessionInUrl && this._isImplicitGrantFlow())) {
|
|
135
|
+
const { data, error } = await this._getSessionFromURL(isPKCEFlow);
|
|
136
|
+
if (error) {
|
|
137
|
+
this._debug('#_initialize()', 'error detecting session from URL', error);
|
|
138
|
+
// failed login attempt via url,
|
|
139
|
+
// remove old session as in verifyOtp, signUp and signInWith*
|
|
140
|
+
await this._removeSession();
|
|
159
141
|
return { error };
|
|
160
142
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
143
|
+
const { session, redirectType } = data;
|
|
144
|
+
this._debug('#_initialize()', 'detected session in URL', session, 'redirect type', redirectType);
|
|
145
|
+
await this._saveSession(session);
|
|
146
|
+
setTimeout(async () => {
|
|
147
|
+
if (redirectType === 'recovery') {
|
|
148
|
+
await this._notifyAllSubscribers('PASSWORD_RECOVERY', session);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
await this._notifyAllSubscribers('SIGNED_IN', session);
|
|
152
|
+
}
|
|
153
|
+
}, 0);
|
|
154
|
+
return { error: null };
|
|
164
155
|
}
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
156
|
+
// no login attempt via callback url try to recover session from storage
|
|
157
|
+
await this._recoverAndRefresh();
|
|
158
|
+
return { error: null };
|
|
159
|
+
}
|
|
160
|
+
catch (error) {
|
|
161
|
+
if (isAuthError(error)) {
|
|
162
|
+
return { error };
|
|
168
163
|
}
|
|
169
|
-
|
|
170
|
-
|
|
164
|
+
return {
|
|
165
|
+
error: new AuthUnknownError('Unexpected error during initialization', error),
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
finally {
|
|
169
|
+
await this._handleVisibilityChange();
|
|
170
|
+
this._debug('#_initialize()', 'end');
|
|
171
|
+
}
|
|
171
172
|
}
|
|
172
173
|
/**
|
|
173
174
|
* Creates a new user.
|
|
@@ -321,6 +322,12 @@ export default class GoTrueClient {
|
|
|
321
322
|
* Log in an existing user by exchanging an Auth Code issued during the PKCE flow.
|
|
322
323
|
*/
|
|
323
324
|
async exchangeCodeForSession(authCode) {
|
|
325
|
+
await this.initializePromise;
|
|
326
|
+
return this._acquireLock(-1, async () => {
|
|
327
|
+
return this._exchangeCodeForSession(authCode);
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
async _exchangeCodeForSession(authCode) {
|
|
324
331
|
const codeVerifier = await getItemAsync(this.storage, `${this.storageKey}-code-verifier`);
|
|
325
332
|
const { data, error } = await _request(this.fetch, 'POST', `${this.url}/token?grant_type=pkce`, {
|
|
326
333
|
headers: this.headers,
|
|
@@ -534,6 +541,12 @@ export default class GoTrueClient {
|
|
|
534
541
|
* Requires the user to be signed-in.
|
|
535
542
|
*/
|
|
536
543
|
async reauthenticate() {
|
|
544
|
+
await this.initializePromise;
|
|
545
|
+
return await this._acquireLock(-1, async () => {
|
|
546
|
+
return await this._reauthenticate();
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
async _reauthenticate() {
|
|
537
550
|
try {
|
|
538
551
|
return await this._useSession(async (result) => {
|
|
539
552
|
const { data: { session }, error: sessionError, } = result;
|
|
@@ -603,8 +616,11 @@ export default class GoTrueClient {
|
|
|
603
616
|
* The session returned can be null if the session is not detected which can happen in the event a user is not signed-in or has logged out.
|
|
604
617
|
*/
|
|
605
618
|
async getSession() {
|
|
606
|
-
|
|
607
|
-
|
|
619
|
+
await this.initializePromise;
|
|
620
|
+
return this._acquireLock(-1, async () => {
|
|
621
|
+
return this._useSession(async (result) => {
|
|
622
|
+
return result;
|
|
623
|
+
});
|
|
608
624
|
});
|
|
609
625
|
}
|
|
610
626
|
/**
|
|
@@ -613,23 +629,49 @@ export default class GoTrueClient {
|
|
|
613
629
|
async _acquireLock(acquireTimeout, fn) {
|
|
614
630
|
this._debug('#_acquireLock', 'begin', acquireTimeout);
|
|
615
631
|
try {
|
|
616
|
-
if (
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
632
|
+
if (this.lockAcquired) {
|
|
633
|
+
const last = this.pendingInLock.length
|
|
634
|
+
? this.pendingInLock[this.pendingInLock.length - 1]
|
|
635
|
+
: Promise.resolve();
|
|
636
|
+
const result = (async () => {
|
|
637
|
+
await last;
|
|
638
|
+
return await fn();
|
|
639
|
+
})();
|
|
640
|
+
this.pendingInLock.push((async () => {
|
|
641
|
+
try {
|
|
642
|
+
await result;
|
|
643
|
+
}
|
|
644
|
+
catch (e) {
|
|
645
|
+
// we jsut care if it finished
|
|
646
|
+
}
|
|
647
|
+
})());
|
|
648
|
+
return result;
|
|
623
649
|
}
|
|
624
650
|
return await this.lock(`lock:${this.storageKey}`, acquireTimeout, async () => {
|
|
625
651
|
this._debug('#_acquireLock', 'lock acquired for storage key', this.storageKey);
|
|
626
652
|
try {
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
653
|
+
this.lockAcquired = true;
|
|
654
|
+
const result = fn();
|
|
655
|
+
this.pendingInLock.push((async () => {
|
|
656
|
+
try {
|
|
657
|
+
await result;
|
|
658
|
+
}
|
|
659
|
+
catch (e) {
|
|
660
|
+
// we just care if it finished
|
|
661
|
+
}
|
|
662
|
+
})());
|
|
663
|
+
await result;
|
|
664
|
+
// keep draining the queue until there's nothing to wait on
|
|
665
|
+
while (this.pendingInLock.length) {
|
|
666
|
+
const waitOn = [...this.pendingInLock];
|
|
667
|
+
await Promise.all(waitOn);
|
|
668
|
+
this.pendingInLock.splice(0, waitOn.length);
|
|
669
|
+
}
|
|
670
|
+
return await result;
|
|
630
671
|
}
|
|
631
672
|
finally {
|
|
632
673
|
this._debug('#_acquireLock', 'lock released for storage key', this.storageKey);
|
|
674
|
+
this.lockAcquired = false;
|
|
633
675
|
}
|
|
634
676
|
});
|
|
635
677
|
}
|
|
@@ -646,19 +688,9 @@ export default class GoTrueClient {
|
|
|
646
688
|
async _useSession(fn) {
|
|
647
689
|
this._debug('#_useSession', 'begin');
|
|
648
690
|
try {
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
const result = await this.__loadSession();
|
|
653
|
-
return await fn(result);
|
|
654
|
-
}
|
|
655
|
-
return await this._acquireLock(-1, async () => {
|
|
656
|
-
return await stackGuard('_useSession', async () => {
|
|
657
|
-
// the use of __loadSession here is the only correct use of the function!
|
|
658
|
-
const result = await this.__loadSession();
|
|
659
|
-
return await fn(result);
|
|
660
|
-
});
|
|
661
|
-
});
|
|
691
|
+
// the use of __loadSession here is the only correct use of the function!
|
|
692
|
+
const result = await this.__loadSession();
|
|
693
|
+
return await fn(result);
|
|
662
694
|
}
|
|
663
695
|
finally {
|
|
664
696
|
this._debug('#_useSession', 'end');
|
|
@@ -671,15 +703,9 @@ export default class GoTrueClient {
|
|
|
671
703
|
*/
|
|
672
704
|
async __loadSession() {
|
|
673
705
|
this._debug('#__loadSession()', 'begin');
|
|
674
|
-
if (this.
|
|
675
|
-
|
|
706
|
+
if (!this.lockAcquired) {
|
|
707
|
+
this._debug('#__loadSession()', 'used outside of an acquired lock!', new Error().stack);
|
|
676
708
|
}
|
|
677
|
-
if (isInStackGuard('_initialize')) {
|
|
678
|
-
this._debug('#__loadSession', '#_initialize recursion detected', new Error().stack);
|
|
679
|
-
}
|
|
680
|
-
// always wait for #_initialize() to finish before loading anything from
|
|
681
|
-
// storage
|
|
682
|
-
await this.initializePromise;
|
|
683
709
|
try {
|
|
684
710
|
let currentSession = null;
|
|
685
711
|
if (this.persistSession) {
|
|
@@ -724,6 +750,15 @@ export default class GoTrueClient {
|
|
|
724
750
|
* @param jwt Takes in an optional access token jwt. If no jwt is provided, getUser() will attempt to get the jwt from the current session.
|
|
725
751
|
*/
|
|
726
752
|
async getUser(jwt) {
|
|
753
|
+
if (jwt) {
|
|
754
|
+
return await this._getUser(jwt);
|
|
755
|
+
}
|
|
756
|
+
await this.initializePromise;
|
|
757
|
+
return this._acquireLock(-1, async () => {
|
|
758
|
+
return await this._getUser();
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
async _getUser(jwt) {
|
|
727
762
|
try {
|
|
728
763
|
if (jwt) {
|
|
729
764
|
return await _request(this.fetch, 'GET', `${this.url}/user`, {
|
|
@@ -756,6 +791,12 @@ export default class GoTrueClient {
|
|
|
756
791
|
* Updates user data for a logged in user.
|
|
757
792
|
*/
|
|
758
793
|
async updateUser(attributes, options = {}) {
|
|
794
|
+
await this.initializePromise;
|
|
795
|
+
return await this._acquireLock(-1, async () => {
|
|
796
|
+
return await this._updateUser(attributes, options);
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
async _updateUser(attributes, options = {}) {
|
|
759
800
|
try {
|
|
760
801
|
return await this._useSession(async (result) => {
|
|
761
802
|
const { data: sessionData, error: sessionError } = result;
|
|
@@ -800,6 +841,12 @@ export default class GoTrueClient {
|
|
|
800
841
|
* @param currentSession The current session that minimally contains an access token and refresh token.
|
|
801
842
|
*/
|
|
802
843
|
async setSession(currentSession) {
|
|
844
|
+
await this.initializePromise;
|
|
845
|
+
return await this._acquireLock(-1, async () => {
|
|
846
|
+
return await this._setSession(currentSession);
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
async _setSession(currentSession) {
|
|
803
850
|
try {
|
|
804
851
|
if (!currentSession.access_token || !currentSession.refresh_token) {
|
|
805
852
|
throw new AuthSessionMissingError();
|
|
@@ -824,7 +871,7 @@ export default class GoTrueClient {
|
|
|
824
871
|
session = refreshedSession;
|
|
825
872
|
}
|
|
826
873
|
else {
|
|
827
|
-
const { data, error } = await this.
|
|
874
|
+
const { data, error } = await this._getUser(currentSession.access_token);
|
|
828
875
|
if (error) {
|
|
829
876
|
throw error;
|
|
830
877
|
}
|
|
@@ -855,6 +902,12 @@ export default class GoTrueClient {
|
|
|
855
902
|
* @param currentSession The current session. If passed in, it must contain a refresh token.
|
|
856
903
|
*/
|
|
857
904
|
async refreshSession(currentSession) {
|
|
905
|
+
await this.initializePromise;
|
|
906
|
+
return await this._acquireLock(-1, async () => {
|
|
907
|
+
return await this._refreshSession(currentSession);
|
|
908
|
+
});
|
|
909
|
+
}
|
|
910
|
+
async _refreshSession(currentSession) {
|
|
858
911
|
try {
|
|
859
912
|
return await this._useSession(async (result) => {
|
|
860
913
|
var _a;
|
|
@@ -902,7 +955,7 @@ export default class GoTrueClient {
|
|
|
902
955
|
if (isPKCEFlow) {
|
|
903
956
|
if (!params.code)
|
|
904
957
|
throw new AuthPKCEGrantCodeExchangeError('No code detected.');
|
|
905
|
-
const { data, error } = await this.
|
|
958
|
+
const { data, error } = await this._exchangeCodeForSession(params.code);
|
|
906
959
|
if (error)
|
|
907
960
|
throw error;
|
|
908
961
|
const url = new URL(window.location.href);
|
|
@@ -923,7 +976,7 @@ export default class GoTrueClient {
|
|
|
923
976
|
const timeNow = Math.round(Date.now() / 1000);
|
|
924
977
|
const expiresIn = parseInt(expires_in);
|
|
925
978
|
const expires_at = timeNow + expiresIn;
|
|
926
|
-
const { data, error } = await this.
|
|
979
|
+
const { data, error } = await this._getUser(access_token);
|
|
927
980
|
if (error)
|
|
928
981
|
throw error;
|
|
929
982
|
const session = {
|
|
@@ -972,7 +1025,13 @@ export default class GoTrueClient {
|
|
|
972
1025
|
*
|
|
973
1026
|
* If using others scope, no `SIGNED_OUT` event is fired!
|
|
974
1027
|
*/
|
|
975
|
-
async signOut(
|
|
1028
|
+
async signOut(options = { scope: 'global' }) {
|
|
1029
|
+
await this.initializePromise;
|
|
1030
|
+
return await this._acquireLock(-1, async () => {
|
|
1031
|
+
return await this._signOut(options);
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
async _signOut({ scope } = { scope: 'global' }) {
|
|
976
1035
|
return await this._useSession(async (result) => {
|
|
977
1036
|
var _a;
|
|
978
1037
|
const { data, error: sessionError } = result;
|
|
@@ -1014,7 +1073,12 @@ export default class GoTrueClient {
|
|
|
1014
1073
|
};
|
|
1015
1074
|
this._debug('#onAuthStateChange()', 'registered callback with id', id);
|
|
1016
1075
|
this.stateChangeEmitters.set(id, subscription);
|
|
1017
|
-
|
|
1076
|
+
(async () => {
|
|
1077
|
+
await this.initializePromise;
|
|
1078
|
+
await this._acquireLock(-1, async () => {
|
|
1079
|
+
this._emitInitialSession(id);
|
|
1080
|
+
});
|
|
1081
|
+
})();
|
|
1018
1082
|
return { data: { subscription } };
|
|
1019
1083
|
}
|
|
1020
1084
|
async _emitInitialSession(id) {
|
|
@@ -1375,29 +1439,41 @@ export default class GoTrueClient {
|
|
|
1375
1439
|
async _autoRefreshTokenTick() {
|
|
1376
1440
|
this._debug('#_autoRefreshTokenTick()', 'begin');
|
|
1377
1441
|
try {
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1442
|
+
await this._acquireLock(0, async () => {
|
|
1443
|
+
try {
|
|
1444
|
+
const now = Date.now();
|
|
1445
|
+
try {
|
|
1446
|
+
return await this._useSession(async (result) => {
|
|
1447
|
+
const { data: { session }, } = result;
|
|
1448
|
+
if (!session || !session.refresh_token || !session.expires_at) {
|
|
1449
|
+
this._debug('#_autoRefreshTokenTick()', 'no session');
|
|
1450
|
+
return;
|
|
1451
|
+
}
|
|
1452
|
+
// session will expire in this many ticks (or has already expired if <= 0)
|
|
1453
|
+
const expiresInTicks = Math.floor((session.expires_at * 1000 - now) / AUTO_REFRESH_TICK_DURATION);
|
|
1454
|
+
this._debug('#_autoRefreshTokenTick()', `access token expires in ${expiresInTicks} ticks, a tick lasts ${AUTO_REFRESH_TICK_DURATION}ms, refresh threshold is ${AUTO_REFRESH_TICK_THRESHOLD} ticks`);
|
|
1455
|
+
if (expiresInTicks <= AUTO_REFRESH_TICK_THRESHOLD) {
|
|
1456
|
+
await this._callRefreshToken(session.refresh_token);
|
|
1457
|
+
}
|
|
1458
|
+
});
|
|
1385
1459
|
}
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
this._debug('#_autoRefreshTokenTick()', `access token expires in ${expiresInTicks} ticks, a tick lasts ${AUTO_REFRESH_TICK_DURATION}ms, refresh threshold is ${AUTO_REFRESH_TICK_THRESHOLD} ticks`);
|
|
1389
|
-
if (expiresInTicks <= AUTO_REFRESH_TICK_THRESHOLD) {
|
|
1390
|
-
await this._callRefreshToken(session.refresh_token);
|
|
1460
|
+
catch (e) {
|
|
1461
|
+
console.error('Auto refresh tick failed with error. This is likely a transient error.', e);
|
|
1391
1462
|
}
|
|
1392
|
-
}
|
|
1463
|
+
}
|
|
1464
|
+
finally {
|
|
1465
|
+
this._debug('#_autoRefreshTokenTick()', 'end');
|
|
1466
|
+
}
|
|
1467
|
+
});
|
|
1468
|
+
}
|
|
1469
|
+
catch (e) {
|
|
1470
|
+
if (e.isAcquireTimeout) {
|
|
1471
|
+
this._debug('auto refresh token tick lock not available');
|
|
1393
1472
|
}
|
|
1394
|
-
|
|
1395
|
-
|
|
1473
|
+
else {
|
|
1474
|
+
throw e;
|
|
1396
1475
|
}
|
|
1397
1476
|
}
|
|
1398
|
-
finally {
|
|
1399
|
-
this._debug('#_autoRefreshTokenTick()', 'end');
|
|
1400
|
-
}
|
|
1401
1477
|
}
|
|
1402
1478
|
/**
|
|
1403
1479
|
* Registers callbacks on the browser / platform, which in-turn run
|
|
@@ -1616,7 +1692,7 @@ export default class GoTrueClient {
|
|
|
1616
1692
|
* {@see GoTrueMFAApi#listFactors}
|
|
1617
1693
|
*/
|
|
1618
1694
|
async _listFactors() {
|
|
1619
|
-
const { data: { user }, error: userError, } = await this.
|
|
1695
|
+
const { data: { user }, error: userError, } = await this._getUser();
|
|
1620
1696
|
if (userError) {
|
|
1621
1697
|
return { data: null, error: userError };
|
|
1622
1698
|
}
|