@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.js
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
1
8
|
// src/types.ts
|
|
2
9
|
var AUTH_PROVIDERS = ["google", "github", "gitlab", "bitbucket", "facebook", "saml", "email"];
|
|
3
10
|
|
|
@@ -23,6 +30,7 @@ var MissingIdentityError = class extends Error {
|
|
|
23
30
|
};
|
|
24
31
|
|
|
25
32
|
// src/environment.ts
|
|
33
|
+
var IDENTITY_PATH = "/.netlify/identity";
|
|
26
34
|
var goTrueClient = null;
|
|
27
35
|
var cachedApiUrl;
|
|
28
36
|
var warnedMissingUrl = false;
|
|
@@ -30,13 +38,15 @@ var isBrowser = () => typeof window !== "undefined" && typeof window.location !=
|
|
|
30
38
|
var discoverApiUrl = () => {
|
|
31
39
|
if (cachedApiUrl !== void 0) return cachedApiUrl;
|
|
32
40
|
if (isBrowser()) {
|
|
33
|
-
cachedApiUrl = `${window.location.origin}
|
|
41
|
+
cachedApiUrl = `${window.location.origin}${IDENTITY_PATH}`;
|
|
34
42
|
} else {
|
|
35
43
|
const identityContext = getIdentityContext();
|
|
36
44
|
if (identityContext?.url) {
|
|
37
45
|
cachedApiUrl = identityContext.url;
|
|
38
46
|
} else if (globalThis.Netlify?.context?.url) {
|
|
39
|
-
cachedApiUrl = new URL(
|
|
47
|
+
cachedApiUrl = new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href;
|
|
48
|
+
} else if (process.env.URL) {
|
|
49
|
+
cachedApiUrl = new URL(IDENTITY_PATH, process.env.URL).href;
|
|
40
50
|
}
|
|
41
51
|
}
|
|
42
52
|
return cachedApiUrl ?? null;
|
|
@@ -53,7 +63,7 @@ var getGoTrueClient = () => {
|
|
|
53
63
|
}
|
|
54
64
|
return null;
|
|
55
65
|
}
|
|
56
|
-
goTrueClient = new GoTrue({ APIUrl: apiUrl, setCookie:
|
|
66
|
+
goTrueClient = new GoTrue({ APIUrl: apiUrl, setCookie: false });
|
|
57
67
|
return goTrueClient;
|
|
58
68
|
};
|
|
59
69
|
var getClient = () => {
|
|
@@ -63,18 +73,97 @@ var getClient = () => {
|
|
|
63
73
|
};
|
|
64
74
|
var getIdentityContext = () => {
|
|
65
75
|
const identityContext = globalThis.netlifyIdentityContext;
|
|
66
|
-
if (identityContext?.url
|
|
76
|
+
if (identityContext?.url) {
|
|
67
77
|
return {
|
|
68
78
|
url: identityContext.url,
|
|
69
|
-
token:
|
|
79
|
+
token: identityContext.token
|
|
70
80
|
};
|
|
71
81
|
}
|
|
72
82
|
if (globalThis.Netlify?.context?.url) {
|
|
73
|
-
return { url: new URL(
|
|
83
|
+
return { url: new URL(IDENTITY_PATH, globalThis.Netlify.context.url).href };
|
|
84
|
+
}
|
|
85
|
+
const siteUrl = process.env.URL;
|
|
86
|
+
if (siteUrl) {
|
|
87
|
+
return { url: new URL(IDENTITY_PATH, siteUrl).href };
|
|
74
88
|
}
|
|
75
89
|
return null;
|
|
76
90
|
};
|
|
77
91
|
|
|
92
|
+
// src/cookies.ts
|
|
93
|
+
var NF_JWT_COOKIE = "nf_jwt";
|
|
94
|
+
var NF_REFRESH_COOKIE = "nf_refresh";
|
|
95
|
+
var getCookie = (name) => {
|
|
96
|
+
const match = document.cookie.match(new RegExp(`(?:^|; )${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}=([^;]*)`));
|
|
97
|
+
return match ? decodeURIComponent(match[1]) : null;
|
|
98
|
+
};
|
|
99
|
+
var setAuthCookies = (cookies, accessToken, refreshToken) => {
|
|
100
|
+
cookies.set({
|
|
101
|
+
name: NF_JWT_COOKIE,
|
|
102
|
+
value: accessToken,
|
|
103
|
+
httpOnly: false,
|
|
104
|
+
secure: true,
|
|
105
|
+
path: "/",
|
|
106
|
+
sameSite: "Lax"
|
|
107
|
+
});
|
|
108
|
+
if (refreshToken) {
|
|
109
|
+
cookies.set({
|
|
110
|
+
name: NF_REFRESH_COOKIE,
|
|
111
|
+
value: refreshToken,
|
|
112
|
+
httpOnly: false,
|
|
113
|
+
secure: true,
|
|
114
|
+
path: "/",
|
|
115
|
+
sameSite: "Lax"
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
var deleteAuthCookies = (cookies) => {
|
|
120
|
+
cookies.delete(NF_JWT_COOKIE);
|
|
121
|
+
cookies.delete(NF_REFRESH_COOKIE);
|
|
122
|
+
};
|
|
123
|
+
var setBrowserAuthCookies = (accessToken, refreshToken) => {
|
|
124
|
+
document.cookie = `${NF_JWT_COOKIE}=${encodeURIComponent(accessToken)}; path=/; secure; samesite=lax`;
|
|
125
|
+
if (refreshToken) {
|
|
126
|
+
document.cookie = `${NF_REFRESH_COOKIE}=${encodeURIComponent(refreshToken)}; path=/; secure; samesite=lax`;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
var deleteBrowserAuthCookies = () => {
|
|
130
|
+
document.cookie = `${NF_JWT_COOKIE}=; path=/; secure; samesite=lax; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
|
131
|
+
document.cookie = `${NF_REFRESH_COOKIE}=; path=/; secure; samesite=lax; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
|
|
132
|
+
};
|
|
133
|
+
var getServerCookie = (name) => {
|
|
134
|
+
const cookies = globalThis.Netlify?.context?.cookies;
|
|
135
|
+
if (!cookies || typeof cookies.get !== "function") return null;
|
|
136
|
+
return cookies.get(name) ?? null;
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// src/nextjs.ts
|
|
140
|
+
var nextHeadersFn;
|
|
141
|
+
var triggerNextjsDynamic = () => {
|
|
142
|
+
if (nextHeadersFn === null) return;
|
|
143
|
+
if (nextHeadersFn === void 0) {
|
|
144
|
+
try {
|
|
145
|
+
if (typeof __require === "undefined") {
|
|
146
|
+
nextHeadersFn = null;
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const mod = __require("next/headers");
|
|
150
|
+
nextHeadersFn = mod.headers;
|
|
151
|
+
} catch {
|
|
152
|
+
nextHeadersFn = null;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
const fn = nextHeadersFn;
|
|
157
|
+
if (!fn) return;
|
|
158
|
+
try {
|
|
159
|
+
fn();
|
|
160
|
+
} catch (e) {
|
|
161
|
+
if (e instanceof Error && ("digest" in e || /bail\s*out.*prerende/i.test(e.message))) {
|
|
162
|
+
throw e;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
78
167
|
// src/user.ts
|
|
79
168
|
var toAuthProvider = (value) => typeof value === "string" && AUTH_PROVIDERS.includes(value) ? value : void 0;
|
|
80
169
|
var toUser = (userData) => {
|
|
@@ -100,32 +189,89 @@ var claimsToUser = (claims) => {
|
|
|
100
189
|
const userMeta = claims.user_metadata ?? {};
|
|
101
190
|
const name = userMeta.full_name || userMeta.name;
|
|
102
191
|
return {
|
|
103
|
-
id:
|
|
104
|
-
email:
|
|
192
|
+
id: claims.sub ?? "",
|
|
193
|
+
email: claims.email,
|
|
105
194
|
provider: toAuthProvider(appMeta.provider),
|
|
106
195
|
name: typeof name === "string" ? name : void 0,
|
|
107
196
|
metadata: userMeta
|
|
108
197
|
};
|
|
109
198
|
};
|
|
199
|
+
var hydrating = false;
|
|
200
|
+
var backgroundHydrate = (accessToken) => {
|
|
201
|
+
if (hydrating) return;
|
|
202
|
+
hydrating = true;
|
|
203
|
+
const refreshToken = getCookie(NF_REFRESH_COOKIE) ?? "";
|
|
204
|
+
setTimeout(() => {
|
|
205
|
+
try {
|
|
206
|
+
const client = getClient();
|
|
207
|
+
client.createUser(
|
|
208
|
+
{
|
|
209
|
+
access_token: accessToken,
|
|
210
|
+
token_type: "bearer",
|
|
211
|
+
expires_in: 3600,
|
|
212
|
+
expires_at: Math.floor(Date.now() / 1e3) + 3600,
|
|
213
|
+
refresh_token: refreshToken
|
|
214
|
+
},
|
|
215
|
+
true
|
|
216
|
+
).catch(() => {
|
|
217
|
+
}).finally(() => {
|
|
218
|
+
hydrating = false;
|
|
219
|
+
});
|
|
220
|
+
} catch {
|
|
221
|
+
hydrating = false;
|
|
222
|
+
}
|
|
223
|
+
}, 0);
|
|
224
|
+
};
|
|
225
|
+
var decodeJwtPayload = (token) => {
|
|
226
|
+
try {
|
|
227
|
+
const parts = token.split(".");
|
|
228
|
+
if (parts.length !== 3) return null;
|
|
229
|
+
const payload = atob(parts[1].replace(/-/g, "+").replace(/_/g, "/"));
|
|
230
|
+
return JSON.parse(payload);
|
|
231
|
+
} catch {
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
234
|
+
};
|
|
110
235
|
var getUser = () => {
|
|
111
236
|
if (isBrowser()) {
|
|
112
237
|
const client = getGoTrueClient();
|
|
113
238
|
const currentUser = client?.currentUser() ?? null;
|
|
114
|
-
if (
|
|
115
|
-
|
|
239
|
+
if (currentUser) {
|
|
240
|
+
const jwt2 = getCookie(NF_JWT_COOKIE);
|
|
241
|
+
if (!jwt2) {
|
|
242
|
+
try {
|
|
243
|
+
currentUser.clearSession();
|
|
244
|
+
} catch {
|
|
245
|
+
}
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
return toUser(currentUser);
|
|
249
|
+
}
|
|
250
|
+
const jwt = getCookie(NF_JWT_COOKIE);
|
|
251
|
+
if (!jwt) return null;
|
|
252
|
+
const claims = decodeJwtPayload(jwt);
|
|
253
|
+
if (!claims) return null;
|
|
254
|
+
backgroundHydrate(jwt);
|
|
255
|
+
return claimsToUser(claims);
|
|
116
256
|
}
|
|
257
|
+
triggerNextjsDynamic();
|
|
117
258
|
const identityContext = globalThis.netlifyIdentityContext;
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
259
|
+
if (identityContext?.user) {
|
|
260
|
+
return claimsToUser(identityContext.user);
|
|
261
|
+
}
|
|
262
|
+
const serverJwt = getServerCookie(NF_JWT_COOKIE);
|
|
263
|
+
if (serverJwt) {
|
|
264
|
+
const claims = decodeJwtPayload(serverJwt);
|
|
265
|
+
if (claims) return claimsToUser(claims);
|
|
266
|
+
}
|
|
267
|
+
return null;
|
|
122
268
|
};
|
|
123
269
|
var isAuthenticated = () => getUser() !== null;
|
|
124
270
|
|
|
125
271
|
// src/config.ts
|
|
126
272
|
var getIdentityConfig = () => {
|
|
127
273
|
if (isBrowser()) {
|
|
128
|
-
return { url: `${window.location.origin}
|
|
274
|
+
return { url: `${window.location.origin}${IDENTITY_PATH}` };
|
|
129
275
|
}
|
|
130
276
|
return getIdentityContext();
|
|
131
277
|
};
|
|
@@ -153,6 +299,20 @@ var getSettings = async () => {
|
|
|
153
299
|
};
|
|
154
300
|
|
|
155
301
|
// src/auth.ts
|
|
302
|
+
var getCookies = () => {
|
|
303
|
+
const cookies = globalThis.Netlify?.context?.cookies;
|
|
304
|
+
if (!cookies) {
|
|
305
|
+
throw new AuthError("Server-side auth requires Netlify Functions runtime");
|
|
306
|
+
}
|
|
307
|
+
return cookies;
|
|
308
|
+
};
|
|
309
|
+
var getServerIdentityUrl = () => {
|
|
310
|
+
const ctx = getIdentityContext();
|
|
311
|
+
if (!ctx?.url) {
|
|
312
|
+
throw new AuthError("Could not determine the Identity endpoint URL on the server");
|
|
313
|
+
}
|
|
314
|
+
return ctx.url;
|
|
315
|
+
};
|
|
156
316
|
var persistSession = true;
|
|
157
317
|
var listeners = /* @__PURE__ */ new Set();
|
|
158
318
|
var emitAuthEvent = (event, user) => {
|
|
@@ -187,9 +347,58 @@ var onAuthChange = (callback) => {
|
|
|
187
347
|
};
|
|
188
348
|
};
|
|
189
349
|
var login = async (email, password) => {
|
|
350
|
+
if (!isBrowser()) {
|
|
351
|
+
const identityUrl = getServerIdentityUrl();
|
|
352
|
+
const cookies = getCookies();
|
|
353
|
+
const body = new URLSearchParams({
|
|
354
|
+
grant_type: "password",
|
|
355
|
+
username: email,
|
|
356
|
+
password
|
|
357
|
+
});
|
|
358
|
+
let res;
|
|
359
|
+
try {
|
|
360
|
+
res = await fetch(`${identityUrl}/token`, {
|
|
361
|
+
method: "POST",
|
|
362
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
363
|
+
body: body.toString()
|
|
364
|
+
});
|
|
365
|
+
} catch (error) {
|
|
366
|
+
throw new AuthError(error.message, void 0, { cause: error });
|
|
367
|
+
}
|
|
368
|
+
if (!res.ok) {
|
|
369
|
+
const errorBody = await res.json().catch(() => ({}));
|
|
370
|
+
throw new AuthError(
|
|
371
|
+
errorBody.msg || errorBody.error_description || `Login failed (${res.status})`,
|
|
372
|
+
res.status
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
const data = await res.json();
|
|
376
|
+
const accessToken = data.access_token;
|
|
377
|
+
let userRes;
|
|
378
|
+
try {
|
|
379
|
+
userRes = await fetch(`${identityUrl}/user`, {
|
|
380
|
+
headers: { Authorization: `Bearer ${accessToken}` }
|
|
381
|
+
});
|
|
382
|
+
} catch (error) {
|
|
383
|
+
throw new AuthError(error.message, void 0, { cause: error });
|
|
384
|
+
}
|
|
385
|
+
if (!userRes.ok) {
|
|
386
|
+
const errorBody = await userRes.json().catch(() => ({}));
|
|
387
|
+
throw new AuthError(
|
|
388
|
+
errorBody.msg || `Failed to fetch user data (${userRes.status})`,
|
|
389
|
+
userRes.status
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
const userData = await userRes.json();
|
|
393
|
+
const user = toUser(userData);
|
|
394
|
+
setAuthCookies(cookies, accessToken, data.refresh_token);
|
|
395
|
+
return user;
|
|
396
|
+
}
|
|
190
397
|
const client = getClient();
|
|
191
398
|
try {
|
|
192
399
|
const gotrueUser = await client.login(email, password, persistSession);
|
|
400
|
+
const jwt = await gotrueUser.jwt();
|
|
401
|
+
setBrowserAuthCookies(jwt);
|
|
193
402
|
const user = toUser(gotrueUser);
|
|
194
403
|
emitAuthEvent("login", user);
|
|
195
404
|
return user;
|
|
@@ -198,6 +407,34 @@ var login = async (email, password) => {
|
|
|
198
407
|
}
|
|
199
408
|
};
|
|
200
409
|
var signup = async (email, password, data) => {
|
|
410
|
+
if (!isBrowser()) {
|
|
411
|
+
const identityUrl = getServerIdentityUrl();
|
|
412
|
+
const cookies = getCookies();
|
|
413
|
+
let res;
|
|
414
|
+
try {
|
|
415
|
+
res = await fetch(`${identityUrl}/signup`, {
|
|
416
|
+
method: "POST",
|
|
417
|
+
headers: { "Content-Type": "application/json" },
|
|
418
|
+
body: JSON.stringify({ email, password, data })
|
|
419
|
+
});
|
|
420
|
+
} catch (error) {
|
|
421
|
+
throw new AuthError(error.message, void 0, { cause: error });
|
|
422
|
+
}
|
|
423
|
+
if (!res.ok) {
|
|
424
|
+
const errorBody = await res.json().catch(() => ({}));
|
|
425
|
+
throw new AuthError(errorBody.msg || `Signup failed (${res.status})`, res.status);
|
|
426
|
+
}
|
|
427
|
+
const responseData = await res.json();
|
|
428
|
+
const user = toUser(responseData);
|
|
429
|
+
if (responseData.confirmed_at) {
|
|
430
|
+
const responseRecord = responseData;
|
|
431
|
+
const accessToken = responseRecord.access_token;
|
|
432
|
+
if (accessToken) {
|
|
433
|
+
setAuthCookies(cookies, accessToken, responseRecord.refresh_token);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return user;
|
|
437
|
+
}
|
|
201
438
|
const client = getClient();
|
|
202
439
|
try {
|
|
203
440
|
const response = await client.signup(email, password, data);
|
|
@@ -211,12 +448,30 @@ var signup = async (email, password, data) => {
|
|
|
211
448
|
}
|
|
212
449
|
};
|
|
213
450
|
var logout = async () => {
|
|
451
|
+
if (!isBrowser()) {
|
|
452
|
+
const identityUrl = getServerIdentityUrl();
|
|
453
|
+
const cookies = getCookies();
|
|
454
|
+
const jwt = cookies.get(NF_JWT_COOKIE);
|
|
455
|
+
if (jwt) {
|
|
456
|
+
try {
|
|
457
|
+
await fetch(`${identityUrl}/logout`, {
|
|
458
|
+
method: "POST",
|
|
459
|
+
headers: { Authorization: `Bearer ${jwt}` }
|
|
460
|
+
});
|
|
461
|
+
} catch (error) {
|
|
462
|
+
throw new AuthError(error.message, void 0, { cause: error });
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
deleteAuthCookies(cookies);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
214
468
|
const client = getClient();
|
|
215
469
|
try {
|
|
216
470
|
const currentUser = client.currentUser();
|
|
217
471
|
if (currentUser) {
|
|
218
472
|
await currentUser.logout();
|
|
219
473
|
}
|
|
474
|
+
deleteBrowserAuthCookies();
|
|
220
475
|
emitAuthEvent("logout", null);
|
|
221
476
|
} catch (error) {
|
|
222
477
|
throw new AuthError(error.message, void 0, { cause: error });
|
|
@@ -239,16 +494,18 @@ var handleAuthCallback = async () => {
|
|
|
239
494
|
const params = new URLSearchParams(hash);
|
|
240
495
|
const accessToken = params.get("access_token");
|
|
241
496
|
if (accessToken) {
|
|
497
|
+
const refreshToken = params.get("refresh_token") ?? "";
|
|
242
498
|
const gotrueUser = await client.createUser(
|
|
243
499
|
{
|
|
244
500
|
access_token: accessToken,
|
|
245
501
|
token_type: params.get("token_type") ?? "bearer",
|
|
246
502
|
expires_in: Number(params.get("expires_in")),
|
|
247
503
|
expires_at: Number(params.get("expires_at")),
|
|
248
|
-
refresh_token:
|
|
504
|
+
refresh_token: refreshToken
|
|
249
505
|
},
|
|
250
506
|
persistSession
|
|
251
507
|
);
|
|
508
|
+
setBrowserAuthCookies(accessToken, refreshToken || void 0);
|
|
252
509
|
const user = toUser(gotrueUser);
|
|
253
510
|
clearHash();
|
|
254
511
|
emitAuthEvent("login", user);
|
|
@@ -257,6 +514,8 @@ var handleAuthCallback = async () => {
|
|
|
257
514
|
const confirmationToken = params.get("confirmation_token");
|
|
258
515
|
if (confirmationToken) {
|
|
259
516
|
const gotrueUser = await client.confirm(confirmationToken, persistSession);
|
|
517
|
+
const jwt = await gotrueUser.jwt();
|
|
518
|
+
setBrowserAuthCookies(jwt);
|
|
260
519
|
const user = toUser(gotrueUser);
|
|
261
520
|
clearHash();
|
|
262
521
|
emitAuthEvent("login", user);
|
|
@@ -265,6 +524,8 @@ var handleAuthCallback = async () => {
|
|
|
265
524
|
const recoveryToken = params.get("recovery_token");
|
|
266
525
|
if (recoveryToken) {
|
|
267
526
|
const gotrueUser = await client.recover(recoveryToken, persistSession);
|
|
527
|
+
const jwt = await gotrueUser.jwt();
|
|
528
|
+
setBrowserAuthCookies(jwt);
|
|
268
529
|
const user = toUser(gotrueUser);
|
|
269
530
|
clearHash();
|
|
270
531
|
emitAuthEvent("login", user);
|
|
@@ -279,11 +540,27 @@ var handleAuthCallback = async () => {
|
|
|
279
540
|
if (emailChangeToken) {
|
|
280
541
|
const currentUser = client.currentUser();
|
|
281
542
|
if (!currentUser) {
|
|
282
|
-
|
|
283
|
-
return { type: "email_change", user: null, token: emailChangeToken };
|
|
543
|
+
throw new AuthError("Email change verification requires an active browser session");
|
|
284
544
|
}
|
|
285
|
-
const
|
|
286
|
-
const
|
|
545
|
+
const jwt = await currentUser.jwt();
|
|
546
|
+
const identityUrl = `${window.location.origin}${IDENTITY_PATH}`;
|
|
547
|
+
const emailChangeRes = await fetch(`${identityUrl}/user`, {
|
|
548
|
+
method: "PUT",
|
|
549
|
+
headers: {
|
|
550
|
+
"Content-Type": "application/json",
|
|
551
|
+
Authorization: `Bearer ${jwt}`
|
|
552
|
+
},
|
|
553
|
+
body: JSON.stringify({ email_change_token: emailChangeToken })
|
|
554
|
+
});
|
|
555
|
+
if (!emailChangeRes.ok) {
|
|
556
|
+
const errorBody = await emailChangeRes.json().catch(() => ({}));
|
|
557
|
+
throw new AuthError(
|
|
558
|
+
errorBody.msg || `Email change verification failed (${emailChangeRes.status})`,
|
|
559
|
+
emailChangeRes.status
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
const emailChangeData = await emailChangeRes.json();
|
|
563
|
+
const user = toUser(emailChangeData);
|
|
287
564
|
clearHash();
|
|
288
565
|
emitAuthEvent("user_updated", user);
|
|
289
566
|
return { type: "email_change", user };
|
|
@@ -296,8 +573,43 @@ var handleAuthCallback = async () => {
|
|
|
296
573
|
var clearHash = () => {
|
|
297
574
|
history.replaceState(null, "", window.location.pathname + window.location.search);
|
|
298
575
|
};
|
|
576
|
+
var hydrateSession = async () => {
|
|
577
|
+
if (!isBrowser()) return null;
|
|
578
|
+
const client = getClient();
|
|
579
|
+
const currentUser = client.currentUser();
|
|
580
|
+
if (currentUser) return toUser(currentUser);
|
|
581
|
+
const accessToken = getCookie(NF_JWT_COOKIE);
|
|
582
|
+
if (!accessToken) return null;
|
|
583
|
+
const refreshToken = getCookie(NF_REFRESH_COOKIE) ?? "";
|
|
584
|
+
const gotrueUser = await client.createUser(
|
|
585
|
+
{
|
|
586
|
+
access_token: accessToken,
|
|
587
|
+
token_type: "bearer",
|
|
588
|
+
expires_in: 3600,
|
|
589
|
+
expires_at: Math.floor(Date.now() / 1e3) + 3600,
|
|
590
|
+
refresh_token: refreshToken
|
|
591
|
+
},
|
|
592
|
+
persistSession
|
|
593
|
+
);
|
|
594
|
+
const user = toUser(gotrueUser);
|
|
595
|
+
emitAuthEvent("login", user);
|
|
596
|
+
return user;
|
|
597
|
+
};
|
|
299
598
|
|
|
300
599
|
// src/account.ts
|
|
600
|
+
var ensureCurrentUser = async () => {
|
|
601
|
+
const client = getClient();
|
|
602
|
+
let currentUser = client.currentUser();
|
|
603
|
+
if (!currentUser && isBrowser()) {
|
|
604
|
+
try {
|
|
605
|
+
await hydrateSession();
|
|
606
|
+
} catch {
|
|
607
|
+
}
|
|
608
|
+
currentUser = client.currentUser();
|
|
609
|
+
}
|
|
610
|
+
if (!currentUser) throw new AuthError("No user is currently logged in");
|
|
611
|
+
return currentUser;
|
|
612
|
+
};
|
|
301
613
|
var requestPasswordRecovery = async (email) => {
|
|
302
614
|
const client = getClient();
|
|
303
615
|
try {
|
|
@@ -306,6 +618,18 @@ var requestPasswordRecovery = async (email) => {
|
|
|
306
618
|
throw new AuthError(error.message, void 0, { cause: error });
|
|
307
619
|
}
|
|
308
620
|
};
|
|
621
|
+
var recoverPassword = async (token, newPassword) => {
|
|
622
|
+
const client = getClient();
|
|
623
|
+
try {
|
|
624
|
+
const gotrueUser = await client.recover(token, persistSession);
|
|
625
|
+
const updatedUser = await gotrueUser.update({ password: newPassword });
|
|
626
|
+
const user = toUser(updatedUser);
|
|
627
|
+
emitAuthEvent("login", user);
|
|
628
|
+
return user;
|
|
629
|
+
} catch (error) {
|
|
630
|
+
throw new AuthError(error.message, void 0, { cause: error });
|
|
631
|
+
}
|
|
632
|
+
};
|
|
309
633
|
var confirmEmail = async (token) => {
|
|
310
634
|
const client = getClient();
|
|
311
635
|
try {
|
|
@@ -329,22 +653,37 @@ var acceptInvite = async (token, password) => {
|
|
|
329
653
|
}
|
|
330
654
|
};
|
|
331
655
|
var verifyEmailChange = async (token) => {
|
|
332
|
-
|
|
333
|
-
const currentUser =
|
|
334
|
-
|
|
656
|
+
if (!isBrowser()) throw new AuthError("verifyEmailChange() is only available in the browser");
|
|
657
|
+
const currentUser = await ensureCurrentUser();
|
|
658
|
+
const jwt = await currentUser.jwt();
|
|
659
|
+
const identityUrl = `${window.location.origin}${IDENTITY_PATH}`;
|
|
335
660
|
try {
|
|
336
|
-
const
|
|
337
|
-
|
|
661
|
+
const res = await fetch(`${identityUrl}/user`, {
|
|
662
|
+
method: "PUT",
|
|
663
|
+
headers: {
|
|
664
|
+
"Content-Type": "application/json",
|
|
665
|
+
Authorization: `Bearer ${jwt}`
|
|
666
|
+
},
|
|
667
|
+
body: JSON.stringify({ email_change_token: token })
|
|
668
|
+
});
|
|
669
|
+
if (!res.ok) {
|
|
670
|
+
const errorBody = await res.json().catch(() => ({}));
|
|
671
|
+
throw new AuthError(
|
|
672
|
+
errorBody.msg || `Email change verification failed (${res.status})`,
|
|
673
|
+
res.status
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
const userData = await res.json();
|
|
677
|
+
const user = toUser(userData);
|
|
338
678
|
emitAuthEvent("user_updated", user);
|
|
339
679
|
return user;
|
|
340
680
|
} catch (error) {
|
|
681
|
+
if (error instanceof AuthError) throw error;
|
|
341
682
|
throw new AuthError(error.message, void 0, { cause: error });
|
|
342
683
|
}
|
|
343
684
|
};
|
|
344
685
|
var updateUser = async (updates) => {
|
|
345
|
-
const
|
|
346
|
-
const currentUser = client.currentUser();
|
|
347
|
-
if (!currentUser) throw new AuthError("No user is currently logged in");
|
|
686
|
+
const currentUser = await ensureCurrentUser();
|
|
348
687
|
try {
|
|
349
688
|
const updatedUser = await currentUser.update(updates);
|
|
350
689
|
const user = toUser(updatedUser);
|
|
@@ -368,6 +707,7 @@ export {
|
|
|
368
707
|
logout,
|
|
369
708
|
oauthLogin,
|
|
370
709
|
onAuthChange,
|
|
710
|
+
recoverPassword,
|
|
371
711
|
requestPasswordRecovery,
|
|
372
712
|
signup,
|
|
373
713
|
updateUser,
|