@netlify/identity 0.1.1-alpha.2 → 0.1.1-alpha.20
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 +363 -7
- package/dist/index.cjs +362 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +24 -7
- package/dist/index.d.ts +24 -7
- package/dist/index.js +368 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -43,6 +43,7 @@ __export(index_exports, {
|
|
|
43
43
|
logout: () => logout,
|
|
44
44
|
oauthLogin: () => oauthLogin,
|
|
45
45
|
onAuthChange: () => onAuthChange,
|
|
46
|
+
recoverPassword: () => recoverPassword,
|
|
46
47
|
requestPasswordRecovery: () => requestPasswordRecovery,
|
|
47
48
|
signup: () => signup,
|
|
48
49
|
updateUser: () => updateUser,
|
|
@@ -75,6 +76,7 @@ var MissingIdentityError = class extends Error {
|
|
|
75
76
|
};
|
|
76
77
|
|
|
77
78
|
// src/environment.ts
|
|
79
|
+
var IDENTITY_PATH = "/.netlify/identity";
|
|
78
80
|
var goTrueClient = null;
|
|
79
81
|
var cachedApiUrl;
|
|
80
82
|
var warnedMissingUrl = false;
|
|
@@ -82,13 +84,15 @@ var isBrowser = () => typeof window !== "undefined" && typeof window.location !=
|
|
|
82
84
|
var discoverApiUrl = () => {
|
|
83
85
|
if (cachedApiUrl !== void 0) return cachedApiUrl;
|
|
84
86
|
if (isBrowser()) {
|
|
85
|
-
cachedApiUrl = `${window.location.origin}
|
|
87
|
+
cachedApiUrl = `${window.location.origin}${IDENTITY_PATH}`;
|
|
86
88
|
} else {
|
|
87
89
|
const identityContext = getIdentityContext();
|
|
88
90
|
if (identityContext?.url) {
|
|
89
91
|
cachedApiUrl = identityContext.url;
|
|
90
92
|
} else if (globalThis.Netlify?.context?.url) {
|
|
91
|
-
cachedApiUrl = new URL(
|
|
93
|
+
cachedApiUrl = new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href;
|
|
94
|
+
} else if (process.env.URL) {
|
|
95
|
+
cachedApiUrl = new URL(IDENTITY_PATH, process.env.URL).href;
|
|
92
96
|
}
|
|
93
97
|
}
|
|
94
98
|
return cachedApiUrl ?? null;
|
|
@@ -105,7 +109,7 @@ var getGoTrueClient = () => {
|
|
|
105
109
|
}
|
|
106
110
|
return null;
|
|
107
111
|
}
|
|
108
|
-
goTrueClient = new import_gotrue_js.default({ APIUrl: apiUrl, setCookie:
|
|
112
|
+
goTrueClient = new import_gotrue_js.default({ APIUrl: apiUrl, setCookie: false });
|
|
109
113
|
return goTrueClient;
|
|
110
114
|
};
|
|
111
115
|
var getClient = () => {
|
|
@@ -115,18 +119,97 @@ var getClient = () => {
|
|
|
115
119
|
};
|
|
116
120
|
var getIdentityContext = () => {
|
|
117
121
|
const identityContext = globalThis.netlifyIdentityContext;
|
|
118
|
-
if (identityContext?.url
|
|
122
|
+
if (identityContext?.url) {
|
|
119
123
|
return {
|
|
120
124
|
url: identityContext.url,
|
|
121
|
-
token:
|
|
125
|
+
token: identityContext.token
|
|
122
126
|
};
|
|
123
127
|
}
|
|
124
128
|
if (globalThis.Netlify?.context?.url) {
|
|
125
|
-
return { url: new URL(
|
|
129
|
+
return { url: new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href };
|
|
130
|
+
}
|
|
131
|
+
const siteUrl = process.env.URL;
|
|
132
|
+
if (siteUrl) {
|
|
133
|
+
return { url: new URL(IDENTITY_PATH, siteUrl).href };
|
|
126
134
|
}
|
|
127
135
|
return null;
|
|
128
136
|
};
|
|
129
137
|
|
|
138
|
+
// src/cookies.ts
|
|
139
|
+
var NF_JWT_COOKIE = "nf_jwt";
|
|
140
|
+
var NF_REFRESH_COOKIE = "nf_refresh";
|
|
141
|
+
var getCookie = (name) => {
|
|
142
|
+
const match = document.cookie.match(new RegExp(`(?:^|; )${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}=([^;]*)`));
|
|
143
|
+
return match ? decodeURIComponent(match[1]) : null;
|
|
144
|
+
};
|
|
145
|
+
var setAuthCookies = (cookies, accessToken, refreshToken) => {
|
|
146
|
+
cookies.set({
|
|
147
|
+
name: NF_JWT_COOKIE,
|
|
148
|
+
value: accessToken,
|
|
149
|
+
httpOnly: false,
|
|
150
|
+
secure: true,
|
|
151
|
+
path: "/",
|
|
152
|
+
sameSite: "Lax"
|
|
153
|
+
});
|
|
154
|
+
if (refreshToken) {
|
|
155
|
+
cookies.set({
|
|
156
|
+
name: NF_REFRESH_COOKIE,
|
|
157
|
+
value: refreshToken,
|
|
158
|
+
httpOnly: false,
|
|
159
|
+
secure: true,
|
|
160
|
+
path: "/",
|
|
161
|
+
sameSite: "Lax"
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
var deleteAuthCookies = (cookies) => {
|
|
166
|
+
cookies.delete(NF_JWT_COOKIE);
|
|
167
|
+
cookies.delete(NF_REFRESH_COOKIE);
|
|
168
|
+
};
|
|
169
|
+
var setBrowserAuthCookies = (accessToken, refreshToken) => {
|
|
170
|
+
document.cookie = `${NF_JWT_COOKIE}=${encodeURIComponent(accessToken)}; path=/; secure; samesite=lax`;
|
|
171
|
+
if (refreshToken) {
|
|
172
|
+
document.cookie = `${NF_REFRESH_COOKIE}=${encodeURIComponent(refreshToken)}; path=/; secure; samesite=lax`;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
var deleteBrowserAuthCookies = () => {
|
|
176
|
+
document.cookie = `${NF_JWT_COOKIE}=; path=/; secure; samesite=lax; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
|
177
|
+
document.cookie = `${NF_REFRESH_COOKIE}=; path=/; secure; samesite=lax; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
|
178
|
+
};
|
|
179
|
+
var getServerCookie = (name) => {
|
|
180
|
+
const cookies = globalThis.Netlify?.context?.cookies;
|
|
181
|
+
if (!cookies || typeof cookies.get !== "function") return null;
|
|
182
|
+
return cookies.get(name) ?? null;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// src/nextjs.ts
|
|
186
|
+
var nextHeadersFn;
|
|
187
|
+
var triggerNextjsDynamic = () => {
|
|
188
|
+
if (nextHeadersFn === null) return;
|
|
189
|
+
if (nextHeadersFn === void 0) {
|
|
190
|
+
try {
|
|
191
|
+
if (typeof require === "undefined") {
|
|
192
|
+
nextHeadersFn = null;
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const mod = require("next/headers");
|
|
196
|
+
nextHeadersFn = mod.headers;
|
|
197
|
+
} catch {
|
|
198
|
+
nextHeadersFn = null;
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const fn = nextHeadersFn;
|
|
203
|
+
if (!fn) return;
|
|
204
|
+
try {
|
|
205
|
+
fn();
|
|
206
|
+
} catch (e) {
|
|
207
|
+
if (e instanceof Error && ("digest" in e || /bail\s*out.*prerende/i.test(e.message))) {
|
|
208
|
+
throw e;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
130
213
|
// src/user.ts
|
|
131
214
|
var toAuthProvider = (value) => typeof value === "string" && AUTH_PROVIDERS.includes(value) ? value : void 0;
|
|
132
215
|
var toUser = (userData) => {
|
|
@@ -152,32 +235,89 @@ var claimsToUser = (claims) => {
|
|
|
152
235
|
const userMeta = claims.user_metadata ?? {};
|
|
153
236
|
const name = userMeta.full_name || userMeta.name;
|
|
154
237
|
return {
|
|
155
|
-
id:
|
|
156
|
-
email:
|
|
238
|
+
id: claims.sub ?? "",
|
|
239
|
+
email: claims.email,
|
|
157
240
|
provider: toAuthProvider(appMeta.provider),
|
|
158
241
|
name: typeof name === "string" ? name : void 0,
|
|
159
242
|
metadata: userMeta
|
|
160
243
|
};
|
|
161
244
|
};
|
|
245
|
+
var hydrating = false;
|
|
246
|
+
var backgroundHydrate = (accessToken) => {
|
|
247
|
+
if (hydrating) return;
|
|
248
|
+
hydrating = true;
|
|
249
|
+
const refreshToken = getCookie(NF_REFRESH_COOKIE) ?? "";
|
|
250
|
+
setTimeout(() => {
|
|
251
|
+
try {
|
|
252
|
+
const client = getClient();
|
|
253
|
+
client.createUser(
|
|
254
|
+
{
|
|
255
|
+
access_token: accessToken,
|
|
256
|
+
token_type: "bearer",
|
|
257
|
+
expires_in: 3600,
|
|
258
|
+
expires_at: Math.floor(Date.now() / 1e3) + 3600,
|
|
259
|
+
refresh_token: refreshToken
|
|
260
|
+
},
|
|
261
|
+
true
|
|
262
|
+
).catch(() => {
|
|
263
|
+
}).finally(() => {
|
|
264
|
+
hydrating = false;
|
|
265
|
+
});
|
|
266
|
+
} catch {
|
|
267
|
+
hydrating = false;
|
|
268
|
+
}
|
|
269
|
+
}, 0);
|
|
270
|
+
};
|
|
271
|
+
var decodeJwtPayload = (token) => {
|
|
272
|
+
try {
|
|
273
|
+
const parts = token.split(".");
|
|
274
|
+
if (parts.length !== 3) return null;
|
|
275
|
+
const payload = atob(parts[1].replace(/-/g, "+").replace(/_/g, "/"));
|
|
276
|
+
return JSON.parse(payload);
|
|
277
|
+
} catch {
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
};
|
|
162
281
|
var getUser = () => {
|
|
163
282
|
if (isBrowser()) {
|
|
164
283
|
const client = getGoTrueClient();
|
|
165
284
|
const currentUser = client?.currentUser() ?? null;
|
|
166
|
-
if (
|
|
167
|
-
|
|
285
|
+
if (currentUser) {
|
|
286
|
+
const jwt2 = getCookie(NF_JWT_COOKIE);
|
|
287
|
+
if (!jwt2) {
|
|
288
|
+
try {
|
|
289
|
+
currentUser.clearSession();
|
|
290
|
+
} catch {
|
|
291
|
+
}
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
return toUser(currentUser);
|
|
295
|
+
}
|
|
296
|
+
const jwt = getCookie(NF_JWT_COOKIE);
|
|
297
|
+
if (!jwt) return null;
|
|
298
|
+
const claims = decodeJwtPayload(jwt);
|
|
299
|
+
if (!claims) return null;
|
|
300
|
+
backgroundHydrate(jwt);
|
|
301
|
+
return claimsToUser(claims);
|
|
168
302
|
}
|
|
303
|
+
triggerNextjsDynamic();
|
|
169
304
|
const identityContext = globalThis.netlifyIdentityContext;
|
|
170
|
-
if (
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
305
|
+
if (identityContext?.user) {
|
|
306
|
+
return claimsToUser(identityContext.user);
|
|
307
|
+
}
|
|
308
|
+
const serverJwt = getServerCookie(NF_JWT_COOKIE);
|
|
309
|
+
if (serverJwt) {
|
|
310
|
+
const claims = decodeJwtPayload(serverJwt);
|
|
311
|
+
if (claims) return claimsToUser(claims);
|
|
312
|
+
}
|
|
313
|
+
return null;
|
|
174
314
|
};
|
|
175
315
|
var isAuthenticated = () => getUser() !== null;
|
|
176
316
|
|
|
177
317
|
// src/config.ts
|
|
178
318
|
var getIdentityConfig = () => {
|
|
179
319
|
if (isBrowser()) {
|
|
180
|
-
return { url: `${window.location.origin}
|
|
320
|
+
return { url: `${window.location.origin}${IDENTITY_PATH}` };
|
|
181
321
|
}
|
|
182
322
|
return getIdentityContext();
|
|
183
323
|
};
|
|
@@ -205,6 +345,20 @@ var getSettings = async () => {
|
|
|
205
345
|
};
|
|
206
346
|
|
|
207
347
|
// src/auth.ts
|
|
348
|
+
var getCookies = () => {
|
|
349
|
+
const cookies = globalThis.Netlify?.context?.cookies;
|
|
350
|
+
if (!cookies) {
|
|
351
|
+
throw new AuthError("Server-side auth requires Netlify Functions runtime");
|
|
352
|
+
}
|
|
353
|
+
return cookies;
|
|
354
|
+
};
|
|
355
|
+
var getServerIdentityUrl = () => {
|
|
356
|
+
const ctx = getIdentityContext();
|
|
357
|
+
if (!ctx?.url) {
|
|
358
|
+
throw new AuthError("Could not determine the Identity endpoint URL on the server");
|
|
359
|
+
}
|
|
360
|
+
return ctx.url;
|
|
361
|
+
};
|
|
208
362
|
var persistSession = true;
|
|
209
363
|
var listeners = /* @__PURE__ */ new Set();
|
|
210
364
|
var emitAuthEvent = (event, user) => {
|
|
@@ -239,9 +393,58 @@ var onAuthChange = (callback) => {
|
|
|
239
393
|
};
|
|
240
394
|
};
|
|
241
395
|
var login = async (email, password) => {
|
|
396
|
+
if (!isBrowser()) {
|
|
397
|
+
const identityUrl = getServerIdentityUrl();
|
|
398
|
+
const cookies = getCookies();
|
|
399
|
+
const body = new URLSearchParams({
|
|
400
|
+
grant_type: "password",
|
|
401
|
+
username: email,
|
|
402
|
+
password
|
|
403
|
+
});
|
|
404
|
+
let res;
|
|
405
|
+
try {
|
|
406
|
+
res = await fetch(`${identityUrl}/token`, {
|
|
407
|
+
method: "POST",
|
|
408
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
409
|
+
body: body.toString()
|
|
410
|
+
});
|
|
411
|
+
} catch (error) {
|
|
412
|
+
throw new AuthError(error.message, void 0, { cause: error });
|
|
413
|
+
}
|
|
414
|
+
if (!res.ok) {
|
|
415
|
+
const errorBody = await res.json().catch(() => ({}));
|
|
416
|
+
throw new AuthError(
|
|
417
|
+
errorBody.msg || errorBody.error_description || `Login failed (${res.status})`,
|
|
418
|
+
res.status
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
const data = await res.json();
|
|
422
|
+
const accessToken = data.access_token;
|
|
423
|
+
let userRes;
|
|
424
|
+
try {
|
|
425
|
+
userRes = await fetch(`${identityUrl}/user`, {
|
|
426
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
427
|
+
});
|
|
428
|
+
} catch (error) {
|
|
429
|
+
throw new AuthError(error.message, void 0, { cause: error });
|
|
430
|
+
}
|
|
431
|
+
if (!userRes.ok) {
|
|
432
|
+
const errorBody = await userRes.json().catch(() => ({}));
|
|
433
|
+
throw new AuthError(
|
|
434
|
+
errorBody.msg || `Failed to fetch user data (${userRes.status})`,
|
|
435
|
+
userRes.status
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
const userData = await userRes.json();
|
|
439
|
+
const user = toUser(userData);
|
|
440
|
+
setAuthCookies(cookies, accessToken, data.refresh_token);
|
|
441
|
+
return user;
|
|
442
|
+
}
|
|
242
443
|
const client = getClient();
|
|
243
444
|
try {
|
|
244
445
|
const gotrueUser = await client.login(email, password, persistSession);
|
|
446
|
+
const jwt = await gotrueUser.jwt();
|
|
447
|
+
setBrowserAuthCookies(jwt);
|
|
245
448
|
const user = toUser(gotrueUser);
|
|
246
449
|
emitAuthEvent("login", user);
|
|
247
450
|
return user;
|
|
@@ -250,6 +453,34 @@ var login = async (email, password) => {
|
|
|
250
453
|
}
|
|
251
454
|
};
|
|
252
455
|
var signup = async (email, password, data) => {
|
|
456
|
+
if (!isBrowser()) {
|
|
457
|
+
const identityUrl = getServerIdentityUrl();
|
|
458
|
+
const cookies = getCookies();
|
|
459
|
+
let res;
|
|
460
|
+
try {
|
|
461
|
+
res = await fetch(`${identityUrl}/signup`, {
|
|
462
|
+
method: "POST",
|
|
463
|
+
headers: { "Content-Type": "application/json" },
|
|
464
|
+
body: JSON.stringify({ email, password, data })
|
|
465
|
+
});
|
|
466
|
+
} catch (error) {
|
|
467
|
+
throw new AuthError(error.message, void 0, { cause: error });
|
|
468
|
+
}
|
|
469
|
+
if (!res.ok) {
|
|
470
|
+
const errorBody = await res.json().catch(() => ({}));
|
|
471
|
+
throw new AuthError(errorBody.msg || `Signup failed (${res.status})`, res.status);
|
|
472
|
+
}
|
|
473
|
+
const responseData = await res.json();
|
|
474
|
+
const user = toUser(responseData);
|
|
475
|
+
if (responseData.confirmed_at) {
|
|
476
|
+
const responseRecord = responseData;
|
|
477
|
+
const accessToken = responseRecord.access_token;
|
|
478
|
+
if (accessToken) {
|
|
479
|
+
setAuthCookies(cookies, accessToken, responseRecord.refresh_token);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return user;
|
|
483
|
+
}
|
|
253
484
|
const client = getClient();
|
|
254
485
|
try {
|
|
255
486
|
const response = await client.signup(email, password, data);
|
|
@@ -263,12 +494,30 @@ var signup = async (email, password, data) => {
|
|
|
263
494
|
}
|
|
264
495
|
};
|
|
265
496
|
var logout = async () => {
|
|
497
|
+
if (!isBrowser()) {
|
|
498
|
+
const identityUrl = getServerIdentityUrl();
|
|
499
|
+
const cookies = getCookies();
|
|
500
|
+
const jwt = cookies.get(NF_JWT_COOKIE);
|
|
501
|
+
if (jwt) {
|
|
502
|
+
try {
|
|
503
|
+
await fetch(`${identityUrl}/logout`, {
|
|
504
|
+
method: "POST",
|
|
505
|
+
headers: { Authorization: `Bearer ${jwt}` }
|
|
506
|
+
});
|
|
507
|
+
} catch (error) {
|
|
508
|
+
throw new AuthError(error.message, void 0, { cause: error });
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
deleteAuthCookies(cookies);
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
266
514
|
const client = getClient();
|
|
267
515
|
try {
|
|
268
516
|
const currentUser = client.currentUser();
|
|
269
517
|
if (currentUser) {
|
|
270
518
|
await currentUser.logout();
|
|
271
519
|
}
|
|
520
|
+
deleteBrowserAuthCookies();
|
|
272
521
|
emitAuthEvent("logout", null);
|
|
273
522
|
} catch (error) {
|
|
274
523
|
throw new AuthError(error.message, void 0, { cause: error });
|
|
@@ -291,16 +540,18 @@ var handleAuthCallback = async () => {
|
|
|
291
540
|
const params = new URLSearchParams(hash);
|
|
292
541
|
const accessToken = params.get("access_token");
|
|
293
542
|
if (accessToken) {
|
|
543
|
+
const refreshToken = params.get("refresh_token") ?? "";
|
|
294
544
|
const gotrueUser = await client.createUser(
|
|
295
545
|
{
|
|
296
546
|
access_token: accessToken,
|
|
297
547
|
token_type: params.get("token_type") ?? "bearer",
|
|
298
548
|
expires_in: Number(params.get("expires_in")),
|
|
299
549
|
expires_at: Number(params.get("expires_at")),
|
|
300
|
-
refresh_token:
|
|
550
|
+
refresh_token: refreshToken
|
|
301
551
|
},
|
|
302
552
|
persistSession
|
|
303
553
|
);
|
|
554
|
+
setBrowserAuthCookies(accessToken, refreshToken || void 0);
|
|
304
555
|
const user = toUser(gotrueUser);
|
|
305
556
|
clearHash();
|
|
306
557
|
emitAuthEvent("login", user);
|
|
@@ -309,6 +560,8 @@ var handleAuthCallback = async () => {
|
|
|
309
560
|
const confirmationToken = params.get("confirmation_token");
|
|
310
561
|
if (confirmationToken) {
|
|
311
562
|
const gotrueUser = await client.confirm(confirmationToken, persistSession);
|
|
563
|
+
const jwt = await gotrueUser.jwt();
|
|
564
|
+
setBrowserAuthCookies(jwt);
|
|
312
565
|
const user = toUser(gotrueUser);
|
|
313
566
|
clearHash();
|
|
314
567
|
emitAuthEvent("login", user);
|
|
@@ -317,6 +570,8 @@ var handleAuthCallback = async () => {
|
|
|
317
570
|
const recoveryToken = params.get("recovery_token");
|
|
318
571
|
if (recoveryToken) {
|
|
319
572
|
const gotrueUser = await client.recover(recoveryToken, persistSession);
|
|
573
|
+
const jwt = await gotrueUser.jwt();
|
|
574
|
+
setBrowserAuthCookies(jwt);
|
|
320
575
|
const user = toUser(gotrueUser);
|
|
321
576
|
clearHash();
|
|
322
577
|
emitAuthEvent("login", user);
|
|
@@ -331,11 +586,27 @@ var handleAuthCallback = async () => {
|
|
|
331
586
|
if (emailChangeToken) {
|
|
332
587
|
const currentUser = client.currentUser();
|
|
333
588
|
if (!currentUser) {
|
|
334
|
-
|
|
335
|
-
return { type: "email_change", user: null, token: emailChangeToken };
|
|
589
|
+
throw new AuthError("Email change verification requires an active browser session");
|
|
336
590
|
}
|
|
337
|
-
const
|
|
338
|
-
const
|
|
591
|
+
const jwt = await currentUser.jwt();
|
|
592
|
+
const identityUrl = `${window.location.origin}${IDENTITY_PATH}`;
|
|
593
|
+
const emailChangeRes = await fetch(`${identityUrl}/user`, {
|
|
594
|
+
method: "PUT",
|
|
595
|
+
headers: {
|
|
596
|
+
"Content-Type": "application/json",
|
|
597
|
+
Authorization: `Bearer ${jwt}`
|
|
598
|
+
},
|
|
599
|
+
body: JSON.stringify({ email_change_token: emailChangeToken })
|
|
600
|
+
});
|
|
601
|
+
if (!emailChangeRes.ok) {
|
|
602
|
+
const errorBody = await emailChangeRes.json().catch(() => ({}));
|
|
603
|
+
throw new AuthError(
|
|
604
|
+
errorBody.msg || `Email change verification failed (${emailChangeRes.status})`,
|
|
605
|
+
emailChangeRes.status
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
const emailChangeData = await emailChangeRes.json();
|
|
609
|
+
const user = toUser(emailChangeData);
|
|
339
610
|
clearHash();
|
|
340
611
|
emitAuthEvent("user_updated", user);
|
|
341
612
|
return { type: "email_change", user };
|
|
@@ -348,8 +619,43 @@ var handleAuthCallback = async () => {
|
|
|
348
619
|
var clearHash = () => {
|
|
349
620
|
history.replaceState(null, "", window.location.pathname + window.location.search);
|
|
350
621
|
};
|
|
622
|
+
var hydrateSession = async () => {
|
|
623
|
+
if (!isBrowser()) return null;
|
|
624
|
+
const client = getClient();
|
|
625
|
+
const currentUser = client.currentUser();
|
|
626
|
+
if (currentUser) return toUser(currentUser);
|
|
627
|
+
const accessToken = getCookie(NF_JWT_COOKIE);
|
|
628
|
+
if (!accessToken) return null;
|
|
629
|
+
const refreshToken = getCookie(NF_REFRESH_COOKIE) ?? "";
|
|
630
|
+
const gotrueUser = await client.createUser(
|
|
631
|
+
{
|
|
632
|
+
access_token: accessToken,
|
|
633
|
+
token_type: "bearer",
|
|
634
|
+
expires_in: 3600,
|
|
635
|
+
expires_at: Math.floor(Date.now() / 1e3) + 3600,
|
|
636
|
+
refresh_token: refreshToken
|
|
637
|
+
},
|
|
638
|
+
persistSession
|
|
639
|
+
);
|
|
640
|
+
const user = toUser(gotrueUser);
|
|
641
|
+
emitAuthEvent("login", user);
|
|
642
|
+
return user;
|
|
643
|
+
};
|
|
351
644
|
|
|
352
645
|
// src/account.ts
|
|
646
|
+
var ensureCurrentUser = async () => {
|
|
647
|
+
const client = getClient();
|
|
648
|
+
let currentUser = client.currentUser();
|
|
649
|
+
if (!currentUser && isBrowser()) {
|
|
650
|
+
try {
|
|
651
|
+
await hydrateSession();
|
|
652
|
+
} catch {
|
|
653
|
+
}
|
|
654
|
+
currentUser = client.currentUser();
|
|
655
|
+
}
|
|
656
|
+
if (!currentUser) throw new AuthError("No user is currently logged in");
|
|
657
|
+
return currentUser;
|
|
658
|
+
};
|
|
353
659
|
var requestPasswordRecovery = async (email) => {
|
|
354
660
|
const client = getClient();
|
|
355
661
|
try {
|
|
@@ -358,6 +664,18 @@ var requestPasswordRecovery = async (email) => {
|
|
|
358
664
|
throw new AuthError(error.message, void 0, { cause: error });
|
|
359
665
|
}
|
|
360
666
|
};
|
|
667
|
+
var recoverPassword = async (token, newPassword) => {
|
|
668
|
+
const client = getClient();
|
|
669
|
+
try {
|
|
670
|
+
const gotrueUser = await client.recover(token, persistSession);
|
|
671
|
+
const updatedUser = await gotrueUser.update({ password: newPassword });
|
|
672
|
+
const user = toUser(updatedUser);
|
|
673
|
+
emitAuthEvent("login", user);
|
|
674
|
+
return user;
|
|
675
|
+
} catch (error) {
|
|
676
|
+
throw new AuthError(error.message, void 0, { cause: error });
|
|
677
|
+
}
|
|
678
|
+
};
|
|
361
679
|
var confirmEmail = async (token) => {
|
|
362
680
|
const client = getClient();
|
|
363
681
|
try {
|
|
@@ -381,22 +699,37 @@ var acceptInvite = async (token, password) => {
|
|
|
381
699
|
}
|
|
382
700
|
};
|
|
383
701
|
var verifyEmailChange = async (token) => {
|
|
384
|
-
|
|
385
|
-
const currentUser =
|
|
386
|
-
|
|
702
|
+
if (!isBrowser()) throw new AuthError("verifyEmailChange() is only available in the browser");
|
|
703
|
+
const currentUser = await ensureCurrentUser();
|
|
704
|
+
const jwt = await currentUser.jwt();
|
|
705
|
+
const identityUrl = `${window.location.origin}${IDENTITY_PATH}`;
|
|
387
706
|
try {
|
|
388
|
-
const
|
|
389
|
-
|
|
707
|
+
const res = await fetch(`${identityUrl}/user`, {
|
|
708
|
+
method: "PUT",
|
|
709
|
+
headers: {
|
|
710
|
+
"Content-Type": "application/json",
|
|
711
|
+
Authorization: `Bearer ${jwt}`
|
|
712
|
+
},
|
|
713
|
+
body: JSON.stringify({ email_change_token: token })
|
|
714
|
+
});
|
|
715
|
+
if (!res.ok) {
|
|
716
|
+
const errorBody = await res.json().catch(() => ({}));
|
|
717
|
+
throw new AuthError(
|
|
718
|
+
errorBody.msg || `Email change verification failed (${res.status})`,
|
|
719
|
+
res.status
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
const userData = await res.json();
|
|
723
|
+
const user = toUser(userData);
|
|
390
724
|
emitAuthEvent("user_updated", user);
|
|
391
725
|
return user;
|
|
392
726
|
} catch (error) {
|
|
727
|
+
if (error instanceof AuthError) throw error;
|
|
393
728
|
throw new AuthError(error.message, void 0, { cause: error });
|
|
394
729
|
}
|
|
395
730
|
};
|
|
396
731
|
var updateUser = async (updates) => {
|
|
397
|
-
const
|
|
398
|
-
const currentUser = client.currentUser();
|
|
399
|
-
if (!currentUser) throw new AuthError("No user is currently logged in");
|
|
732
|
+
const currentUser = await ensureCurrentUser();
|
|
400
733
|
try {
|
|
401
734
|
const updatedUser = await currentUser.update(updates);
|
|
402
735
|
const user = toUser(updatedUser);
|
|
@@ -421,6 +754,7 @@ var updateUser = async (updates) => {
|
|
|
421
754
|
logout,
|
|
422
755
|
oauthLogin,
|
|
423
756
|
onAuthChange,
|
|
757
|
+
recoverPassword,
|
|
424
758
|
requestPasswordRecovery,
|
|
425
759
|
signup,
|
|
426
760
|
updateUser,
|