@supabase/gotrue-js 2.41.0 → 2.42.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 +0 -13
- package/dist/main/GoTrueClient.d.ts.map +1 -1
- package/dist/main/GoTrueClient.js +180 -229
- package/dist/main/GoTrueClient.js.map +1 -1
- package/dist/main/lib/helpers.d.ts +0 -23
- package/dist/main/lib/helpers.d.ts.map +1 -1
- package/dist/main/lib/helpers.js +1 -94
- 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 +0 -13
- package/dist/module/GoTrueClient.d.ts.map +1 -1
- package/dist/module/GoTrueClient.js +181 -230
- package/dist/module/GoTrueClient.js.map +1 -1
- package/dist/module/lib/helpers.d.ts +0 -23
- package/dist/module/lib/helpers.d.ts.map +1 -1
- package/dist/module/lib/helpers.js +0 -91
- 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 +205 -280
- package/src/lib/helpers.ts +0 -111
- package/src/lib/version.ts +1 -1
package/src/GoTrueClient.ts
CHANGED
|
@@ -29,8 +29,6 @@ import {
|
|
|
29
29
|
generatePKCEVerifier,
|
|
30
30
|
generatePKCEChallenge,
|
|
31
31
|
supportsLocalStorage,
|
|
32
|
-
stackGuard,
|
|
33
|
-
isInStackGuard,
|
|
34
32
|
} from './lib/helpers'
|
|
35
33
|
import localStorageAdapter from './lib/local-storage'
|
|
36
34
|
import { polyfillGlobalThis } from './lib/polyfills'
|
|
@@ -281,6 +279,8 @@ export default class GoTrueClient {
|
|
|
281
279
|
redirectType
|
|
282
280
|
)
|
|
283
281
|
|
|
282
|
+
await this._saveSession(session)
|
|
283
|
+
|
|
284
284
|
setTimeout(async () => {
|
|
285
285
|
if (redirectType === 'recovery') {
|
|
286
286
|
await this._notifyAllSubscribers('PASSWORD_RECOVERY', session)
|
|
@@ -291,6 +291,7 @@ export default class GoTrueClient {
|
|
|
291
291
|
|
|
292
292
|
return { error: null }
|
|
293
293
|
}
|
|
294
|
+
|
|
294
295
|
// no login attempt via callback url try to recover session from storage
|
|
295
296
|
await this._recoverAndRefresh()
|
|
296
297
|
return { error: null }
|
|
@@ -698,20 +699,18 @@ export default class GoTrueClient {
|
|
|
698
699
|
*/
|
|
699
700
|
async reauthenticate(): Promise<AuthResponse> {
|
|
700
701
|
try {
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
if (!session) throw new AuthSessionMissingError()
|
|
702
|
+
const {
|
|
703
|
+
data: { session },
|
|
704
|
+
error: sessionError,
|
|
705
|
+
} = await this.getSession()
|
|
706
|
+
if (sessionError) throw sessionError
|
|
707
|
+
if (!session) throw new AuthSessionMissingError()
|
|
708
708
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
})
|
|
713
|
-
return { data: { user: null, session: null }, error }
|
|
709
|
+
const { error } = await _request(this.fetch, 'GET', `${this.url}/reauthenticate`, {
|
|
710
|
+
headers: this.headers,
|
|
711
|
+
jwt: session.access_token,
|
|
714
712
|
})
|
|
713
|
+
return { data: { user: null, session: null }, error }
|
|
715
714
|
} catch (error) {
|
|
716
715
|
if (isAuthError(error)) {
|
|
717
716
|
return { data: { user: null, session: null }, error }
|
|
@@ -769,55 +768,7 @@ export default class GoTrueClient {
|
|
|
769
768
|
* Returns the session, refreshing it if necessary.
|
|
770
769
|
* 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.
|
|
771
770
|
*/
|
|
772
|
-
async getSession()
|
|
773
|
-
return this._useSession(async (result) => {
|
|
774
|
-
return result
|
|
775
|
-
})
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
/**
|
|
779
|
-
* Use instead of {@link #getSession} inside the library. It is
|
|
780
|
-
* semantically usually what you want, as getting a session involves some
|
|
781
|
-
* processing afterwards that requires only one client operating on the
|
|
782
|
-
* session at once across multiple tabs or processes.
|
|
783
|
-
*/
|
|
784
|
-
private async _useSession<R>(
|
|
785
|
-
fn: (
|
|
786
|
-
result:
|
|
787
|
-
| {
|
|
788
|
-
data: {
|
|
789
|
-
session: Session
|
|
790
|
-
}
|
|
791
|
-
error: null
|
|
792
|
-
}
|
|
793
|
-
| {
|
|
794
|
-
data: {
|
|
795
|
-
session: null
|
|
796
|
-
}
|
|
797
|
-
error: AuthError
|
|
798
|
-
}
|
|
799
|
-
| {
|
|
800
|
-
data: {
|
|
801
|
-
session: null
|
|
802
|
-
}
|
|
803
|
-
error: null
|
|
804
|
-
}
|
|
805
|
-
) => Promise<R>
|
|
806
|
-
): Promise<R> {
|
|
807
|
-
return await stackGuard('_useSession', async () => {
|
|
808
|
-
// the use of __loadSession here is the only correct use of the function!
|
|
809
|
-
const result = await this.__loadSession()
|
|
810
|
-
|
|
811
|
-
return await fn(result)
|
|
812
|
-
})
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
/**
|
|
816
|
-
* NEVER USE DIRECTLY!
|
|
817
|
-
*
|
|
818
|
-
* Always use {@link #_useSession}.
|
|
819
|
-
*/
|
|
820
|
-
private async __loadSession(): Promise<
|
|
771
|
+
async getSession(): Promise<
|
|
821
772
|
| {
|
|
822
773
|
data: {
|
|
823
774
|
session: Session
|
|
@@ -837,15 +788,11 @@ export default class GoTrueClient {
|
|
|
837
788
|
error: null
|
|
838
789
|
}
|
|
839
790
|
> {
|
|
840
|
-
if (this.logDebugMessages && !isInStackGuard('_useSession')) {
|
|
841
|
-
throw new Error('Please use #_useSession()')
|
|
842
|
-
}
|
|
843
|
-
|
|
844
791
|
// make sure we've read the session from the url if there is one
|
|
845
792
|
// save to just await, as long we make sure _initialize() never throws
|
|
846
793
|
await this.initializePromise
|
|
847
794
|
|
|
848
|
-
this._debug('#
|
|
795
|
+
this._debug('#getSession()', 'begin')
|
|
849
796
|
|
|
850
797
|
try {
|
|
851
798
|
let currentSession: Session | null = null
|
|
@@ -877,7 +824,7 @@ export default class GoTrueClient {
|
|
|
877
824
|
: false
|
|
878
825
|
|
|
879
826
|
this._debug(
|
|
880
|
-
'#
|
|
827
|
+
'#getSession()',
|
|
881
828
|
`session has${hasExpired ? '' : ' not'} expired`,
|
|
882
829
|
'expires_at',
|
|
883
830
|
currentSession.expires_at
|
|
@@ -894,7 +841,7 @@ export default class GoTrueClient {
|
|
|
894
841
|
|
|
895
842
|
return { data: { session }, error: null }
|
|
896
843
|
} finally {
|
|
897
|
-
this._debug('#
|
|
844
|
+
this._debug('#getSession()', 'end')
|
|
898
845
|
}
|
|
899
846
|
}
|
|
900
847
|
|
|
@@ -904,22 +851,20 @@ export default class GoTrueClient {
|
|
|
904
851
|
*/
|
|
905
852
|
async getUser(jwt?: string): Promise<UserResponse> {
|
|
906
853
|
try {
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
throw error
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
// Default to Authorization header if there is no existing session
|
|
915
|
-
jwt = data.session?.access_token ?? undefined
|
|
854
|
+
if (!jwt) {
|
|
855
|
+
const { data, error } = await this.getSession()
|
|
856
|
+
if (error) {
|
|
857
|
+
throw error
|
|
916
858
|
}
|
|
917
859
|
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
860
|
+
// Default to Authorization header if there is no existing session
|
|
861
|
+
jwt = data.session?.access_token ?? undefined
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
return await _request(this.fetch, 'GET', `${this.url}/user`, {
|
|
865
|
+
headers: this.headers,
|
|
866
|
+
jwt: jwt,
|
|
867
|
+
xform: _userResponse,
|
|
923
868
|
})
|
|
924
869
|
} catch (error) {
|
|
925
870
|
if (isAuthError(error)) {
|
|
@@ -940,29 +885,27 @@ export default class GoTrueClient {
|
|
|
940
885
|
} = {}
|
|
941
886
|
): Promise<UserResponse> {
|
|
942
887
|
try {
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
xform: _userResponse,
|
|
958
|
-
})
|
|
959
|
-
if (userError) throw userError
|
|
960
|
-
session.user = data.user as User
|
|
961
|
-
await this._saveSession(session)
|
|
962
|
-
await this._notifyAllSubscribers('USER_UPDATED', session)
|
|
963
|
-
|
|
964
|
-
return { data: { user: session.user }, error: null }
|
|
888
|
+
const { data: sessionData, error: sessionError } = await this.getSession()
|
|
889
|
+
if (sessionError) {
|
|
890
|
+
throw sessionError
|
|
891
|
+
}
|
|
892
|
+
if (!sessionData.session) {
|
|
893
|
+
throw new AuthSessionMissingError()
|
|
894
|
+
}
|
|
895
|
+
const session: Session = sessionData.session
|
|
896
|
+
const { data, error: userError } = await _request(this.fetch, 'PUT', `${this.url}/user`, {
|
|
897
|
+
headers: this.headers,
|
|
898
|
+
redirectTo: options?.emailRedirectTo,
|
|
899
|
+
body: attributes,
|
|
900
|
+
jwt: session.access_token,
|
|
901
|
+
xform: _userResponse,
|
|
965
902
|
})
|
|
903
|
+
if (userError) throw userError
|
|
904
|
+
session.user = data.user as User
|
|
905
|
+
await this._saveSession(session)
|
|
906
|
+
await this._notifyAllSubscribers('USER_UPDATED', session)
|
|
907
|
+
|
|
908
|
+
return { data: { user: session.user }, error: null }
|
|
966
909
|
} catch (error) {
|
|
967
910
|
if (isAuthError(error)) {
|
|
968
911
|
return { data: { user: null }, error }
|
|
@@ -1054,31 +997,29 @@ export default class GoTrueClient {
|
|
|
1054
997
|
*/
|
|
1055
998
|
async refreshSession(currentSession?: { refresh_token: string }): Promise<AuthResponse> {
|
|
1056
999
|
try {
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
throw error
|
|
1062
|
-
}
|
|
1063
|
-
|
|
1064
|
-
currentSession = data.session ?? undefined
|
|
1000
|
+
if (!currentSession) {
|
|
1001
|
+
const { data, error } = await this.getSession()
|
|
1002
|
+
if (error) {
|
|
1003
|
+
throw error
|
|
1065
1004
|
}
|
|
1066
1005
|
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
}
|
|
1006
|
+
currentSession = data.session ?? undefined
|
|
1007
|
+
}
|
|
1070
1008
|
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
}
|
|
1009
|
+
if (!currentSession?.refresh_token) {
|
|
1010
|
+
throw new AuthSessionMissingError()
|
|
1011
|
+
}
|
|
1075
1012
|
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
}
|
|
1013
|
+
const { session, error } = await this._callRefreshToken(currentSession.refresh_token)
|
|
1014
|
+
if (error) {
|
|
1015
|
+
return { data: { user: null, session: null }, error: error }
|
|
1016
|
+
}
|
|
1079
1017
|
|
|
1080
|
-
|
|
1081
|
-
|
|
1018
|
+
if (!session) {
|
|
1019
|
+
return { data: { user: null, session: null }, error: null }
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
return { data: { user: session.user, session }, error: null }
|
|
1082
1023
|
} catch (error) {
|
|
1083
1024
|
if (isAuthError(error)) {
|
|
1084
1025
|
return { data: { user: null, session: null }, error }
|
|
@@ -1201,29 +1142,27 @@ export default class GoTrueClient {
|
|
|
1201
1142
|
* If using others scope, no `SIGNED_OUT` event is fired!
|
|
1202
1143
|
*/
|
|
1203
1144
|
async signOut({ scope }: SignOut = { scope: 'global' }): Promise<{ error: AuthError | null }> {
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
return { error }
|
|
1217
|
-
}
|
|
1145
|
+
const { data, error: sessionError } = await this.getSession()
|
|
1146
|
+
if (sessionError) {
|
|
1147
|
+
return { error: sessionError }
|
|
1148
|
+
}
|
|
1149
|
+
const accessToken = data.session?.access_token
|
|
1150
|
+
if (accessToken) {
|
|
1151
|
+
const { error } = await this.admin.signOut(accessToken, scope)
|
|
1152
|
+
if (error) {
|
|
1153
|
+
// ignore 404s since user might not exist anymore
|
|
1154
|
+
// ignore 401s since an invalid or expired JWT should sign out the current session
|
|
1155
|
+
if (!(isAuthApiError(error) && (error.status === 404 || error.status === 401))) {
|
|
1156
|
+
return { error }
|
|
1218
1157
|
}
|
|
1219
1158
|
}
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
}
|
|
1159
|
+
}
|
|
1160
|
+
if (scope !== 'others') {
|
|
1161
|
+
await this._removeSession()
|
|
1162
|
+
await removeItemAsync(this.storage, `${this.storageKey}-code-verifier`)
|
|
1163
|
+
await this._notifyAllSubscribers('SIGNED_OUT', null)
|
|
1164
|
+
}
|
|
1165
|
+
return { error: null }
|
|
1227
1166
|
}
|
|
1228
1167
|
|
|
1229
1168
|
/**
|
|
@@ -1256,22 +1195,20 @@ export default class GoTrueClient {
|
|
|
1256
1195
|
}
|
|
1257
1196
|
|
|
1258
1197
|
private async _emitInitialSession(id: string): Promise<void> {
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
if (error) throw error
|
|
1198
|
+
try {
|
|
1199
|
+
const {
|
|
1200
|
+
data: { session },
|
|
1201
|
+
error,
|
|
1202
|
+
} = await this.getSession()
|
|
1203
|
+
if (error) throw error
|
|
1266
1204
|
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
})
|
|
1205
|
+
await this.stateChangeEmitters.get(id)?.callback('INITIAL_SESSION', session)
|
|
1206
|
+
this._debug('INITIAL_SESSION', 'callback id', id, 'session', session)
|
|
1207
|
+
} catch (err) {
|
|
1208
|
+
await this.stateChangeEmitters.get(id)?.callback('INITIAL_SESSION', null)
|
|
1209
|
+
this._debug('INITIAL_SESSION', 'callback id', id, 'error', err)
|
|
1210
|
+
console.error(err)
|
|
1211
|
+
}
|
|
1275
1212
|
}
|
|
1276
1213
|
|
|
1277
1214
|
/**
|
|
@@ -1697,30 +1634,28 @@ export default class GoTrueClient {
|
|
|
1697
1634
|
const now = Date.now()
|
|
1698
1635
|
|
|
1699
1636
|
try {
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
} = result
|
|
1704
|
-
|
|
1705
|
-
if (!session || !session.refresh_token || !session.expires_at) {
|
|
1706
|
-
this._debug('#_autoRefreshTokenTick()', 'no session')
|
|
1707
|
-
return
|
|
1708
|
-
}
|
|
1637
|
+
const {
|
|
1638
|
+
data: { session },
|
|
1639
|
+
} = await this.getSession()
|
|
1709
1640
|
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1641
|
+
if (!session || !session.refresh_token || !session.expires_at) {
|
|
1642
|
+
this._debug('#_autoRefreshTokenTick()', 'no session')
|
|
1643
|
+
return
|
|
1644
|
+
}
|
|
1714
1645
|
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1646
|
+
// session will expire in this many ticks (or has already expired if <= 0)
|
|
1647
|
+
const expiresInTicks = Math.floor(
|
|
1648
|
+
(session.expires_at * 1000 - now) / AUTO_REFRESH_TICK_DURATION
|
|
1649
|
+
)
|
|
1719
1650
|
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
}
|
|
1723
|
-
|
|
1651
|
+
this._debug(
|
|
1652
|
+
'#_autoRefreshTokenTick()',
|
|
1653
|
+
`access token expires in ${expiresInTicks} ticks, a tick lasts ${AUTO_REFRESH_TICK_DURATION}ms, refresh threshold is ${AUTO_REFRESH_TICK_THRESHOLD} ticks`
|
|
1654
|
+
)
|
|
1655
|
+
|
|
1656
|
+
if (expiresInTicks <= AUTO_REFRESH_TICK_THRESHOLD) {
|
|
1657
|
+
await this._callRefreshToken(session.refresh_token)
|
|
1658
|
+
}
|
|
1724
1659
|
} catch (e: any) {
|
|
1725
1660
|
console.error('Auto refresh tick failed with error. This is likely a transient error.', e)
|
|
1726
1661
|
}
|
|
@@ -1842,16 +1777,14 @@ export default class GoTrueClient {
|
|
|
1842
1777
|
|
|
1843
1778
|
private async _unenroll(params: MFAUnenrollParams): Promise<AuthMFAUnenrollResponse> {
|
|
1844
1779
|
try {
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
}
|
|
1780
|
+
const { data: sessionData, error: sessionError } = await this.getSession()
|
|
1781
|
+
if (sessionError) {
|
|
1782
|
+
return { data: null, error: sessionError }
|
|
1783
|
+
}
|
|
1850
1784
|
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
})
|
|
1785
|
+
return await _request(this.fetch, 'DELETE', `${this.url}/factors/${params.factorId}`, {
|
|
1786
|
+
headers: this.headers,
|
|
1787
|
+
jwt: sessionData?.session?.access_token,
|
|
1855
1788
|
})
|
|
1856
1789
|
} catch (error) {
|
|
1857
1790
|
if (isAuthError(error)) {
|
|
@@ -1866,32 +1799,30 @@ export default class GoTrueClient {
|
|
|
1866
1799
|
*/
|
|
1867
1800
|
private async _enroll(params: MFAEnrollParams): Promise<AuthMFAEnrollResponse> {
|
|
1868
1801
|
try {
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
}
|
|
1802
|
+
const { data: sessionData, error: sessionError } = await this.getSession()
|
|
1803
|
+
if (sessionError) {
|
|
1804
|
+
return { data: null, error: sessionError }
|
|
1805
|
+
}
|
|
1874
1806
|
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1807
|
+
const { data, error } = await _request(this.fetch, 'POST', `${this.url}/factors`, {
|
|
1808
|
+
body: {
|
|
1809
|
+
friendly_name: params.friendlyName,
|
|
1810
|
+
factor_type: params.factorType,
|
|
1811
|
+
issuer: params.issuer,
|
|
1812
|
+
},
|
|
1813
|
+
headers: this.headers,
|
|
1814
|
+
jwt: sessionData?.session?.access_token,
|
|
1815
|
+
})
|
|
1884
1816
|
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1817
|
+
if (error) {
|
|
1818
|
+
return { data: null, error }
|
|
1819
|
+
}
|
|
1888
1820
|
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1821
|
+
if (data?.totp?.qr_code) {
|
|
1822
|
+
data.totp.qr_code = `data:image/svg+xml;utf-8,${data.totp.qr_code}`
|
|
1823
|
+
}
|
|
1892
1824
|
|
|
1893
|
-
|
|
1894
|
-
})
|
|
1825
|
+
return { data, error: null }
|
|
1895
1826
|
} catch (error) {
|
|
1896
1827
|
if (isAuthError(error)) {
|
|
1897
1828
|
return { data: null, error }
|
|
@@ -1905,34 +1836,32 @@ export default class GoTrueClient {
|
|
|
1905
1836
|
*/
|
|
1906
1837
|
private async _verify(params: MFAVerifyParams): Promise<AuthMFAVerifyResponse> {
|
|
1907
1838
|
try {
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
}
|
|
1839
|
+
const { data: sessionData, error: sessionError } = await this.getSession()
|
|
1840
|
+
if (sessionError) {
|
|
1841
|
+
return { data: null, error: sessionError }
|
|
1842
|
+
}
|
|
1913
1843
|
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
}
|
|
1923
|
-
)
|
|
1924
|
-
if (error) {
|
|
1925
|
-
return { data: null, error }
|
|
1844
|
+
const { data, error } = await _request(
|
|
1845
|
+
this.fetch,
|
|
1846
|
+
'POST',
|
|
1847
|
+
`${this.url}/factors/${params.factorId}/verify`,
|
|
1848
|
+
{
|
|
1849
|
+
body: { code: params.code, challenge_id: params.challengeId },
|
|
1850
|
+
headers: this.headers,
|
|
1851
|
+
jwt: sessionData?.session?.access_token,
|
|
1926
1852
|
}
|
|
1853
|
+
)
|
|
1854
|
+
if (error) {
|
|
1855
|
+
return { data: null, error }
|
|
1856
|
+
}
|
|
1927
1857
|
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
})
|
|
1932
|
-
await this._notifyAllSubscribers('MFA_CHALLENGE_VERIFIED', data)
|
|
1933
|
-
|
|
1934
|
-
return { data, error }
|
|
1858
|
+
await this._saveSession({
|
|
1859
|
+
expires_at: Math.round(Date.now() / 1000) + data.expires_in,
|
|
1860
|
+
...data,
|
|
1935
1861
|
})
|
|
1862
|
+
await this._notifyAllSubscribers('MFA_CHALLENGE_VERIFIED', data)
|
|
1863
|
+
|
|
1864
|
+
return { data, error }
|
|
1936
1865
|
} catch (error) {
|
|
1937
1866
|
if (isAuthError(error)) {
|
|
1938
1867
|
return { data: null, error }
|
|
@@ -1946,22 +1875,20 @@ export default class GoTrueClient {
|
|
|
1946
1875
|
*/
|
|
1947
1876
|
private async _challenge(params: MFAChallengeParams): Promise<AuthMFAChallengeResponse> {
|
|
1948
1877
|
try {
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
}
|
|
1878
|
+
const { data: sessionData, error: sessionError } = await this.getSession()
|
|
1879
|
+
if (sessionError) {
|
|
1880
|
+
return { data: null, error: sessionError }
|
|
1881
|
+
}
|
|
1954
1882
|
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
})
|
|
1883
|
+
return await _request(
|
|
1884
|
+
this.fetch,
|
|
1885
|
+
'POST',
|
|
1886
|
+
`${this.url}/factors/${params.factorId}/challenge`,
|
|
1887
|
+
{
|
|
1888
|
+
headers: this.headers,
|
|
1889
|
+
jwt: sessionData?.session?.access_token,
|
|
1890
|
+
}
|
|
1891
|
+
)
|
|
1965
1892
|
} catch (error) {
|
|
1966
1893
|
if (isAuthError(error)) {
|
|
1967
1894
|
return { data: null, error }
|
|
@@ -2019,41 +1946,39 @@ export default class GoTrueClient {
|
|
|
2019
1946
|
* {@see GoTrueMFAApi#getAuthenticatorAssuranceLevel}
|
|
2020
1947
|
*/
|
|
2021
1948
|
private async _getAuthenticatorAssuranceLevel(): Promise<AuthMFAGetAuthenticatorAssuranceLevelResponse> {
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
error: null,
|
|
2034
|
-
}
|
|
1949
|
+
const {
|
|
1950
|
+
data: { session },
|
|
1951
|
+
error: sessionError,
|
|
1952
|
+
} = await this.getSession()
|
|
1953
|
+
if (sessionError) {
|
|
1954
|
+
return { data: null, error: sessionError }
|
|
1955
|
+
}
|
|
1956
|
+
if (!session) {
|
|
1957
|
+
return {
|
|
1958
|
+
data: { currentLevel: null, nextLevel: null, currentAuthenticationMethods: [] },
|
|
1959
|
+
error: null,
|
|
2035
1960
|
}
|
|
1961
|
+
}
|
|
2036
1962
|
|
|
2037
|
-
|
|
1963
|
+
const payload = this._decodeJWT(session.access_token)
|
|
2038
1964
|
|
|
2039
|
-
|
|
1965
|
+
let currentLevel: AuthenticatorAssuranceLevels | null = null
|
|
2040
1966
|
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
1967
|
+
if (payload.aal) {
|
|
1968
|
+
currentLevel = payload.aal
|
|
1969
|
+
}
|
|
2044
1970
|
|
|
2045
|
-
|
|
1971
|
+
let nextLevel: AuthenticatorAssuranceLevels | null = currentLevel
|
|
2046
1972
|
|
|
2047
|
-
|
|
2048
|
-
|
|
1973
|
+
const verifiedFactors =
|
|
1974
|
+
session.user.factors?.filter((factor: Factor) => factor.status === 'verified') ?? []
|
|
2049
1975
|
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
1976
|
+
if (verifiedFactors.length > 0) {
|
|
1977
|
+
nextLevel = 'aal2'
|
|
1978
|
+
}
|
|
2053
1979
|
|
|
2054
|
-
|
|
1980
|
+
const currentAuthenticationMethods = payload.amr || []
|
|
2055
1981
|
|
|
2056
|
-
|
|
2057
|
-
})
|
|
1982
|
+
return { data: { currentLevel, nextLevel, currentAuthenticationMethods }, error: null }
|
|
2058
1983
|
}
|
|
2059
1984
|
}
|