@supabase/gotrue-js 2.42.0 → 2.43.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 +13 -0
- package/dist/main/GoTrueClient.d.ts.map +1 -1
- package/dist/main/GoTrueClient.js +280 -221
- package/dist/main/GoTrueClient.js.map +1 -1
- package/dist/main/lib/helpers.d.ts +23 -0
- package/dist/main/lib/helpers.d.ts.map +1 -1
- package/dist/main/lib/helpers.js +94 -1
- package/dist/main/lib/helpers.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 +13 -0
- package/dist/module/GoTrueClient.d.ts.map +1 -1
- package/dist/module/GoTrueClient.js +281 -222
- package/dist/module/GoTrueClient.js.map +1 -1
- package/dist/module/lib/helpers.d.ts +23 -0
- package/dist/module/lib/helpers.d.ts.map +1 -1
- package/dist/module/lib/helpers.js +91 -0
- package/dist/module/lib/helpers.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 +337 -250
- package/src/lib/helpers.ts +111 -0
- package/src/lib/version.ts +1 -1
|
@@ -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, getParameterByName, isBrowser, removeItemAsync, resolveFetch, setItemAsync, uuid, retryable, sleep, generatePKCEVerifier, generatePKCEChallenge, supportsLocalStorage, } from './lib/helpers';
|
|
5
|
+
import { decodeJWTPayload, Deferred, getItemAsync, getParameterByName, isBrowser, removeItemAsync, resolveFetch, setItemAsync, uuid, retryable, sleep, generatePKCEVerifier, generatePKCEChallenge, supportsLocalStorage, stackGuard, isInStackGuard, } from './lib/helpers';
|
|
6
6
|
import localStorageAdapter from './lib/local-storage';
|
|
7
7
|
import { polyfillGlobalThis } from './lib/polyfills';
|
|
8
8
|
polyfillGlobalThis(); // Make "globalThis" available
|
|
@@ -104,10 +104,10 @@ export default class GoTrueClient {
|
|
|
104
104
|
* manually when checking for an error from an auth redirect (oauth, magiclink, password recovery, etc).
|
|
105
105
|
*/
|
|
106
106
|
initialize() {
|
|
107
|
-
if (
|
|
108
|
-
this.initializePromise
|
|
107
|
+
if (this.initializePromise) {
|
|
108
|
+
return this.initializePromise;
|
|
109
109
|
}
|
|
110
|
-
return this.
|
|
110
|
+
return this._initialize();
|
|
111
111
|
}
|
|
112
112
|
/**
|
|
113
113
|
* IMPORTANT:
|
|
@@ -117,49 +117,52 @@ export default class GoTrueClient {
|
|
|
117
117
|
*/
|
|
118
118
|
async _initialize() {
|
|
119
119
|
if (this.initializePromise) {
|
|
120
|
-
|
|
120
|
+
throw new Error('Double call of #_initialize()');
|
|
121
121
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const { session, redirectType } = data;
|
|
135
|
-
this._debug('#_initialize()', 'detected session in URL', session, 'redirect type', redirectType);
|
|
136
|
-
await this._saveSession(session);
|
|
137
|
-
setTimeout(async () => {
|
|
138
|
-
if (redirectType === 'recovery') {
|
|
139
|
-
await this._notifyAllSubscribers('PASSWORD_RECOVERY', session);
|
|
140
|
-
}
|
|
141
|
-
else {
|
|
142
|
-
await this._notifyAllSubscribers('SIGNED_IN', session);
|
|
122
|
+
this.initializePromise = stackGuard('_initialize', async () => {
|
|
123
|
+
try {
|
|
124
|
+
const isPKCEFlow = isBrowser() ? await this._isPKCEFlow() : false;
|
|
125
|
+
this._debug('#_initialize()', 'begin', 'is PKCE flow', isPKCEFlow);
|
|
126
|
+
if (isPKCEFlow || (this.detectSessionInUrl && this._isImplicitGrantFlow())) {
|
|
127
|
+
const { data, error } = await this._getSessionFromUrl(isPKCEFlow);
|
|
128
|
+
if (error) {
|
|
129
|
+
this._debug('#_initialize()', 'error detecting session from URL', error);
|
|
130
|
+
// failed login attempt via url,
|
|
131
|
+
// remove old session as in verifyOtp, signUp and signInWith*
|
|
132
|
+
await this._removeSession();
|
|
133
|
+
return { error };
|
|
143
134
|
}
|
|
144
|
-
|
|
135
|
+
const { session, redirectType } = data;
|
|
136
|
+
this._debug('#_initialize()', 'detected session in URL', session, 'redirect type', redirectType);
|
|
137
|
+
await this._saveSession(session);
|
|
138
|
+
setTimeout(async () => {
|
|
139
|
+
if (redirectType === 'recovery') {
|
|
140
|
+
await this._notifyAllSubscribers('PASSWORD_RECOVERY', session);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
await this._notifyAllSubscribers('SIGNED_IN', session);
|
|
144
|
+
}
|
|
145
|
+
}, 0);
|
|
146
|
+
return { error: null };
|
|
147
|
+
}
|
|
148
|
+
// no login attempt via callback url try to recover session from storage
|
|
149
|
+
await this._recoverAndRefresh();
|
|
145
150
|
return { error: null };
|
|
146
151
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
catch (error) {
|
|
153
|
+
if (isAuthError(error)) {
|
|
154
|
+
return { error };
|
|
155
|
+
}
|
|
156
|
+
return {
|
|
157
|
+
error: new AuthUnknownError('Unexpected error during initialization', error),
|
|
158
|
+
};
|
|
154
159
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
this._debug('#_initialize()', 'end');
|
|
162
|
-
}
|
|
160
|
+
finally {
|
|
161
|
+
await this._handleVisibilityChange();
|
|
162
|
+
this._debug('#_initialize()', 'end');
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
return await this.initializePromise;
|
|
163
166
|
}
|
|
164
167
|
/**
|
|
165
168
|
* Creates a new user.
|
|
@@ -521,16 +524,18 @@ export default class GoTrueClient {
|
|
|
521
524
|
*/
|
|
522
525
|
async reauthenticate() {
|
|
523
526
|
try {
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
527
|
+
return await this._useSession(async (result) => {
|
|
528
|
+
const { data: { session }, error: sessionError, } = result;
|
|
529
|
+
if (sessionError)
|
|
530
|
+
throw sessionError;
|
|
531
|
+
if (!session)
|
|
532
|
+
throw new AuthSessionMissingError();
|
|
533
|
+
const { error } = await _request(this.fetch, 'GET', `${this.url}/reauthenticate`, {
|
|
534
|
+
headers: this.headers,
|
|
535
|
+
jwt: session.access_token,
|
|
536
|
+
});
|
|
537
|
+
return { data: { user: null, session: null }, error };
|
|
532
538
|
});
|
|
533
|
-
return { data: { user: null, session: null }, error };
|
|
534
539
|
}
|
|
535
540
|
catch (error) {
|
|
536
541
|
if (isAuthError(error)) {
|
|
@@ -587,10 +592,42 @@ export default class GoTrueClient {
|
|
|
587
592
|
* 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.
|
|
588
593
|
*/
|
|
589
594
|
async getSession() {
|
|
595
|
+
return this._useSession(async (result) => {
|
|
596
|
+
return result;
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Use instead of {@link #getSession} inside the library. It is
|
|
601
|
+
* semantically usually what you want, as getting a session involves some
|
|
602
|
+
* processing afterwards that requires only one client operating on the
|
|
603
|
+
* session at once across multiple tabs or processes.
|
|
604
|
+
*/
|
|
605
|
+
async _useSession(fn) {
|
|
606
|
+
return await stackGuard('_useSession', async () => {
|
|
607
|
+
// the use of __loadSession here is the only correct use of the function!
|
|
608
|
+
const result = await this.__loadSession();
|
|
609
|
+
return await fn(result);
|
|
610
|
+
});
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* NEVER USE DIRECTLY!
|
|
614
|
+
*
|
|
615
|
+
* Always use {@link #_useSession}.
|
|
616
|
+
*/
|
|
617
|
+
async __loadSession() {
|
|
618
|
+
this._debug('#__loadSession()', 'begin');
|
|
619
|
+
if (this.logDebugMessages && !isInStackGuard('_useSession')) {
|
|
620
|
+
throw new Error('Please use #_useSession()');
|
|
621
|
+
}
|
|
590
622
|
// make sure we've read the session from the url if there is one
|
|
591
623
|
// save to just await, as long we make sure _initialize() never throws
|
|
592
|
-
|
|
593
|
-
|
|
624
|
+
if (!isInStackGuard('_initialize')) {
|
|
625
|
+
// only wait when not called from within #_initialize() since it's
|
|
626
|
+
// waiting for itself. one such pathway is #_initialize() ->
|
|
627
|
+
// #_handleVisibilityChange() -> #_onVisbilityChanged() ->
|
|
628
|
+
// #_loadSession().
|
|
629
|
+
await this.initializePromise;
|
|
630
|
+
}
|
|
594
631
|
try {
|
|
595
632
|
let currentSession = null;
|
|
596
633
|
if (this.persistSession) {
|
|
@@ -616,7 +653,7 @@ export default class GoTrueClient {
|
|
|
616
653
|
const hasExpired = currentSession.expires_at
|
|
617
654
|
? currentSession.expires_at <= Date.now() / 1000
|
|
618
655
|
: false;
|
|
619
|
-
this._debug('#
|
|
656
|
+
this._debug('#__loadSession()', `session has${hasExpired ? '' : ' not'} expired`, 'expires_at', currentSession.expires_at);
|
|
620
657
|
if (!hasExpired) {
|
|
621
658
|
return { data: { session: currentSession }, error: null };
|
|
622
659
|
}
|
|
@@ -627,7 +664,7 @@ export default class GoTrueClient {
|
|
|
627
664
|
return { data: { session }, error: null };
|
|
628
665
|
}
|
|
629
666
|
finally {
|
|
630
|
-
this._debug('#
|
|
667
|
+
this._debug('#__loadSession()', 'end');
|
|
631
668
|
}
|
|
632
669
|
}
|
|
633
670
|
/**
|
|
@@ -635,20 +672,22 @@ export default class GoTrueClient {
|
|
|
635
672
|
* @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.
|
|
636
673
|
*/
|
|
637
674
|
async getUser(jwt) {
|
|
638
|
-
var _a, _b;
|
|
639
675
|
try {
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
if (
|
|
643
|
-
|
|
676
|
+
return await this._useSession(async (result) => {
|
|
677
|
+
var _a, _b;
|
|
678
|
+
if (!jwt) {
|
|
679
|
+
const { data, error } = result;
|
|
680
|
+
if (error) {
|
|
681
|
+
throw error;
|
|
682
|
+
}
|
|
683
|
+
// Default to Authorization header if there is no existing session
|
|
684
|
+
jwt = (_b = (_a = data.session) === null || _a === void 0 ? void 0 : _a.access_token) !== null && _b !== void 0 ? _b : undefined;
|
|
644
685
|
}
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
jwt: jwt,
|
|
651
|
-
xform: _userResponse,
|
|
686
|
+
return await _request(this.fetch, 'GET', `${this.url}/user`, {
|
|
687
|
+
headers: this.headers,
|
|
688
|
+
jwt: jwt,
|
|
689
|
+
xform: _userResponse,
|
|
690
|
+
});
|
|
652
691
|
});
|
|
653
692
|
}
|
|
654
693
|
catch (error) {
|
|
@@ -663,27 +702,29 @@ export default class GoTrueClient {
|
|
|
663
702
|
*/
|
|
664
703
|
async updateUser(attributes, options = {}) {
|
|
665
704
|
try {
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
705
|
+
return await this._useSession(async (result) => {
|
|
706
|
+
const { data: sessionData, error: sessionError } = result;
|
|
707
|
+
if (sessionError) {
|
|
708
|
+
throw sessionError;
|
|
709
|
+
}
|
|
710
|
+
if (!sessionData.session) {
|
|
711
|
+
throw new AuthSessionMissingError();
|
|
712
|
+
}
|
|
713
|
+
const session = sessionData.session;
|
|
714
|
+
const { data, error: userError } = await _request(this.fetch, 'PUT', `${this.url}/user`, {
|
|
715
|
+
headers: this.headers,
|
|
716
|
+
redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo,
|
|
717
|
+
body: attributes,
|
|
718
|
+
jwt: session.access_token,
|
|
719
|
+
xform: _userResponse,
|
|
720
|
+
});
|
|
721
|
+
if (userError)
|
|
722
|
+
throw userError;
|
|
723
|
+
session.user = data.user;
|
|
724
|
+
await this._saveSession(session);
|
|
725
|
+
await this._notifyAllSubscribers('USER_UPDATED', session);
|
|
726
|
+
return { data: { user: session.user }, error: null };
|
|
680
727
|
});
|
|
681
|
-
if (userError)
|
|
682
|
-
throw userError;
|
|
683
|
-
session.user = data.user;
|
|
684
|
-
await this._saveSession(session);
|
|
685
|
-
await this._notifyAllSubscribers('USER_UPDATED', session);
|
|
686
|
-
return { data: { user: session.user }, error: null };
|
|
687
728
|
}
|
|
688
729
|
catch (error) {
|
|
689
730
|
if (isAuthError(error)) {
|
|
@@ -759,26 +800,28 @@ export default class GoTrueClient {
|
|
|
759
800
|
* @param currentSession The current session. If passed in, it must contain a refresh token.
|
|
760
801
|
*/
|
|
761
802
|
async refreshSession(currentSession) {
|
|
762
|
-
var _a;
|
|
763
803
|
try {
|
|
764
|
-
|
|
765
|
-
|
|
804
|
+
return await this._useSession(async (result) => {
|
|
805
|
+
var _a;
|
|
806
|
+
if (!currentSession) {
|
|
807
|
+
const { data, error } = result;
|
|
808
|
+
if (error) {
|
|
809
|
+
throw error;
|
|
810
|
+
}
|
|
811
|
+
currentSession = (_a = data.session) !== null && _a !== void 0 ? _a : undefined;
|
|
812
|
+
}
|
|
813
|
+
if (!(currentSession === null || currentSession === void 0 ? void 0 : currentSession.refresh_token)) {
|
|
814
|
+
throw new AuthSessionMissingError();
|
|
815
|
+
}
|
|
816
|
+
const { session, error } = await this._callRefreshToken(currentSession.refresh_token);
|
|
766
817
|
if (error) {
|
|
767
|
-
|
|
818
|
+
return { data: { user: null, session: null }, error: error };
|
|
768
819
|
}
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
}
|
|
774
|
-
const { session, error } = await this._callRefreshToken(currentSession.refresh_token);
|
|
775
|
-
if (error) {
|
|
776
|
-
return { data: { user: null, session: null }, error: error };
|
|
777
|
-
}
|
|
778
|
-
if (!session) {
|
|
779
|
-
return { data: { user: null, session: null }, error: null };
|
|
780
|
-
}
|
|
781
|
-
return { data: { user: session.user, session }, error: null };
|
|
820
|
+
if (!session) {
|
|
821
|
+
return { data: { user: null, session: null }, error: null };
|
|
822
|
+
}
|
|
823
|
+
return { data: { user: session.user, session }, error: null };
|
|
824
|
+
});
|
|
782
825
|
}
|
|
783
826
|
catch (error) {
|
|
784
827
|
if (isAuthError(error)) {
|
|
@@ -892,28 +935,30 @@ export default class GoTrueClient {
|
|
|
892
935
|
* If using others scope, no `SIGNED_OUT` event is fired!
|
|
893
936
|
*/
|
|
894
937
|
async signOut({ scope } = { scope: 'global' }) {
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
938
|
+
return await this._useSession(async (result) => {
|
|
939
|
+
var _a;
|
|
940
|
+
const { data, error: sessionError } = result;
|
|
941
|
+
if (sessionError) {
|
|
942
|
+
return { error: sessionError };
|
|
943
|
+
}
|
|
944
|
+
const accessToken = (_a = data.session) === null || _a === void 0 ? void 0 : _a.access_token;
|
|
945
|
+
if (accessToken) {
|
|
946
|
+
const { error } = await this.admin.signOut(accessToken, scope);
|
|
947
|
+
if (error) {
|
|
948
|
+
// ignore 404s since user might not exist anymore
|
|
949
|
+
// ignore 401s since an invalid or expired JWT should sign out the current session
|
|
950
|
+
if (!(isAuthApiError(error) && (error.status === 404 || error.status === 401))) {
|
|
951
|
+
return { error };
|
|
952
|
+
}
|
|
908
953
|
}
|
|
909
954
|
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
955
|
+
if (scope !== 'others') {
|
|
956
|
+
await this._removeSession();
|
|
957
|
+
await removeItemAsync(this.storage, `${this.storageKey}-code-verifier`);
|
|
958
|
+
await this._notifyAllSubscribers('SIGNED_OUT', null);
|
|
959
|
+
}
|
|
960
|
+
return { error: null };
|
|
961
|
+
});
|
|
917
962
|
}
|
|
918
963
|
/**
|
|
919
964
|
* Receive a notification every time an auth event happens.
|
|
@@ -935,19 +980,21 @@ export default class GoTrueClient {
|
|
|
935
980
|
return { data: { subscription } };
|
|
936
981
|
}
|
|
937
982
|
async _emitInitialSession(id) {
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
983
|
+
return await this._useSession(async (result) => {
|
|
984
|
+
var _a, _b;
|
|
985
|
+
try {
|
|
986
|
+
const { data: { session }, error, } = result;
|
|
987
|
+
if (error)
|
|
988
|
+
throw error;
|
|
989
|
+
await ((_a = this.stateChangeEmitters.get(id)) === null || _a === void 0 ? void 0 : _a.callback('INITIAL_SESSION', session));
|
|
990
|
+
this._debug('INITIAL_SESSION', 'callback id', id, 'session', session);
|
|
991
|
+
}
|
|
992
|
+
catch (err) {
|
|
993
|
+
await ((_b = this.stateChangeEmitters.get(id)) === null || _b === void 0 ? void 0 : _b.callback('INITIAL_SESSION', null));
|
|
994
|
+
this._debug('INITIAL_SESSION', 'callback id', id, 'error', err);
|
|
995
|
+
console.error(err);
|
|
996
|
+
}
|
|
997
|
+
});
|
|
951
998
|
}
|
|
952
999
|
/**
|
|
953
1000
|
* Sends a password reset request to an email address.
|
|
@@ -1287,17 +1334,19 @@ export default class GoTrueClient {
|
|
|
1287
1334
|
try {
|
|
1288
1335
|
const now = Date.now();
|
|
1289
1336
|
try {
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1337
|
+
return await this._useSession(async (result) => {
|
|
1338
|
+
const { data: { session }, } = result;
|
|
1339
|
+
if (!session || !session.refresh_token || !session.expires_at) {
|
|
1340
|
+
this._debug('#_autoRefreshTokenTick()', 'no session');
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
// session will expire in this many ticks (or has already expired if <= 0)
|
|
1344
|
+
const expiresInTicks = Math.floor((session.expires_at * 1000 - now) / AUTO_REFRESH_TICK_DURATION);
|
|
1345
|
+
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`);
|
|
1346
|
+
if (expiresInTicks <= AUTO_REFRESH_TICK_THRESHOLD) {
|
|
1347
|
+
await this._callRefreshToken(session.refresh_token);
|
|
1348
|
+
}
|
|
1349
|
+
});
|
|
1301
1350
|
}
|
|
1302
1351
|
catch (e) {
|
|
1303
1352
|
console.error('Auto refresh tick failed with error. This is likely a transient error.', e);
|
|
@@ -1389,15 +1438,17 @@ export default class GoTrueClient {
|
|
|
1389
1438
|
return `${this.url}/authorize?${urlParams.join('&')}`;
|
|
1390
1439
|
}
|
|
1391
1440
|
async _unenroll(params) {
|
|
1392
|
-
var _a;
|
|
1393
1441
|
try {
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1442
|
+
return await this._useSession(async (result) => {
|
|
1443
|
+
var _a;
|
|
1444
|
+
const { data: sessionData, error: sessionError } = result;
|
|
1445
|
+
if (sessionError) {
|
|
1446
|
+
return { data: null, error: sessionError };
|
|
1447
|
+
}
|
|
1448
|
+
return await _request(this.fetch, 'DELETE', `${this.url}/factors/${params.factorId}`, {
|
|
1449
|
+
headers: this.headers,
|
|
1450
|
+
jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token,
|
|
1451
|
+
});
|
|
1401
1452
|
});
|
|
1402
1453
|
}
|
|
1403
1454
|
catch (error) {
|
|
@@ -1411,28 +1462,30 @@ export default class GoTrueClient {
|
|
|
1411
1462
|
* {@see GoTrueMFAApi#enroll}
|
|
1412
1463
|
*/
|
|
1413
1464
|
async _enroll(params) {
|
|
1414
|
-
var _a, _b;
|
|
1415
1465
|
try {
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1466
|
+
return await this._useSession(async (result) => {
|
|
1467
|
+
var _a, _b;
|
|
1468
|
+
const { data: sessionData, error: sessionError } = result;
|
|
1469
|
+
if (sessionError) {
|
|
1470
|
+
return { data: null, error: sessionError };
|
|
1471
|
+
}
|
|
1472
|
+
const { data, error } = await _request(this.fetch, 'POST', `${this.url}/factors`, {
|
|
1473
|
+
body: {
|
|
1474
|
+
friendly_name: params.friendlyName,
|
|
1475
|
+
factor_type: params.factorType,
|
|
1476
|
+
issuer: params.issuer,
|
|
1477
|
+
},
|
|
1478
|
+
headers: this.headers,
|
|
1479
|
+
jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token,
|
|
1480
|
+
});
|
|
1481
|
+
if (error) {
|
|
1482
|
+
return { data: null, error };
|
|
1483
|
+
}
|
|
1484
|
+
if ((_b = data === null || data === void 0 ? void 0 : data.totp) === null || _b === void 0 ? void 0 : _b.qr_code) {
|
|
1485
|
+
data.totp.qr_code = `data:image/svg+xml;utf-8,${data.totp.qr_code}`;
|
|
1486
|
+
}
|
|
1487
|
+
return { data, error: null };
|
|
1428
1488
|
});
|
|
1429
|
-
if (error) {
|
|
1430
|
-
return { data: null, error };
|
|
1431
|
-
}
|
|
1432
|
-
if ((_b = data === null || data === void 0 ? void 0 : data.totp) === null || _b === void 0 ? void 0 : _b.qr_code) {
|
|
1433
|
-
data.totp.qr_code = `data:image/svg+xml;utf-8,${data.totp.qr_code}`;
|
|
1434
|
-
}
|
|
1435
|
-
return { data, error: null };
|
|
1436
1489
|
}
|
|
1437
1490
|
catch (error) {
|
|
1438
1491
|
if (isAuthError(error)) {
|
|
@@ -1445,23 +1498,25 @@ export default class GoTrueClient {
|
|
|
1445
1498
|
* {@see GoTrueMFAApi#verify}
|
|
1446
1499
|
*/
|
|
1447
1500
|
async _verify(params) {
|
|
1448
|
-
var _a;
|
|
1449
1501
|
try {
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1502
|
+
return await this._useSession(async (result) => {
|
|
1503
|
+
var _a;
|
|
1504
|
+
const { data: sessionData, error: sessionError } = result;
|
|
1505
|
+
if (sessionError) {
|
|
1506
|
+
return { data: null, error: sessionError };
|
|
1507
|
+
}
|
|
1508
|
+
const { data, error } = await _request(this.fetch, 'POST', `${this.url}/factors/${params.factorId}/verify`, {
|
|
1509
|
+
body: { code: params.code, challenge_id: params.challengeId },
|
|
1510
|
+
headers: this.headers,
|
|
1511
|
+
jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token,
|
|
1512
|
+
});
|
|
1513
|
+
if (error) {
|
|
1514
|
+
return { data: null, error };
|
|
1515
|
+
}
|
|
1516
|
+
await this._saveSession(Object.assign({ expires_at: Math.round(Date.now() / 1000) + data.expires_in }, data));
|
|
1517
|
+
await this._notifyAllSubscribers('MFA_CHALLENGE_VERIFIED', data);
|
|
1518
|
+
return { data, error };
|
|
1458
1519
|
});
|
|
1459
|
-
if (error) {
|
|
1460
|
-
return { data: null, error };
|
|
1461
|
-
}
|
|
1462
|
-
await this._saveSession(Object.assign({ expires_at: Math.round(Date.now() / 1000) + data.expires_in }, data));
|
|
1463
|
-
await this._notifyAllSubscribers('MFA_CHALLENGE_VERIFIED', data);
|
|
1464
|
-
return { data, error };
|
|
1465
1520
|
}
|
|
1466
1521
|
catch (error) {
|
|
1467
1522
|
if (isAuthError(error)) {
|
|
@@ -1474,15 +1529,17 @@ export default class GoTrueClient {
|
|
|
1474
1529
|
* {@see GoTrueMFAApi#challenge}
|
|
1475
1530
|
*/
|
|
1476
1531
|
async _challenge(params) {
|
|
1477
|
-
var _a;
|
|
1478
1532
|
try {
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1533
|
+
return await this._useSession(async (result) => {
|
|
1534
|
+
var _a;
|
|
1535
|
+
const { data: sessionData, error: sessionError } = result;
|
|
1536
|
+
if (sessionError) {
|
|
1537
|
+
return { data: null, error: sessionError };
|
|
1538
|
+
}
|
|
1539
|
+
return await _request(this.fetch, 'POST', `${this.url}/factors/${params.factorId}/challenge`, {
|
|
1540
|
+
headers: this.headers,
|
|
1541
|
+
jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token,
|
|
1542
|
+
});
|
|
1486
1543
|
});
|
|
1487
1544
|
}
|
|
1488
1545
|
catch (error) {
|
|
@@ -1530,29 +1587,31 @@ export default class GoTrueClient {
|
|
|
1530
1587
|
* {@see GoTrueMFAApi#getAuthenticatorAssuranceLevel}
|
|
1531
1588
|
*/
|
|
1532
1589
|
async _getAuthenticatorAssuranceLevel() {
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1590
|
+
return await this._useSession(async (result) => {
|
|
1591
|
+
var _a, _b;
|
|
1592
|
+
const { data: { session }, error: sessionError, } = result;
|
|
1593
|
+
if (sessionError) {
|
|
1594
|
+
return { data: null, error: sessionError };
|
|
1595
|
+
}
|
|
1596
|
+
if (!session) {
|
|
1597
|
+
return {
|
|
1598
|
+
data: { currentLevel: null, nextLevel: null, currentAuthenticationMethods: [] },
|
|
1599
|
+
error: null,
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1602
|
+
const payload = this._decodeJWT(session.access_token);
|
|
1603
|
+
let currentLevel = null;
|
|
1604
|
+
if (payload.aal) {
|
|
1605
|
+
currentLevel = payload.aal;
|
|
1606
|
+
}
|
|
1607
|
+
let nextLevel = currentLevel;
|
|
1608
|
+
const verifiedFactors = (_b = (_a = session.user.factors) === null || _a === void 0 ? void 0 : _a.filter((factor) => factor.status === 'verified')) !== null && _b !== void 0 ? _b : [];
|
|
1609
|
+
if (verifiedFactors.length > 0) {
|
|
1610
|
+
nextLevel = 'aal2';
|
|
1611
|
+
}
|
|
1612
|
+
const currentAuthenticationMethods = payload.amr || [];
|
|
1613
|
+
return { data: { currentLevel, nextLevel, currentAuthenticationMethods }, error: null };
|
|
1614
|
+
});
|
|
1556
1615
|
}
|
|
1557
1616
|
}
|
|
1558
1617
|
GoTrueClient.nextInstanceID = 0;
|