tinbase 0.16.2 → 0.18.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/auth/handler.d.ts +94 -8
- package/dist/auth/handler.js +399 -35
- package/dist/auth/handler.js.map +1 -1
- package/dist/auth/settings.d.ts +11 -0
- package/dist/auth/settings.js +3 -0
- package/dist/auth/settings.js.map +1 -1
- package/dist/cli.js +18 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.js +7 -2
- package/dist/index.js.map +1 -1
- package/dist/node/load-config.js +3 -0
- package/dist/node/load-config.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/package.json +1 -1
package/dist/auth/handler.d.ts
CHANGED
|
@@ -99,6 +99,7 @@ interface UserRow {
|
|
|
99
99
|
phone: string | null;
|
|
100
100
|
phone_confirmed_at: Date | string | null;
|
|
101
101
|
is_anonymous: boolean | null;
|
|
102
|
+
email_change: string | null;
|
|
102
103
|
}
|
|
103
104
|
/** Routes and services the GoTrue-compatible `/auth/v1/*` endpoints. */
|
|
104
105
|
export declare class AuthHandler {
|
|
@@ -120,18 +121,34 @@ export declare class AuthHandler {
|
|
|
120
121
|
* (GoTrue's `over_request_rate_limit`) when exceeded, else null to proceed.
|
|
121
122
|
*/
|
|
122
123
|
private limit;
|
|
124
|
+
/** GoTrue's 429 for `max_frequency`, with the seconds the caller must wait. */
|
|
125
|
+
private static tooSoon;
|
|
123
126
|
/**
|
|
124
|
-
* Enforce `max_frequency
|
|
125
|
-
*
|
|
127
|
+
* Enforce `max_frequency` the way GoTrue does: against the timestamp that
|
|
128
|
+
* flow last wrote on the user row, not against one budget per address.
|
|
126
129
|
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
130
|
+
* Which column a flow measures itself by is GoTrue's mapping, quirks
|
|
131
|
+
* included - a magic link is measured by `recovery_sent_at`, the same column
|
|
132
|
+
* password recovery uses, because GoTrue mints both from the recovery token.
|
|
133
|
+
* Sharing that budget is therefore correct rather than an oversight; a
|
|
134
|
+
* confirmation, by contrast, has its own. An app that sets `max_frequency`
|
|
135
|
+
* in config.toml gets the pacing Supabase's docs describe, which is the
|
|
136
|
+
* point of spelling it the same way.
|
|
137
|
+
*
|
|
138
|
+
* An address with no account has no row to measure, so those fall back to an
|
|
139
|
+
* in-memory window keyed the same way. GoTrue simply lets them through,
|
|
140
|
+
* which makes a 429 proof that an account exists - `/recover` answers 200
|
|
141
|
+
* for an address it has never seen precisely so the response cannot be used
|
|
142
|
+
* to enumerate accounts, and a frequency check that only ever fires for real
|
|
143
|
+
* users hands that back. The fallback keeps the two indistinguishable.
|
|
133
144
|
*/
|
|
134
145
|
private limitEmailFrequency;
|
|
146
|
+
/**
|
|
147
|
+
* Record that this flow has just mailed the address, so the next request is
|
|
148
|
+
* measured from now. Written only after the mail was accepted - a transport
|
|
149
|
+
* that refused it has not spent the window.
|
|
150
|
+
*/
|
|
151
|
+
private markEmailSent;
|
|
135
152
|
/** Stop background timers (rate-limiter sweep). Called on backend close. */
|
|
136
153
|
stop(): void;
|
|
137
154
|
/** Dispatch one `/auth/v1/*` request. Any thrown error becomes a 500 `unexpected_failure`. */
|
|
@@ -140,6 +157,33 @@ export declare class AuthHandler {
|
|
|
140
157
|
private token;
|
|
141
158
|
private getUser;
|
|
142
159
|
private updateUser;
|
|
160
|
+
/**
|
|
161
|
+
* Begin an email change: park the new address, mint a token for each side,
|
|
162
|
+
* and mail them.
|
|
163
|
+
*
|
|
164
|
+
* The address does not move until the tokens come back. Writing it straight
|
|
165
|
+
* to `auth.users.email` - which is what this did - means a session is all it
|
|
166
|
+
* takes to walk an account to an address of the holder's choosing, with no
|
|
167
|
+
* confirmation from either end and nothing sent to the address losing it.
|
|
168
|
+
*
|
|
169
|
+
* With `secure_email_change_enabled` (the Supabase default) both ends have
|
|
170
|
+
* to click: the new address proves it exists and is reachable, and the
|
|
171
|
+
* current one gets a say in losing the account. The second token is what
|
|
172
|
+
* makes a stolen session insufficient on its own.
|
|
173
|
+
*
|
|
174
|
+
* Returns a Response only when the change could not be started.
|
|
175
|
+
*/
|
|
176
|
+
private startEmailChange;
|
|
177
|
+
/**
|
|
178
|
+
* Park the new address and mint a token per side, without sending anything.
|
|
179
|
+
*
|
|
180
|
+
* Shared with `admin/generate_link`, which needs the same tokens but hands
|
|
181
|
+
* them to the caller. One implementation so the two cannot disagree about
|
|
182
|
+
* how many sides there are or when the previous attempt is invalidated.
|
|
183
|
+
*/
|
|
184
|
+
private mintEmailChangeTokens;
|
|
185
|
+
/** One side of an email change, to whichever address that side belongs to. */
|
|
186
|
+
private mailEmailChange;
|
|
143
187
|
/**
|
|
144
188
|
* POST /auth/v1/logout[?scope=global|local|others]
|
|
145
189
|
*
|
|
@@ -180,6 +224,21 @@ export declare class AuthHandler {
|
|
|
180
224
|
*/
|
|
181
225
|
private issueToken;
|
|
182
226
|
private sendOtp;
|
|
227
|
+
/**
|
|
228
|
+
* POST /auth/v1/resend - send the confirmation for `type` again.
|
|
229
|
+
*
|
|
230
|
+
* This used to be an alias for /magiclink, which is a different email
|
|
231
|
+
* entirely: it mails a login link measured by `recovery_sent_at`, creates an
|
|
232
|
+
* account for an address it has never seen, and pays no attention to `type`.
|
|
233
|
+
* So a resend for an address with no account signed that person up and sent
|
|
234
|
+
* them a way in, and a resend for a signup was paced by the recovery window.
|
|
235
|
+
*
|
|
236
|
+
* GoTrue answers 200 with an empty body both for an address it does not know
|
|
237
|
+
* and for one already confirmed - the two look identical from outside, which
|
|
238
|
+
* is what stops the endpoint from reporting who has an account. No mail goes
|
|
239
|
+
* out in either case.
|
|
240
|
+
*/
|
|
241
|
+
private resend;
|
|
183
242
|
private sendRecovery;
|
|
184
243
|
/** Max wrong guesses for a one-time code before its tokens are invalidated. */
|
|
185
244
|
private static readonly MAX_OTP_ATTEMPTS;
|
|
@@ -194,6 +253,25 @@ export declare class AuthHandler {
|
|
|
194
253
|
* otp+magiclink rows.
|
|
195
254
|
*/
|
|
196
255
|
private static redeemTypes;
|
|
256
|
+
/** What a caller is told when one side of an email change is still outstanding. */
|
|
257
|
+
private static readonly EMAIL_CHANGE_PENDING_MSG;
|
|
258
|
+
/**
|
|
259
|
+
* Redeem one side of an email change.
|
|
260
|
+
*
|
|
261
|
+
* Not routed through {@link redeem}, which exists for the login and recovery
|
|
262
|
+
* tokens and does things that are wrong here: it clears every live token for
|
|
263
|
+
* the address and stamps `last_sign_in_at`, and an email change is not a
|
|
264
|
+
* sign-in. It also cannot express the part that matters - that one click may
|
|
265
|
+
* not be enough.
|
|
266
|
+
*
|
|
267
|
+
* The address moves only once no side is left outstanding. With
|
|
268
|
+
* `secure_email_change_enabled` that means both tokens, in either order;
|
|
269
|
+
* with it off there is only ever the new address's. Deciding it by what
|
|
270
|
+
* remains in the table, rather than by counting clicks, is what makes the
|
|
271
|
+
* order irrelevant and a replay harmless - the row is gone the moment it is
|
|
272
|
+
* redeemed.
|
|
273
|
+
*/
|
|
274
|
+
private verifyEmailChange;
|
|
197
275
|
private verifyToken;
|
|
198
276
|
private verifyLink;
|
|
199
277
|
private admin;
|
|
@@ -212,6 +290,14 @@ export declare class AuthHandler {
|
|
|
212
290
|
* is nothing to un-hash and `verifyOtp({ token_hash })` redeems it directly.
|
|
213
291
|
*/
|
|
214
292
|
private generateLink;
|
|
293
|
+
/**
|
|
294
|
+
* `admin.generateLink({ type: 'email_change_current' | 'email_change_new' })`.
|
|
295
|
+
*
|
|
296
|
+
* Both sides are minted whichever is asked for - they are one change, and
|
|
297
|
+
* minting only the requested half would leave a secure change that can never
|
|
298
|
+
* complete. The caller gets the link for the side it named.
|
|
299
|
+
*/
|
|
300
|
+
private generateEmailChangeLink;
|
|
215
301
|
/**
|
|
216
302
|
* Append a security event to auth.audit_log_entries (GoTrue-compatible
|
|
217
303
|
* payload). Best-effort: a logging failure never breaks the request.
|