@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
package/src/lib/constants.ts
CHANGED
|
@@ -40,4 +40,19 @@ export const API_VERSIONS = {
|
|
|
40
40
|
|
|
41
41
|
export const BASE64URL_REGEX = /^([a-z0-9_-]{4})*($|[a-z0-9_-]{3}$|[a-z0-9_-]{2}$)$/i
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Reserved query parameter appended to `redirectTo` URLs (behind
|
|
45
|
+
* `experimental.appendPkceFlowIdToRedirects`) that correlates a PKCE callback
|
|
46
|
+
* with the code verifier stored when its flow started. It round-trips through
|
|
47
|
+
* the auth server untouched and identifies a verifier slot in storage — the
|
|
48
|
+
* verifier itself never appears in a URL.
|
|
49
|
+
*/
|
|
50
|
+
export const PKCE_FLOW_ID_PARAM = 'sb_flow_id'
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Maximum number of PKCE code verifiers kept in storage at once. Starting a
|
|
54
|
+
* new flow beyond this evicts the oldest pending verifier.
|
|
55
|
+
*/
|
|
56
|
+
export const PKCE_MAX_CONCURRENT_FLOWS = 5
|
|
57
|
+
|
|
43
58
|
export const JWKS_TTL = 10 * 60 * 1000 // 10 minutes
|
package/src/lib/errors.ts
CHANGED
|
@@ -16,7 +16,7 @@ export class AuthError extends Error {
|
|
|
16
16
|
* Error code associated with the error. Most errors coming from
|
|
17
17
|
* HTTP responses will have a code, though some errors that occur
|
|
18
18
|
* before a response is received will not have one present. In that
|
|
19
|
-
* case {@link
|
|
19
|
+
* case {@link AuthError.status} will also be undefined.
|
|
20
20
|
*/
|
|
21
21
|
code: ErrorCode | (string & {}) | undefined
|
|
22
22
|
|
package/src/lib/fetch.ts
CHANGED
|
@@ -81,18 +81,22 @@ export async function handleError(error: unknown) {
|
|
|
81
81
|
throw new AuthRetryableFetchError(_getErrorMessage(error), 0)
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
if (NETWORK_ERROR_CODES.includes(error.status)) {
|
|
85
|
-
// status in 500...599 range - server had an error, request might be retryed.
|
|
86
|
-
throw new AuthRetryableFetchError(_getErrorMessage(error), error.status)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
84
|
let data: any
|
|
90
85
|
try {
|
|
91
86
|
data = await error.json()
|
|
92
87
|
} catch (e) {
|
|
88
|
+
if (NETWORK_ERROR_CODES.includes(error.status)) {
|
|
89
|
+
// statusText can be empty — HTTP/2 has no reason phrase
|
|
90
|
+
throw new AuthRetryableFetchError(error.statusText || `HTTP ${error.status}`, error.status)
|
|
91
|
+
}
|
|
93
92
|
throw new AuthUnknownError(_getErrorMessage(e), e)
|
|
94
93
|
}
|
|
95
94
|
|
|
95
|
+
if (NETWORK_ERROR_CODES.includes(error.status)) {
|
|
96
|
+
// status in 500...599 range - server had an error, request might be retryed.
|
|
97
|
+
throw new AuthRetryableFetchError(_getErrorMessage(data), error.status)
|
|
98
|
+
}
|
|
99
|
+
|
|
96
100
|
let errorCode: string | undefined = undefined
|
|
97
101
|
|
|
98
102
|
const responseAPIVersion = parseResponseAPIVersion(error)
|
|
@@ -224,9 +228,10 @@ async function _handleRequest(
|
|
|
224
228
|
...requestParams,
|
|
225
229
|
})
|
|
226
230
|
} catch (e) {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
//
|
|
231
|
+
// fetch failed (network / CORS / aborted request) — surfaced to the
|
|
232
|
+
// caller as a retryable error below. Deliberately not logged here: an
|
|
233
|
+
// aborted in-flight request (e.g. a superseded page navigation) is a
|
|
234
|
+
// transient condition, and logging the raw error pollutes the console.
|
|
230
235
|
throw new AuthRetryableFetchError(_getErrorMessage(e), 0)
|
|
231
236
|
}
|
|
232
237
|
|
package/src/lib/helpers.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
API_VERSION_HEADER_NAME,
|
|
3
|
+
BASE64URL_REGEX,
|
|
4
|
+
PKCE_FLOW_ID_PARAM,
|
|
5
|
+
PKCE_MAX_CONCURRENT_FLOWS,
|
|
6
|
+
} from './constants'
|
|
2
7
|
import { AuthInvalidJwtError } from './errors'
|
|
3
8
|
import { base64UrlToUint8Array, stringFromBase64URL } from './base64url'
|
|
4
9
|
import { JwtHeader, JwtPayload, SupportedStorage, User } from './types'
|
|
@@ -301,20 +306,207 @@ export async function generatePKCEChallenge(verifier: string) {
|
|
|
301
306
|
return btoa(hashed).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')
|
|
302
307
|
}
|
|
303
308
|
|
|
309
|
+
const PKCE_FLOW_ID_PATTERN = /^[a-zA-Z0-9_-]{8,64}$/
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* Returns the flow id if it is a plausible flow id, `null` otherwise. Flow
|
|
313
|
+
* ids can arrive via URL parameters, so anything outside the expected shape
|
|
314
|
+
* is discarded before it is used to build a storage key.
|
|
315
|
+
*/
|
|
316
|
+
export function validatePKCEFlowId(flowId: unknown): string | null {
|
|
317
|
+
return typeof flowId === 'string' && PKCE_FLOW_ID_PATTERN.test(flowId) ? flowId : null
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export function generatePKCEFlowId(): string {
|
|
321
|
+
if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {
|
|
322
|
+
const bytes = new Uint8Array(16)
|
|
323
|
+
crypto.getRandomValues(bytes)
|
|
324
|
+
return Array.from(bytes, dec2hex).join('')
|
|
325
|
+
}
|
|
326
|
+
let flowId = ''
|
|
327
|
+
for (let i = 0; i < 32; i++) {
|
|
328
|
+
flowId += Math.floor(Math.random() * 16).toString(16)
|
|
329
|
+
}
|
|
330
|
+
return flowId
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Slot keys deliberately end in `-code-verifier`: @supabase/ssr's server
|
|
334
|
+
// cookie adapter only persists writes immediately for keys with that suffix
|
|
335
|
+
// (no auth event fires when a verifier is stored). They also contain no dot,
|
|
336
|
+
// because @supabase/ssr chunks oversized cookies as `<key>.<number>` and a
|
|
337
|
+
// dot-delimited key could be mistaken for a chunk of the fixed
|
|
338
|
+
// `-code-verifier` cookie and clobbered by its chunk management.
|
|
339
|
+
export const pkceVerifierSlotKey = (storageKey: string, flowId: string) =>
|
|
340
|
+
`${storageKey}-flow-${flowId}-code-verifier`
|
|
341
|
+
|
|
342
|
+
const pkceFlowIndexKey = (storageKey: string) => `${storageKey}-flows-code-verifier`
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Storage adapters cannot enumerate keys, so the ids of pending verifier
|
|
346
|
+
* slots are tracked in an index entry, oldest first. Index entries pass
|
|
347
|
+
* through the same validation as URL-provided flow ids: with cookie-based
|
|
348
|
+
* storage the index contents are no more trustworthy than a URL parameter.
|
|
349
|
+
*/
|
|
350
|
+
async function getPKCEFlowIndex(storage: SupportedStorage, storageKey: string): Promise<string[]> {
|
|
351
|
+
const index = await getItemAsync(storage, pkceFlowIndexKey(storageKey))
|
|
352
|
+
return Array.isArray(index)
|
|
353
|
+
? index.filter((id): id is string => validatePKCEFlowId(id) !== null)
|
|
354
|
+
: []
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* The index is read-modify-write without a lock: two concurrent starts (e.g.
|
|
359
|
+
* two tabs) can lose one index update. The losing flow still works — its slot
|
|
360
|
+
* is addressed directly by key — but its entry is missing from the index, so
|
|
361
|
+
* it escapes both ring eviction and removeAllPKCEVerifiers: the orphaned slot
|
|
362
|
+
* persists for the storage medium's lifetime (up to the cookie max age in
|
|
363
|
+
* cookie storage) and repeated races accumulate one orphan each. Accepted
|
|
364
|
+
* trade-off: locking every flow start is far more intrusive than the leak.
|
|
365
|
+
*/
|
|
366
|
+
export async function storePKCEVerifier(
|
|
367
|
+
storage: SupportedStorage,
|
|
368
|
+
storageKey: string,
|
|
369
|
+
flowId: string,
|
|
370
|
+
verifier: string,
|
|
371
|
+
onEvictFlow?: (evictedFlowId: string) => void
|
|
372
|
+
): Promise<void> {
|
|
373
|
+
await setItemAsync(storage, pkceVerifierSlotKey(storageKey, flowId), verifier)
|
|
374
|
+
|
|
375
|
+
const index = (await getPKCEFlowIndex(storage, storageKey)).filter((id) => id !== flowId)
|
|
376
|
+
index.push(flowId)
|
|
377
|
+
while (index.length > PKCE_MAX_CONCURRENT_FLOWS) {
|
|
378
|
+
const evicted = index.shift()!
|
|
379
|
+
await removeItemAsync(storage, pkceVerifierSlotKey(storageKey, evicted))
|
|
380
|
+
onEvictFlow?.(evicted)
|
|
381
|
+
}
|
|
382
|
+
await setItemAsync(storage, pkceFlowIndexKey(storageKey), index)
|
|
383
|
+
|
|
384
|
+
// Deprecation-window dual write: exchanges that cannot identify their flow
|
|
385
|
+
// (older SDK versions, redirects without the flow id parameter) read the
|
|
386
|
+
// fixed key, which mirrors the most recently started flow.
|
|
387
|
+
await setItemAsync(storage, `${storageKey}-code-verifier`, verifier)
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Looks up the verifier for `flowId`. When a flow id is given, only that slot
|
|
392
|
+
* is consulted — deliberately no fallback to the fixed legacy key: submitting
|
|
393
|
+
* another flow's verifier would burn the single-use auth code, and the
|
|
394
|
+
* subsequent cleanup would delete a pending flow's only fallback. The legacy
|
|
395
|
+
* key is read only when no flow id is available at all.
|
|
396
|
+
*/
|
|
397
|
+
export async function retrievePKCEVerifier(
|
|
398
|
+
storage: SupportedStorage,
|
|
399
|
+
storageKey: string,
|
|
400
|
+
flowId: string | null
|
|
401
|
+
): Promise<{ verifier: string | null; flowId: string | null }> {
|
|
402
|
+
if (flowId) {
|
|
403
|
+
const verifier = await getItemAsync(storage, pkceVerifierSlotKey(storageKey, flowId))
|
|
404
|
+
return { verifier: typeof verifier === 'string' ? verifier : null, flowId }
|
|
405
|
+
}
|
|
406
|
+
const verifier = await getItemAsync(storage, `${storageKey}-code-verifier`)
|
|
407
|
+
return { verifier: typeof verifier === 'string' ? verifier : null, flowId: null }
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Removes a single flow's verifier. Never clears other flows' slots: with a
|
|
412
|
+
* `flowId` only that slot is deleted (plus the legacy fixed key when it holds
|
|
413
|
+
* the same verifier); without one, only the legacy fixed key is deleted.
|
|
414
|
+
*/
|
|
415
|
+
export async function removePKCEVerifier(
|
|
416
|
+
storage: SupportedStorage,
|
|
417
|
+
storageKey: string,
|
|
418
|
+
flowId: string | null
|
|
419
|
+
): Promise<void> {
|
|
420
|
+
const legacyKey = `${storageKey}-code-verifier`
|
|
421
|
+
if (!flowId) {
|
|
422
|
+
await removeItemAsync(storage, legacyKey)
|
|
423
|
+
return
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
const slotKey = pkceVerifierSlotKey(storageKey, flowId)
|
|
427
|
+
const slotValue = await getItemAsync(storage, slotKey)
|
|
428
|
+
await removeItemAsync(storage, slotKey)
|
|
429
|
+
|
|
430
|
+
// Skip the index rewrite when the flow was never indexed (e.g. a failed
|
|
431
|
+
// exchange for an absent slot): on cookie storage every write is a full
|
|
432
|
+
// Set-Cookie cycle.
|
|
433
|
+
const index = await getPKCEFlowIndex(storage, storageKey)
|
|
434
|
+
const remaining = index.filter((id) => id !== flowId)
|
|
435
|
+
if (remaining.length !== index.length) {
|
|
436
|
+
if (remaining.length > 0) {
|
|
437
|
+
await setItemAsync(storage, pkceFlowIndexKey(storageKey), remaining)
|
|
438
|
+
} else {
|
|
439
|
+
await removeItemAsync(storage, pkceFlowIndexKey(storageKey))
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (slotValue != null && slotValue === (await getItemAsync(storage, legacyKey))) {
|
|
444
|
+
await removeItemAsync(storage, legacyKey)
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Removes every pending verifier: all slots in the index, the index itself
|
|
450
|
+
* and the fixed legacy key. Used on session teardown (sign-out, invalid
|
|
451
|
+
* session) — matches the pre-slot behavior where tearing down the session
|
|
452
|
+
* deleted the only verifier, and prevents long-lived stale verifier cookies.
|
|
453
|
+
*/
|
|
454
|
+
export async function removeAllPKCEVerifiers(
|
|
455
|
+
storage: SupportedStorage,
|
|
456
|
+
storageKey: string
|
|
457
|
+
): Promise<void> {
|
|
458
|
+
const index = await getPKCEFlowIndex(storage, storageKey)
|
|
459
|
+
for (const flowId of index) {
|
|
460
|
+
await removeItemAsync(storage, pkceVerifierSlotKey(storageKey, flowId))
|
|
461
|
+
}
|
|
462
|
+
await removeItemAsync(storage, pkceFlowIndexKey(storageKey))
|
|
463
|
+
await removeItemAsync(storage, `${storageKey}-code-verifier`)
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Appends the reserved flow id parameter to a `redirectTo` URL, replacing any
|
|
468
|
+
* existing occurrence. String-based (no URL round-trip) so custom schemes
|
|
469
|
+
* (native deep links) and the exact encoding of the app's own parameters
|
|
470
|
+
* survive untouched; an existing fragment stays at the end of the URL.
|
|
471
|
+
*/
|
|
472
|
+
export function appendFlowIdToRedirectTo(redirectTo: string, flowId: string): string {
|
|
473
|
+
const hashIndex = redirectTo.indexOf('#')
|
|
474
|
+
let base = hashIndex === -1 ? redirectTo : redirectTo.slice(0, hashIndex)
|
|
475
|
+
const fragment = hashIndex === -1 ? '' : redirectTo.slice(hashIndex)
|
|
476
|
+
|
|
477
|
+
const queryIndex = base.indexOf('?')
|
|
478
|
+
if (queryIndex !== -1) {
|
|
479
|
+
const path = base.slice(0, queryIndex)
|
|
480
|
+
const remaining = base
|
|
481
|
+
.slice(queryIndex + 1)
|
|
482
|
+
.split('&')
|
|
483
|
+
.filter(
|
|
484
|
+
(pair) =>
|
|
485
|
+
pair !== '' && pair !== PKCE_FLOW_ID_PARAM && !pair.startsWith(`${PKCE_FLOW_ID_PARAM}=`)
|
|
486
|
+
)
|
|
487
|
+
base = remaining.length > 0 ? `${path}?${remaining.join('&')}` : path
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
const separator = base.includes('?') ? '&' : '?'
|
|
491
|
+
return `${base}${separator}${PKCE_FLOW_ID_PARAM}=${encodeURIComponent(flowId)}${fragment}`
|
|
492
|
+
}
|
|
493
|
+
|
|
304
494
|
export async function getCodeChallengeAndMethod(
|
|
305
495
|
storage: SupportedStorage,
|
|
306
496
|
storageKey: string,
|
|
307
|
-
isPasswordRecovery = false
|
|
308
|
-
)
|
|
497
|
+
isPasswordRecovery = false,
|
|
498
|
+
onEvictFlow?: (evictedFlowId: string) => void
|
|
499
|
+
): Promise<[string, string, string]> {
|
|
309
500
|
const codeVerifier = generatePKCEVerifier()
|
|
310
501
|
let storedCodeVerifier = codeVerifier
|
|
311
502
|
if (isPasswordRecovery) {
|
|
312
503
|
storedCodeVerifier += '/recovery'
|
|
313
504
|
}
|
|
314
|
-
|
|
505
|
+
const flowId = generatePKCEFlowId()
|
|
506
|
+
await storePKCEVerifier(storage, storageKey, flowId, storedCodeVerifier, onEvictFlow)
|
|
315
507
|
const codeChallenge = await generatePKCEChallenge(codeVerifier)
|
|
316
508
|
const codeChallengeMethod = codeVerifier === codeChallenge ? 'plain' : 's256'
|
|
317
|
-
return [codeChallenge, codeChallengeMethod]
|
|
509
|
+
return [codeChallenge, codeChallengeMethod, flowId]
|
|
318
510
|
}
|
|
319
511
|
|
|
320
512
|
/** Parses the API version which is 2YYY-MM-DD. */
|
|
@@ -369,7 +561,7 @@ export function getAlgorithm(
|
|
|
369
561
|
}
|
|
370
562
|
}
|
|
371
563
|
|
|
372
|
-
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
|
|
564
|
+
const UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
|
|
373
565
|
|
|
374
566
|
export function validateUUID(str: string) {
|
|
375
567
|
if (!UUID_REGEX.test(str)) {
|
package/src/lib/locks.ts
CHANGED
|
@@ -302,7 +302,7 @@ const PROCESS_LOCKS: { [name: string]: Promise<any> } = {}
|
|
|
302
302
|
* Useful for environments like React Native or other non-browser
|
|
303
303
|
* single-process (i.e. no concept of "tabs") environments.
|
|
304
304
|
*
|
|
305
|
-
* Use {@link
|
|
305
|
+
* Use {@link navigatorLock} in browser environments.
|
|
306
306
|
*
|
|
307
307
|
* @param name Name of the lock to be acquired.
|
|
308
308
|
* @param acquireTimeout If negative, no timeout. If 0 an error is thrown if
|
package/src/lib/types.ts
CHANGED
|
@@ -190,6 +190,30 @@ export type ExperimentalFeatureFlags = {
|
|
|
190
190
|
* disabled throws a descriptive error at call time.
|
|
191
191
|
*/
|
|
192
192
|
passkey?: boolean
|
|
193
|
+
/**
|
|
194
|
+
* Appends a reserved `sb_flow_id` query parameter to `redirectTo` URLs on
|
|
195
|
+
* PKCE flows. The parameter round-trips through the auth server back to
|
|
196
|
+
* your callback URL, where the client uses it to select the code verifier
|
|
197
|
+
* created by that specific flow — so multiple sign-in flows (e.g. two OAuth
|
|
198
|
+
* providers started in different tabs) can be in flight at the same time
|
|
199
|
+
* without overwriting each other.
|
|
200
|
+
*
|
|
201
|
+
* Before enabling, make sure your [redirect URL allow
|
|
202
|
+
* list](https://supabase.com/docs/guides/auth/redirect-urls) tolerates the
|
|
203
|
+
* extra query parameter: allow-list entries are matched against the full
|
|
204
|
+
* URL including the query string, so an exact entry (no wildcard) stops
|
|
205
|
+
* matching once the parameter is appended and the redirect falls back to
|
|
206
|
+
* your Site URL. Redirects to the Site URL's own origin always pass.
|
|
207
|
+
*
|
|
208
|
+
* Defaults to `false`. Without it, concurrent flows still keep separate
|
|
209
|
+
* verifiers in storage, but no flow id travels through the redirect: to
|
|
210
|
+
* match a callback to its verifier you must carry the `flowId` returned by
|
|
211
|
+
* `signInWithOAuth` (or `linkIdentity`) through your own channel and pass
|
|
212
|
+
* it to `exchangeCodeForSession`. Flows that offer no way to obtain the
|
|
213
|
+
* flow id (email OTP, password recovery, sign-up confirmation) can only be
|
|
214
|
+
* correlated via this flag.
|
|
215
|
+
*/
|
|
216
|
+
appendPkceFlowIdToRedirects?: boolean
|
|
193
217
|
}
|
|
194
218
|
|
|
195
219
|
const WeakPasswordReasons = ['length', 'characters', 'pwned'] as const
|
|
@@ -228,7 +252,7 @@ export type RequestResult<T, ErrorType extends Error = AuthError> =
|
|
|
228
252
|
|
|
229
253
|
/**
|
|
230
254
|
* similar to RequestResult except it allows you to destructure the possible shape of the success response
|
|
231
|
-
* {@
|
|
255
|
+
* {@link RequestResult}
|
|
232
256
|
*/
|
|
233
257
|
export type RequestResultSafeDestructure<T> =
|
|
234
258
|
| { data: T; error: null }
|
|
@@ -251,7 +275,7 @@ export type AuthResponsePassword = RequestResultSafeDestructure<{
|
|
|
251
275
|
/**
|
|
252
276
|
* AuthOtpResponse is returned when OTP is used.
|
|
253
277
|
*
|
|
254
|
-
* {@
|
|
278
|
+
* {@link AuthResponse}
|
|
255
279
|
*/
|
|
256
280
|
export type AuthOtpResponse = RequestResultSafeDestructure<{
|
|
257
281
|
user: null
|
|
@@ -275,6 +299,19 @@ export type OAuthResponse =
|
|
|
275
299
|
data: {
|
|
276
300
|
provider: Provider
|
|
277
301
|
url: string
|
|
302
|
+
/**
|
|
303
|
+
* Identifier of the PKCE flow started by this call, usable as the
|
|
304
|
+
* `flowId` option of {@link GoTrueClient#exchangeCodeForSession} to
|
|
305
|
+
* select this flow's code verifier when several flows are in flight.
|
|
306
|
+
* `null` on the implicit flow. The id is a selector for a verifier
|
|
307
|
+
* kept in storage — it is not a secret and never contains the
|
|
308
|
+
* verifier itself.
|
|
309
|
+
*
|
|
310
|
+
* Always set at runtime; optional in the type so existing code that
|
|
311
|
+
* constructs `OAuthResponse` values (e.g. test mocks) keeps
|
|
312
|
+
* compiling.
|
|
313
|
+
*/
|
|
314
|
+
flowId?: string | null
|
|
278
315
|
}
|
|
279
316
|
error: null
|
|
280
317
|
}
|
|
@@ -282,6 +319,7 @@ export type OAuthResponse =
|
|
|
282
319
|
data: {
|
|
283
320
|
provider: Provider
|
|
284
321
|
url: null
|
|
322
|
+
flowId?: string | null
|
|
285
323
|
}
|
|
286
324
|
error: AuthError
|
|
287
325
|
}
|
|
@@ -407,7 +445,7 @@ type FactorVerificationStatus = (typeof FactorVerificationStatuses)[number]
|
|
|
407
445
|
*
|
|
408
446
|
* @see {@link GoTrueMFAApi#enroll}
|
|
409
447
|
* @see {@link GoTrueMFAApi#listFactors}
|
|
410
|
-
* @see {@link
|
|
448
|
+
* @see {@link GoTrueAdminMFAApi#listFactors}
|
|
411
449
|
*/
|
|
412
450
|
export type Factor<
|
|
413
451
|
Type extends FactorType = FactorType,
|
|
@@ -1691,14 +1729,14 @@ export interface GoTrueMFAApi {
|
|
|
1691
1729
|
}
|
|
1692
1730
|
|
|
1693
1731
|
/**
|
|
1694
|
-
* @
|
|
1732
|
+
* @experimental
|
|
1695
1733
|
*/
|
|
1696
1734
|
export type AuthMFAAdminDeleteFactorResponse = RequestResult<{
|
|
1697
1735
|
/** ID of the factor that was successfully deleted. */
|
|
1698
1736
|
id: string
|
|
1699
1737
|
}>
|
|
1700
1738
|
/**
|
|
1701
|
-
* @
|
|
1739
|
+
* @experimental
|
|
1702
1740
|
*/
|
|
1703
1741
|
export type AuthMFAAdminDeleteFactorParams = {
|
|
1704
1742
|
/** ID of the MFA factor to delete. */
|
|
@@ -1709,7 +1747,7 @@ export type AuthMFAAdminDeleteFactorParams = {
|
|
|
1709
1747
|
}
|
|
1710
1748
|
|
|
1711
1749
|
/**
|
|
1712
|
-
* @
|
|
1750
|
+
* @experimental
|
|
1713
1751
|
*/
|
|
1714
1752
|
export type AuthMFAAdminListFactorsResponse = RequestResult<{
|
|
1715
1753
|
/** All factors attached to the user. */
|
|
@@ -1717,7 +1755,7 @@ export type AuthMFAAdminListFactorsResponse = RequestResult<{
|
|
|
1717
1755
|
}>
|
|
1718
1756
|
|
|
1719
1757
|
/**
|
|
1720
|
-
* @
|
|
1758
|
+
* @experimental
|
|
1721
1759
|
*/
|
|
1722
1760
|
export type AuthMFAAdminListFactorsParams = {
|
|
1723
1761
|
/** ID of the user. */
|
|
@@ -1727,7 +1765,7 @@ export type AuthMFAAdminListFactorsParams = {
|
|
|
1727
1765
|
/**
|
|
1728
1766
|
* Contains the full multi-factor authentication administration API.
|
|
1729
1767
|
*
|
|
1730
|
-
* @
|
|
1768
|
+
* @experimental
|
|
1731
1769
|
*/
|
|
1732
1770
|
export interface GoTrueAdminMFAApi {
|
|
1733
1771
|
/**
|
|
@@ -1769,7 +1807,7 @@ export interface GoTrueAdminMFAApi {
|
|
|
1769
1807
|
*
|
|
1770
1808
|
* @see {@link GoTrueMFAApi#unenroll}
|
|
1771
1809
|
*
|
|
1772
|
-
* @
|
|
1810
|
+
* @experimental
|
|
1773
1811
|
*
|
|
1774
1812
|
* @category Auth
|
|
1775
1813
|
* @subcategory Auth Admin
|
|
@@ -2250,6 +2288,14 @@ export type CustomOAuthProvider = {
|
|
|
2250
2288
|
acceptable_client_ids?: string[]
|
|
2251
2289
|
/** OAuth scopes requested during authorization */
|
|
2252
2290
|
scopes?: string[]
|
|
2291
|
+
/**
|
|
2292
|
+
* Allowlist of raw identity provider claim keys to copy verbatim into the
|
|
2293
|
+
* user's `custom_claims` field (within `identity_data` and
|
|
2294
|
+
* `raw_user_meta_data`), e.g. `["groups", "org_id", "mail"]`. This is an
|
|
2295
|
+
* opt-in allowlist that defaults to empty (no claims captured) and operates
|
|
2296
|
+
* independently from `attribute_mapping`.
|
|
2297
|
+
*/
|
|
2298
|
+
custom_claims_allowlist?: string[]
|
|
2253
2299
|
/** Whether PKCE is enabled */
|
|
2254
2300
|
pkce_enabled?: boolean
|
|
2255
2301
|
/** Mapping of provider attributes to Supabase user attributes */
|
|
@@ -2300,6 +2346,14 @@ export type CreateCustomProviderParams = {
|
|
|
2300
2346
|
acceptable_client_ids?: string[]
|
|
2301
2347
|
/** OAuth scopes requested during authorization */
|
|
2302
2348
|
scopes?: string[]
|
|
2349
|
+
/**
|
|
2350
|
+
* Allowlist of raw identity provider claim keys to copy verbatim into the
|
|
2351
|
+
* user's `custom_claims` field (within `identity_data` and
|
|
2352
|
+
* `raw_user_meta_data`), e.g. `["groups", "org_id", "mail"]`. This is an
|
|
2353
|
+
* opt-in allowlist that defaults to empty (no claims captured) and operates
|
|
2354
|
+
* independently from `attribute_mapping`.
|
|
2355
|
+
*/
|
|
2356
|
+
custom_claims_allowlist?: string[]
|
|
2303
2357
|
/** Whether PKCE is enabled */
|
|
2304
2358
|
pkce_enabled?: boolean
|
|
2305
2359
|
/** Mapping of provider attributes to Supabase user attributes */
|
|
@@ -2342,6 +2396,14 @@ export type UpdateCustomProviderParams = {
|
|
|
2342
2396
|
acceptable_client_ids?: string[]
|
|
2343
2397
|
/** OAuth scopes requested during authorization */
|
|
2344
2398
|
scopes?: string[]
|
|
2399
|
+
/**
|
|
2400
|
+
* Allowlist of raw identity provider claim keys to copy verbatim into the
|
|
2401
|
+
* user's `custom_claims` field (within `identity_data` and
|
|
2402
|
+
* `raw_user_meta_data`), e.g. `["groups", "org_id", "mail"]`. This is an
|
|
2403
|
+
* opt-in allowlist that defaults to empty (no claims captured) and operates
|
|
2404
|
+
* independently from `attribute_mapping`.
|
|
2405
|
+
*/
|
|
2406
|
+
custom_claims_allowlist?: string[]
|
|
2345
2407
|
/** Whether PKCE is enabled */
|
|
2346
2408
|
pkce_enabled?: boolean
|
|
2347
2409
|
/** Mapping of provider attributes to Supabase user attributes */
|
package/src/lib/version.ts
CHANGED
|
@@ -4,4 +4,4 @@
|
|
|
4
4
|
// - Debugging and support (identifying which version is running)
|
|
5
5
|
// - Telemetry and logging (version reporting in errors/analytics)
|
|
6
6
|
// - Ensuring build artifacts match the published package version
|
|
7
|
-
export const version = '2.
|
|
7
|
+
export const version = '2.112.3'
|