@depup/supabase__auth-js 2.103.0-depup.0 → 2.110.8-depup.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/AGENTS.md +11 -0
- package/README.md +2 -2
- package/changes.json +1 -1
- package/dist/main/GoTrueAdminApi.d.ts +45 -8
- package/dist/main/GoTrueAdminApi.d.ts.map +1 -1
- package/dist/main/GoTrueAdminApi.js +67 -7
- package/dist/main/GoTrueAdminApi.js.map +1 -1
- package/dist/main/GoTrueClient.d.ts +239 -42
- package/dist/main/GoTrueClient.d.ts.map +1 -1
- package/dist/main/GoTrueClient.js +946 -164
- package/dist/main/GoTrueClient.js.map +1 -1
- package/dist/main/lib/constants.d.ts +8 -0
- package/dist/main/lib/constants.d.ts.map +1 -1
- package/dist/main/lib/constants.js +9 -1
- package/dist/main/lib/constants.js.map +1 -1
- package/dist/main/lib/errors.d.ts +42 -3
- package/dist/main/lib/errors.d.ts.map +1 -1
- package/dist/main/lib/errors.js +44 -13
- package/dist/main/lib/errors.js.map +1 -1
- package/dist/main/lib/fetch.d.ts +28 -8
- package/dist/main/lib/fetch.d.ts.map +1 -1
- package/dist/main/lib/fetch.js +28 -6
- package/dist/main/lib/fetch.js.map +1 -1
- package/dist/main/lib/helpers.d.ts +4 -1
- package/dist/main/lib/helpers.d.ts.map +1 -1
- package/dist/main/lib/helpers.js +15 -4
- package/dist/main/lib/helpers.js.map +1 -1
- package/dist/main/lib/locks.d.ts +29 -35
- package/dist/main/lib/locks.d.ts.map +1 -1
- package/dist/main/lib/locks.js +37 -38
- package/dist/main/lib/locks.js.map +1 -1
- package/dist/main/lib/types.d.ts +305 -64
- 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/main/lib/webauthn.d.ts +8 -0
- package/dist/main/lib/webauthn.d.ts.map +1 -1
- package/dist/main/lib/webauthn.dom.d.ts +3 -3
- package/dist/main/lib/webauthn.dom.d.ts.map +1 -1
- package/dist/main/lib/webauthn.errors.d.ts +5 -0
- package/dist/main/lib/webauthn.errors.d.ts.map +1 -1
- package/dist/main/lib/webauthn.errors.js +7 -0
- package/dist/main/lib/webauthn.errors.js.map +1 -1
- package/dist/main/lib/webauthn.js +1 -0
- package/dist/main/lib/webauthn.js.map +1 -1
- package/dist/module/GoTrueAdminApi.d.ts +45 -8
- package/dist/module/GoTrueAdminApi.d.ts.map +1 -1
- package/dist/module/GoTrueAdminApi.js +68 -8
- package/dist/module/GoTrueAdminApi.js.map +1 -1
- package/dist/module/GoTrueClient.d.ts +239 -42
- package/dist/module/GoTrueClient.d.ts.map +1 -1
- package/dist/module/GoTrueClient.js +951 -169
- package/dist/module/GoTrueClient.js.map +1 -1
- package/dist/module/lib/constants.d.ts +8 -0
- package/dist/module/lib/constants.d.ts.map +1 -1
- package/dist/module/lib/constants.js +8 -0
- package/dist/module/lib/constants.js.map +1 -1
- package/dist/module/lib/errors.d.ts +42 -3
- package/dist/module/lib/errors.d.ts.map +1 -1
- package/dist/module/lib/errors.js +41 -12
- package/dist/module/lib/errors.js.map +1 -1
- package/dist/module/lib/fetch.d.ts +28 -8
- package/dist/module/lib/fetch.d.ts.map +1 -1
- package/dist/module/lib/fetch.js +28 -6
- package/dist/module/lib/fetch.js.map +1 -1
- package/dist/module/lib/helpers.d.ts +4 -1
- package/dist/module/lib/helpers.d.ts.map +1 -1
- package/dist/module/lib/helpers.js +14 -4
- package/dist/module/lib/helpers.js.map +1 -1
- package/dist/module/lib/locks.d.ts +29 -35
- package/dist/module/lib/locks.d.ts.map +1 -1
- package/dist/module/lib/locks.js +37 -38
- package/dist/module/lib/locks.js.map +1 -1
- package/dist/module/lib/types.d.ts +305 -64
- 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/module/lib/webauthn.d.ts +8 -0
- package/dist/module/lib/webauthn.d.ts.map +1 -1
- package/dist/module/lib/webauthn.dom.d.ts +3 -3
- package/dist/module/lib/webauthn.dom.d.ts.map +1 -1
- package/dist/module/lib/webauthn.errors.d.ts +5 -0
- package/dist/module/lib/webauthn.errors.d.ts.map +1 -1
- package/dist/module/lib/webauthn.errors.js +7 -0
- package/dist/module/lib/webauthn.errors.js.map +1 -1
- package/dist/module/lib/webauthn.js +1 -1
- package/dist/module/lib/webauthn.js.map +1 -1
- package/dist/tsconfig.module.tsbuildinfo +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/migrations/README.md +25 -0
- package/migrations/lockless-coordination.md +155 -0
- package/package.json +25 -12
- package/src/GoTrueAdminApi.ts +99 -7
- package/src/GoTrueClient.ts +1117 -181
- package/src/lib/constants.ts +9 -0
- package/src/lib/errors.ts +76 -9
- package/src/lib/fetch.ts +66 -24
- package/src/lib/helpers.ts +19 -6
- package/src/lib/locks.ts +44 -42
- package/src/lib/types.ts +374 -82
- package/src/lib/version.ts +1 -1
- package/src/lib/webauthn.dom.ts +3 -3
- package/src/lib/webauthn.errors.ts +12 -0
- package/src/lib/webauthn.ts +1 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# Lockless auth coordination
|
|
2
|
+
|
|
3
|
+
**Since:** v2.X.Y (update at release time)
|
|
4
|
+
**Action required by:** v3.0.0
|
|
5
|
+
|
|
6
|
+
`@supabase/auth-js` now coordinates session refreshes without a shared mutex by default. The legacy `lock` option is still honored when supplied, but it is deprecated and will be removed in v3.
|
|
7
|
+
|
|
8
|
+
## What changed
|
|
9
|
+
|
|
10
|
+
- **Default coordination is lockless.** A client constructed without a `lock` option no longer acquires `navigator.locks` or any in-process lock. In-tab concurrent refreshes are deduplicated via the pre-existing single-flight (`refreshingDeferred`); cross-tab refresh races are resolved by GoTrue's server-side parent-of-active mechanism on the v1 refresh-token path.
|
|
11
|
+
- **Commit guard inside `_callRefreshToken`.** The client snapshots storage before the rotated-token fetch and re-reads after. If a non-null pre-fetch snapshot was cleared between the two reads (typical case: a concurrent `signOut` ran `_removeSession`), the rotated tokens are discarded instead of being written back over the cleared storage. The discarded result resolves with `{ data: null, error: new AuthRefreshDiscardedError() }`.
|
|
12
|
+
- **New `AuthRefreshDiscardedError`** (with `isAuthRefreshDiscardedError` type guard). Surfaces through `refreshSession()` and `getSession()` results when the commit guard fires. Distinct from `AuthRetryableFetchError` (transient network) and `AuthApiError` (server rejection).
|
|
13
|
+
- **New `client.auth.dispose()`.** Tears down the auto-refresh interval, the `visibilitychange` listener, the `BroadcastChannel`, and registered `onAuthStateChange` subscribers. Idempotent. Designed for React Strict Mode and HMR cleanup hooks. In-flight `fetch` calls are not aborted — they run to completion.
|
|
14
|
+
- **`lock` and `lockAcquireTimeout` options.** Accepted and honored when supplied (legacy opt-in path); both are `@deprecated` and will be removed in v3.
|
|
15
|
+
|
|
16
|
+
## Who is affected
|
|
17
|
+
|
|
18
|
+
**Most callers: nothing to do.** If you do not pass a `lock` option to `createClient` / `GoTrueClient`, you are already on the lockless default path and will get the bug fixes and new APIs without any code change.
|
|
19
|
+
|
|
20
|
+
**Callers passing a custom `lock`** (typically React Native `processLock`, Node multi-process setups with shared AsyncStorage, or a custom lock implementation):
|
|
21
|
+
|
|
22
|
+
- v2.x (this release): your custom `lock` is still invoked exactly as before. The legacy `_acquireLock` machinery is preserved on an opt-in path gated by `settings.lock != null`. No code change required.
|
|
23
|
+
- v3.0.0 (planned): the `lock` and `lockAcquireTimeout` options will be removed entirely. Drop them from your client options before upgrading to v3.
|
|
24
|
+
|
|
25
|
+
## New APIs worth knowing
|
|
26
|
+
|
|
27
|
+
### `client.auth.dispose()`
|
|
28
|
+
|
|
29
|
+
Tears down the client's background work in one call. Safe to call repeatedly.
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
const supabase = createClient(URL, KEY)
|
|
34
|
+
return () => {
|
|
35
|
+
supabase.auth.dispose()
|
|
36
|
+
}
|
|
37
|
+
}, [])
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### `AuthRefreshDiscardedError`
|
|
41
|
+
|
|
42
|
+
Returned from `refreshSession()` / `getSession()` when the commit guard discards a successfully-rotated session.
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { isAuthRefreshDiscardedError } from '@supabase/auth-js'
|
|
46
|
+
|
|
47
|
+
const { data, error } = await supabase.auth.refreshSession()
|
|
48
|
+
if (isAuthRefreshDiscardedError(error)) {
|
|
49
|
+
// A concurrent signOut cleared storage between fetch start and now.
|
|
50
|
+
// The rotated tokens were discarded; the SIGNED_OUT event already fired.
|
|
51
|
+
// Treat as a successful no-op — no need to retry.
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Behavior changes worth flagging
|
|
56
|
+
|
|
57
|
+
- **`_autoRefreshTokenTick` may run concurrently with `signOut` / `setSession` / `getUser`** on the lockless default path. Previously the tick used `_acquireLock(0, ...)` which skipped whenever any auth op held the lock. The lockless equivalent only skips when `refreshingDeferred` is set. The commit guard keeps storage consistent under the new concurrency. The legacy lock opt-in path retains the old skip-on-any-lock behavior.
|
|
58
|
+
- **`onAuthStateChange` async callbacks** that call `getUser`, `setSession`, or read the session from inside the callback are now safe on the default path (previously deadlocked through the lock). One residual hazard remains: calling `refreshSession` (or anything routing through `_callRefreshToken`) from inside a `TOKEN_REFRESHED` handler still deadlocks via `refreshingDeferred`. The `@deprecated` marker on the async overload is kept with its reason updated to point at this specific case.
|
|
59
|
+
- **Subscriber timing on the default path:** subscribers stay awaited; same as before. What changes is that `signOut` no longer waits for an in-flight refresh's HTTP and continuation to finish before its own fetch goes out. Both fetches now run concurrently, and the commit guard keeps storage consistent.
|
|
60
|
+
|
|
61
|
+
## Timing & concurrency notes for downstream consumers
|
|
62
|
+
|
|
63
|
+
Removing the default `_acquireLock(...)` wrapper changes the _microtask shape_ of `getSession`, `getUser`, `refreshSession`, `setSession`, `signOut`, `_initialize`, and `_reauthenticate`. Application behavior is unchanged — these methods still return the same values — but the await chain is shorter.
|
|
64
|
+
|
|
65
|
+
### What changed in the await chain
|
|
66
|
+
|
|
67
|
+
Previously, each of those methods looked like:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
return await this._acquireLock(this.lockAcquireTimeout, async () => {
|
|
71
|
+
return await this._getUser()
|
|
72
|
+
})
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`_acquireLock` awaited `navigator.locks.request` (browser) or the in-process `processLock` (Node). That added a handful of microtasks before the inner operation ran. On the lockless default path, the wrapper is skipped and the inner operation runs directly:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
if (this.lock) {
|
|
79
|
+
return await this._acquireLock(this.lockAcquireTimeout, async () => {
|
|
80
|
+
return await this._getUser()
|
|
81
|
+
})
|
|
82
|
+
}
|
|
83
|
+
return await this._getUser()
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Downstream impact via `fetchWithAuth`
|
|
87
|
+
|
|
88
|
+
`supabase-js` wraps the user's `fetch` via `fetchWithAuth` (in `packages/core/supabase-js/src/SupabaseClient.ts`), which awaits `_getAccessToken()` before every PostgREST, Storage, and Functions request. With the shorter pre-fetch await chain, concurrent client calls — for example `Promise.all([supabase.rpc(...), supabase.rpc(...)])` or `Promise.all(rows.map((r) => supabase.from(...).insert(...)))` — may reach the network layer in a different micro-order than they did on v2.106 and earlier.
|
|
89
|
+
|
|
90
|
+
### What this can surface as
|
|
91
|
+
|
|
92
|
+
Tests that use order-sensitive mocks (nock, MSW, or any interceptor that matches requests in registration order) against parallel client calls may flip. A concrete example from the wild: a downstream worker repo registered two `nock(URL).post('/rest/v1/rpc/queue_job', body => expect(body).toMatchInlineSnapshot(...)).reply(200)` interceptors back-to-back, one expecting database `333`, the other expecting database `222`, and relied on the calls arriving in that order. The application code dispatched both via `Promise.all(replicas.map((r) => supabase.rpc('queue_job', ...)))`. On v2.107 the arrival order flipped, the first interceptor's body matcher ran against the wrong payload, vitest raised `toMatchInlineSnapshot with different snapshots cannot be called at the same location`, and the unmatched interceptor caused a "pending mocks left" failure at teardown.
|
|
93
|
+
|
|
94
|
+
The application behavior was correct in both versions: both RPCs completed, both rows ended up in the queue. Only the _test_ depended on an ordering that was never guaranteed.
|
|
95
|
+
|
|
96
|
+
### Recommended fix pattern
|
|
97
|
+
|
|
98
|
+
Make mocks order-independent. Two common shapes:
|
|
99
|
+
|
|
100
|
+
1. **Branch the body matcher on a discriminator field.** Register one interceptor with `.times(N)`; inside the body matcher, look at a field on the request body (e.g. an `id`) and assert against the expected payload for that id.
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
const expected: Record<number, unknown> = {
|
|
104
|
+
222: {
|
|
105
|
+
/* expected body for replica 222 */
|
|
106
|
+
},
|
|
107
|
+
333: {
|
|
108
|
+
/* expected body for replica 333 */
|
|
109
|
+
},
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
nock(URL)
|
|
113
|
+
.post('/path', (body) => {
|
|
114
|
+
expect(body).toStrictEqual(expected[body.id])
|
|
115
|
+
return true
|
|
116
|
+
})
|
|
117
|
+
.times(2)
|
|
118
|
+
.reply(200)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
2. **Capture and assert as a set.** Push each received body into an array from the matcher, return `true` to accept, then after the parallel block resolves assert the array's _contents_ (e.g. via `expect(received).toEqual(expect.arrayContaining([...]))`) without pinning order.
|
|
122
|
+
|
|
123
|
+
Do not pin behavior to lock-induced delays. They were incidental, not a guarantee — and they may shift again in future patch releases as internal awaits are refactored.
|
|
124
|
+
|
|
125
|
+
The custom-`lock` opt-in path retains the old await shape and is unaffected by this section.
|
|
126
|
+
|
|
127
|
+
## Migration steps
|
|
128
|
+
|
|
129
|
+
### If you do not pass a custom `lock` (most users)
|
|
130
|
+
|
|
131
|
+
No action required for v2. No action required for v3.
|
|
132
|
+
|
|
133
|
+
### If you pass a custom `lock` (e.g., React Native `processLock`)
|
|
134
|
+
|
|
135
|
+
No action required for v2 — your lock continues to work.
|
|
136
|
+
|
|
137
|
+
For v3 readiness:
|
|
138
|
+
|
|
139
|
+
1. Remove `lock` and `lockAcquireTimeout` from your `createClient` / `GoTrueClient` options before upgrading to v3.
|
|
140
|
+
2. If you depended on cross-process serialization (e.g., Node multi-process with shared AsyncStorage), validate that the lockless coordination (in-tab single-flight + server parent-of-active) is sufficient for your runtime. The default is safe for the cases the lock was originally added to handle (cross-tab refresh races), since the server resolves them.
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
// Before (v2.x, still works):
|
|
144
|
+
const supabase = createClient(URL, KEY, {
|
|
145
|
+
auth: { lock: processLock, lockAcquireTimeout: 5000 },
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
// After (v3-ready):
|
|
149
|
+
const supabase = createClient(URL, KEY)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Reference
|
|
153
|
+
|
|
154
|
+
- Server-side parent-of-active mechanism: `internal/tokens/service.go:376-385` in the [supabase/auth](https://github.com/supabase/auth) repo (v1 branch, the `*models.RefreshToken` type assertion). When a request arrives with a revoked refresh token whose child is the currently-active token, the server returns the active token instead of rejecting — both tabs receive the same rotated token under DB row locking.
|
|
155
|
+
- `lib/locks.ts` exports (`navigatorLock`, `processLock`, `LockAcquireTimeoutError`, `NavigatorLockAcquireTimeoutError`, `ProcessLockAcquireTimeoutError`, `internals`) remain available for direct imports, marked `@deprecated`. Direct callers who use these exports outside the `GoTrueClient` constructor option are unaffected.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@depup/supabase__auth-js",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.110.8-depup.0",
|
|
4
4
|
"description": "Official SDK for Supabase Auth (with updated dependencies)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"@supabase/auth-js",
|
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
"files": [
|
|
21
21
|
"dist",
|
|
22
22
|
"src",
|
|
23
|
+
"migrations",
|
|
24
|
+
"AGENTS.md",
|
|
23
25
|
"changes.json",
|
|
24
26
|
"README.md"
|
|
25
27
|
],
|
|
@@ -31,28 +33,39 @@
|
|
|
31
33
|
"url": "https://github.com/supabase/supabase-js.git",
|
|
32
34
|
"directory": "packages/core/auth-js"
|
|
33
35
|
},
|
|
34
|
-
"scripts": {
|
|
35
|
-
"build": "npm run build:main && npm run build:module",
|
|
36
|
-
"build:main": "tsc -p tsconfig.json",
|
|
37
|
-
"build:module": "tsc -p tsconfig.module.json",
|
|
38
|
-
"docs": "typedoc src/index.ts --out docs/v2 --excludePrivate --excludeProtected",
|
|
39
|
-
"docs:json": "typedoc --json docs/v2/spec.json --excludeExternals --excludePrivate --excludeProtected src/index.ts"
|
|
40
|
-
},
|
|
41
36
|
"dependencies": {
|
|
42
37
|
"tslib": "2.8.1"
|
|
43
38
|
},
|
|
44
39
|
"devDependencies": {
|
|
45
|
-
"
|
|
40
|
+
"@faker-js/faker": "^9.9.0",
|
|
41
|
+
"@types/jest": "30.0.0",
|
|
42
|
+
"@types/jsonwebtoken": "^8.5.8",
|
|
43
|
+
"@types/node": "20.19.9",
|
|
44
|
+
"jest": "30.4.2",
|
|
45
|
+
"jest-environment-jsdom": "30.4.1",
|
|
46
|
+
"jest-mock-server": "^0.1.0",
|
|
47
|
+
"jsonwebtoken": "^9.0.0",
|
|
48
|
+
"prettier": "^3.6.2",
|
|
49
|
+
"ts-jest": "^29.4.9",
|
|
50
|
+
"typedoc": "^0.27.9",
|
|
51
|
+
"typescript": "~5.8.3"
|
|
46
52
|
},
|
|
47
53
|
"engines": {
|
|
48
|
-
"node": ">=
|
|
54
|
+
"node": ">=22.0.0"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "npm run build:main && npm run build:module",
|
|
58
|
+
"build:main": "tsc -p tsconfig.json",
|
|
59
|
+
"build:module": "tsc -p tsconfig.module.json",
|
|
60
|
+
"docs": "typedoc --options ../../../typedoc.base.mjs src/index.ts --out docs/v2 --excludePrivate --excludeProtected",
|
|
61
|
+
"docs:json": "typedoc --options ../../../typedoc.base.mjs --json docs/v2/spec.json --excludeExternals --excludePrivate --excludeProtected src/index.ts"
|
|
49
62
|
},
|
|
50
63
|
"depup": {
|
|
51
64
|
"changes": {},
|
|
52
65
|
"depsUpdated": 0,
|
|
53
66
|
"originalPackage": "@supabase/auth-js",
|
|
54
|
-
"originalVersion": "2.
|
|
55
|
-
"processedAt": "2026-
|
|
67
|
+
"originalVersion": "2.110.8",
|
|
68
|
+
"processedAt": "2026-07-21T16:08:53.860Z",
|
|
56
69
|
"smokeTest": "passed"
|
|
57
70
|
}
|
|
58
71
|
}
|
package/src/GoTrueAdminApi.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
_request,
|
|
6
6
|
_userResponse,
|
|
7
7
|
} from './lib/fetch'
|
|
8
|
-
import { resolveFetch, validateUUID } from './lib/helpers'
|
|
8
|
+
import { assertPasskeyExperimentalEnabled, resolveFetch, validateUUID } from './lib/helpers'
|
|
9
9
|
import {
|
|
10
10
|
AdminUserAttributes,
|
|
11
11
|
GenerateLinkParams,
|
|
@@ -32,6 +32,12 @@ import {
|
|
|
32
32
|
ListCustomProvidersParams,
|
|
33
33
|
CustomProviderResponse,
|
|
34
34
|
CustomProviderListResponse,
|
|
35
|
+
GoTrueAdminPasskeyApi,
|
|
36
|
+
AuthPasskeyAdminListParams,
|
|
37
|
+
AuthPasskeyAdminDeleteParams,
|
|
38
|
+
AuthPasskeyListResponse,
|
|
39
|
+
AuthPasskeyDeleteResponse,
|
|
40
|
+
ExperimentalFeatureFlags,
|
|
35
41
|
} from './lib/types'
|
|
36
42
|
import { AuthError, isAuthError } from './lib/errors'
|
|
37
43
|
|
|
@@ -48,22 +54,38 @@ export default class GoTrueAdminApi {
|
|
|
48
54
|
/** Contains all custom OIDC/OAuth provider administration methods. */
|
|
49
55
|
customProviders: GoTrueAdminCustomProvidersApi
|
|
50
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Contains all passkey administration methods.
|
|
59
|
+
*
|
|
60
|
+
* Requires `auth.experimental.passkey: true`; otherwise all methods throw.
|
|
61
|
+
*/
|
|
62
|
+
passkey: GoTrueAdminPasskeyApi
|
|
63
|
+
|
|
51
64
|
protected url: string
|
|
52
65
|
protected headers: {
|
|
53
66
|
[key: string]: string
|
|
54
67
|
}
|
|
55
68
|
protected fetch: Fetch
|
|
69
|
+
protected experimental: ExperimentalFeatureFlags
|
|
56
70
|
|
|
57
71
|
/**
|
|
58
72
|
* Creates an admin API client that can be used to manage users and OAuth clients.
|
|
59
73
|
*
|
|
60
|
-
* @example
|
|
74
|
+
* @example Using supabase-js (recommended)
|
|
75
|
+
* ```ts
|
|
76
|
+
* import { createClient } from '@supabase/supabase-js'
|
|
77
|
+
*
|
|
78
|
+
* const supabase = createClient('https://xyzcompany.supabase.co', 'your-secret-key')
|
|
79
|
+
* const { data, error } = await supabase.auth.admin.listUsers()
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* @example Standalone import for bundle-sensitive environments
|
|
61
83
|
* ```ts
|
|
62
84
|
* import { GoTrueAdminApi } from '@supabase/auth-js'
|
|
63
85
|
*
|
|
64
86
|
* const admin = new GoTrueAdminApi({
|
|
65
87
|
* url: 'https://xyzcompany.supabase.co/auth/v1',
|
|
66
|
-
* headers: { Authorization: `Bearer ${process.env.
|
|
88
|
+
* headers: { Authorization: `Bearer ${process.env.SUPABASE_SECRET_KEY}` },
|
|
67
89
|
* })
|
|
68
90
|
* ```
|
|
69
91
|
*/
|
|
@@ -71,16 +93,19 @@ export default class GoTrueAdminApi {
|
|
|
71
93
|
url = '',
|
|
72
94
|
headers = {},
|
|
73
95
|
fetch,
|
|
96
|
+
experimental,
|
|
74
97
|
}: {
|
|
75
98
|
url: string
|
|
76
99
|
headers?: {
|
|
77
100
|
[key: string]: string
|
|
78
101
|
}
|
|
79
102
|
fetch?: Fetch
|
|
103
|
+
experimental?: ExperimentalFeatureFlags
|
|
80
104
|
}) {
|
|
81
105
|
this.url = url
|
|
82
106
|
this.headers = headers
|
|
83
107
|
this.fetch = resolveFetch(fetch)
|
|
108
|
+
this.experimental = experimental ?? {}
|
|
84
109
|
this.mfa = {
|
|
85
110
|
listFactors: this._listFactors.bind(this),
|
|
86
111
|
deleteFactor: this._deleteFactor.bind(this),
|
|
@@ -100,6 +125,10 @@ export default class GoTrueAdminApi {
|
|
|
100
125
|
updateProvider: this._updateCustomProvider.bind(this),
|
|
101
126
|
deleteProvider: this._deleteCustomProvider.bind(this),
|
|
102
127
|
}
|
|
128
|
+
this.passkey = {
|
|
129
|
+
listPasskeys: this._adminListPasskeys.bind(this),
|
|
130
|
+
deletePasskey: this._adminDeletePasskey.bind(this),
|
|
131
|
+
}
|
|
103
132
|
}
|
|
104
133
|
|
|
105
134
|
/**
|
|
@@ -108,6 +137,7 @@ export default class GoTrueAdminApi {
|
|
|
108
137
|
* @param scope The logout sope.
|
|
109
138
|
*
|
|
110
139
|
* @category Auth
|
|
140
|
+
* @subcategory Auth Admin
|
|
111
141
|
*/
|
|
112
142
|
async signOut(
|
|
113
143
|
jwt: string,
|
|
@@ -141,6 +171,7 @@ export default class GoTrueAdminApi {
|
|
|
141
171
|
* @param options Additional options to be included when inviting.
|
|
142
172
|
*
|
|
143
173
|
* @category Auth
|
|
174
|
+
* @subcategory Auth Admin
|
|
144
175
|
*
|
|
145
176
|
* @remarks
|
|
146
177
|
* - Sends an invite link to the user's email address.
|
|
@@ -226,12 +257,10 @@ export default class GoTrueAdminApi {
|
|
|
226
257
|
|
|
227
258
|
/**
|
|
228
259
|
* Generates email links and OTPs to be sent via a custom email provider.
|
|
229
|
-
* @param
|
|
230
|
-
* @param options.password User password. For signup only.
|
|
231
|
-
* @param options.data Optional user metadata. For signup only.
|
|
232
|
-
* @param options.redirectTo The redirect url which should be appended to the generated link
|
|
260
|
+
* @param params The parameters for generating the link, including the link `type`, the user's `email`, and type-specific options such as `password`, `data`, and `redirectTo`.
|
|
233
261
|
*
|
|
234
262
|
* @category Auth
|
|
263
|
+
* @subcategory Auth Admin
|
|
235
264
|
*
|
|
236
265
|
* @remarks
|
|
237
266
|
* - The following types can be passed into `generateLink()`: `signup`, `magiclink`, `invite`, `recovery`, `email_change_current`, `email_change_new`, `phone_change`.
|
|
@@ -375,6 +404,7 @@ export default class GoTrueAdminApi {
|
|
|
375
404
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
376
405
|
*
|
|
377
406
|
* @category Auth
|
|
407
|
+
* @subcategory Auth Admin
|
|
378
408
|
*
|
|
379
409
|
* @remarks
|
|
380
410
|
* - To confirm the user's email address or phone number, set `email_confirm` or `phone_confirm` to true. Both arguments default to false.
|
|
@@ -472,6 +502,7 @@ export default class GoTrueAdminApi {
|
|
|
472
502
|
* @param params An object which supports `page` and `perPage` as numbers, to alter the paginated results.
|
|
473
503
|
*
|
|
474
504
|
* @category Auth
|
|
505
|
+
* @subcategory Auth Admin
|
|
475
506
|
*
|
|
476
507
|
* @remarks
|
|
477
508
|
* - Defaults to return 50 users per page.
|
|
@@ -537,6 +568,7 @@ export default class GoTrueAdminApi {
|
|
|
537
568
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
538
569
|
*
|
|
539
570
|
* @category Auth
|
|
571
|
+
* @subcategory Auth Admin
|
|
540
572
|
*
|
|
541
573
|
* @remarks
|
|
542
574
|
* - Fetches the user object from the database based on the user's id.
|
|
@@ -640,6 +672,7 @@ export default class GoTrueAdminApi {
|
|
|
640
672
|
* @see {@link GoTrueClient.updateUser} for client-side user updates (triggers listeners automatically)
|
|
641
673
|
*
|
|
642
674
|
* @category Auth
|
|
675
|
+
* @subcategory Auth Admin
|
|
643
676
|
*
|
|
644
677
|
* @example Updates a user's email
|
|
645
678
|
* ```js
|
|
@@ -778,6 +811,7 @@ export default class GoTrueAdminApi {
|
|
|
778
811
|
* This function should only be called on a server. Never expose your `service_role` key in the browser.
|
|
779
812
|
*
|
|
780
813
|
* @category Auth
|
|
814
|
+
* @subcategory Auth Admin
|
|
781
815
|
*
|
|
782
816
|
* @remarks
|
|
783
817
|
* - The `deleteUser()` method requires the user's ID, which maps to the `auth.users.id` column.
|
|
@@ -1169,4 +1203,62 @@ export default class GoTrueAdminApi {
|
|
|
1169
1203
|
throw error
|
|
1170
1204
|
}
|
|
1171
1205
|
}
|
|
1206
|
+
|
|
1207
|
+
/**
|
|
1208
|
+
* Lists all passkeys for a user.
|
|
1209
|
+
*
|
|
1210
|
+
* This function should only be called on a server. Never expose your secret key in the browser.
|
|
1211
|
+
*
|
|
1212
|
+
* Requires `auth.experimental.passkey: true`.
|
|
1213
|
+
*/
|
|
1214
|
+
private async _adminListPasskeys(
|
|
1215
|
+
params: AuthPasskeyAdminListParams
|
|
1216
|
+
): Promise<AuthPasskeyListResponse> {
|
|
1217
|
+
assertPasskeyExperimentalEnabled(this.experimental)
|
|
1218
|
+
validateUUID(params.userId)
|
|
1219
|
+
|
|
1220
|
+
try {
|
|
1221
|
+
return await _request(
|
|
1222
|
+
this.fetch,
|
|
1223
|
+
'GET',
|
|
1224
|
+
`${this.url}/admin/users/${params.userId}/passkeys`,
|
|
1225
|
+
{ headers: this.headers, xform: (data: any) => ({ data, error: null }) }
|
|
1226
|
+
)
|
|
1227
|
+
} catch (error) {
|
|
1228
|
+
if (isAuthError(error)) {
|
|
1229
|
+
return { data: null, error }
|
|
1230
|
+
}
|
|
1231
|
+
throw error
|
|
1232
|
+
}
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
/**
|
|
1236
|
+
* Deletes a user's passkey.
|
|
1237
|
+
*
|
|
1238
|
+
* This function should only be called on a server. Never expose your secret key in the browser.
|
|
1239
|
+
*
|
|
1240
|
+
* Requires `auth.experimental.passkey: true`.
|
|
1241
|
+
*/
|
|
1242
|
+
private async _adminDeletePasskey(
|
|
1243
|
+
params: AuthPasskeyAdminDeleteParams
|
|
1244
|
+
): Promise<AuthPasskeyDeleteResponse> {
|
|
1245
|
+
assertPasskeyExperimentalEnabled(this.experimental)
|
|
1246
|
+
validateUUID(params.userId)
|
|
1247
|
+
validateUUID(params.passkeyId)
|
|
1248
|
+
|
|
1249
|
+
try {
|
|
1250
|
+
await _request(
|
|
1251
|
+
this.fetch,
|
|
1252
|
+
'DELETE',
|
|
1253
|
+
`${this.url}/admin/users/${params.userId}/passkeys/${params.passkeyId}`,
|
|
1254
|
+
{ headers: this.headers, noResolveJson: true }
|
|
1255
|
+
)
|
|
1256
|
+
return { data: null, error: null }
|
|
1257
|
+
} catch (error) {
|
|
1258
|
+
if (isAuthError(error)) {
|
|
1259
|
+
return { data: null, error }
|
|
1260
|
+
}
|
|
1261
|
+
throw error
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1172
1264
|
}
|