@insforge/sdk 1.1.2-pkce.0 → 1.1.2-pkce.1
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/index.d.mts +25 -141
- package/dist/index.d.ts +25 -141
- package/dist/index.js +180 -447
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +180 -447
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -304,21 +304,12 @@ var TokenManager = class {
|
|
|
304
304
|
}
|
|
305
305
|
};
|
|
306
306
|
|
|
307
|
-
// src/modules/auth.ts
|
|
308
|
-
function isHostedAuthEnvironment() {
|
|
309
|
-
if (typeof window === "undefined") {
|
|
310
|
-
return false;
|
|
311
|
-
}
|
|
312
|
-
const { hostname, port, protocol } = window.location;
|
|
313
|
-
if (hostname === "localhost" && port === "7130") {
|
|
314
|
-
return true;
|
|
315
|
-
}
|
|
316
|
-
if (protocol === "https:" && hostname.endsWith(".insforge.app")) {
|
|
317
|
-
return true;
|
|
318
|
-
}
|
|
319
|
-
return false;
|
|
320
|
-
}
|
|
307
|
+
// src/modules/auth/helpers.ts
|
|
321
308
|
var PKCE_VERIFIER_KEY = "insforge_pkce_verifier";
|
|
309
|
+
function base64UrlEncode(buffer) {
|
|
310
|
+
const base64 = btoa(String.fromCharCode(...buffer));
|
|
311
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
312
|
+
}
|
|
322
313
|
function generateCodeVerifier() {
|
|
323
314
|
const array = new Uint8Array(32);
|
|
324
315
|
crypto.getRandomValues(array);
|
|
@@ -330,10 +321,6 @@ async function generateCodeChallenge(verifier) {
|
|
|
330
321
|
const hash = await crypto.subtle.digest("SHA-256", data);
|
|
331
322
|
return base64UrlEncode(new Uint8Array(hash));
|
|
332
323
|
}
|
|
333
|
-
function base64UrlEncode(buffer) {
|
|
334
|
-
const base64 = btoa(String.fromCharCode(...buffer));
|
|
335
|
-
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
336
|
-
}
|
|
337
324
|
function storePkceVerifier(verifier) {
|
|
338
325
|
if (typeof sessionStorage !== "undefined") {
|
|
339
326
|
sessionStorage.setItem(PKCE_VERIFIER_KEY, verifier);
|
|
@@ -349,6 +336,42 @@ function retrievePkceVerifier() {
|
|
|
349
336
|
}
|
|
350
337
|
return verifier;
|
|
351
338
|
}
|
|
339
|
+
function isHostedAuthEnvironment() {
|
|
340
|
+
if (typeof window === "undefined") {
|
|
341
|
+
return false;
|
|
342
|
+
}
|
|
343
|
+
const { hostname, port, protocol } = window.location;
|
|
344
|
+
if (hostname === "localhost" && port === "7130") {
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
if (protocol === "https:" && hostname.endsWith(".insforge.app")) {
|
|
348
|
+
return true;
|
|
349
|
+
}
|
|
350
|
+
return false;
|
|
351
|
+
}
|
|
352
|
+
function wrapError(error, fallbackMessage) {
|
|
353
|
+
if (error instanceof InsForgeError) {
|
|
354
|
+
return { data: null, error };
|
|
355
|
+
}
|
|
356
|
+
return {
|
|
357
|
+
data: null,
|
|
358
|
+
error: new InsForgeError(
|
|
359
|
+
error instanceof Error ? error.message : fallbackMessage,
|
|
360
|
+
500,
|
|
361
|
+
"UNEXPECTED_ERROR"
|
|
362
|
+
)
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
function cleanUrlParams(...params) {
|
|
366
|
+
if (typeof window === "undefined") {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
const url = new URL(window.location.href);
|
|
370
|
+
params.forEach((p) => url.searchParams.delete(p));
|
|
371
|
+
window.history.replaceState({}, document.title, url.toString());
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// src/modules/auth/auth.ts
|
|
352
375
|
var Auth = class {
|
|
353
376
|
constructor(http, tokenManager) {
|
|
354
377
|
this.http = http;
|
|
@@ -356,12 +379,31 @@ var Auth = class {
|
|
|
356
379
|
this.authCallbackHandled = this.detectAuthCallback();
|
|
357
380
|
}
|
|
358
381
|
/**
|
|
359
|
-
*
|
|
360
|
-
*
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
382
|
+
* Save session from API response
|
|
383
|
+
* Handles token storage, CSRF token, and HTTP client auth header
|
|
384
|
+
*/
|
|
385
|
+
saveSessionFromResponse(response) {
|
|
386
|
+
if (isHostedAuthEnvironment() || !response.accessToken || !response.user) {
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
const session = {
|
|
390
|
+
accessToken: response.accessToken,
|
|
391
|
+
user: response.user
|
|
392
|
+
};
|
|
393
|
+
if (response.csrfToken) {
|
|
394
|
+
this.tokenManager.setMemoryMode();
|
|
395
|
+
setCsrfToken(response.csrfToken);
|
|
396
|
+
}
|
|
397
|
+
this.tokenManager.saveSession(session);
|
|
398
|
+
this.http.setAuthToken(response.accessToken);
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
401
|
+
// ============================================================================
|
|
402
|
+
// OAuth Callback Detection (runs on initialization)
|
|
403
|
+
// ============================================================================
|
|
404
|
+
/**
|
|
405
|
+
* Detect and handle OAuth callback parameters in URL
|
|
406
|
+
* Supports PKCE flow (insforge_code) and legacy flow (access_token in URL)
|
|
365
407
|
*/
|
|
366
408
|
async detectAuthCallback() {
|
|
367
409
|
if (typeof window === "undefined") return;
|
|
@@ -369,17 +411,13 @@ var Auth = class {
|
|
|
369
411
|
const params = new URLSearchParams(window.location.search);
|
|
370
412
|
const error = params.get("error");
|
|
371
413
|
if (error) {
|
|
372
|
-
|
|
373
|
-
url.searchParams.delete("error");
|
|
374
|
-
window.history.replaceState({}, document.title, url.toString());
|
|
414
|
+
cleanUrlParams("error");
|
|
375
415
|
console.debug("OAuth callback error:", error);
|
|
376
416
|
return;
|
|
377
417
|
}
|
|
378
418
|
const code = params.get("insforge_code");
|
|
379
419
|
if (code) {
|
|
380
|
-
|
|
381
|
-
url.searchParams.delete("insforge_code");
|
|
382
|
-
window.history.replaceState({}, document.title, url.toString());
|
|
420
|
+
cleanUrlParams("insforge_code");
|
|
383
421
|
const { error: exchangeError } = await this.exchangeOAuthCode(code);
|
|
384
422
|
if (exchangeError) {
|
|
385
423
|
console.debug("OAuth code exchange failed:", exchangeError.message);
|
|
@@ -389,9 +427,9 @@ var Auth = class {
|
|
|
389
427
|
const accessToken = params.get("access_token");
|
|
390
428
|
const userId = params.get("user_id");
|
|
391
429
|
const email = params.get("email");
|
|
392
|
-
const name = params.get("name");
|
|
393
|
-
const csrfToken = params.get("csrf_token");
|
|
394
430
|
if (accessToken && userId && email) {
|
|
431
|
+
const csrfToken = params.get("csrf_token");
|
|
432
|
+
const name = params.get("name");
|
|
395
433
|
if (csrfToken) {
|
|
396
434
|
this.tokenManager.setMemoryMode();
|
|
397
435
|
setCsrfToken(csrfToken);
|
|
@@ -410,93 +448,62 @@ var Auth = class {
|
|
|
410
448
|
};
|
|
411
449
|
this.tokenManager.saveSession(session);
|
|
412
450
|
this.http.setAuthToken(accessToken);
|
|
413
|
-
|
|
414
|
-
url.searchParams.delete("access_token");
|
|
415
|
-
url.searchParams.delete("user_id");
|
|
416
|
-
url.searchParams.delete("email");
|
|
417
|
-
url.searchParams.delete("name");
|
|
418
|
-
url.searchParams.delete("csrf_token");
|
|
419
|
-
window.history.replaceState({}, document.title, url.toString());
|
|
451
|
+
cleanUrlParams("access_token", "user_id", "email", "name", "csrf_token");
|
|
420
452
|
}
|
|
421
453
|
} catch (error) {
|
|
422
454
|
console.debug("OAuth callback detection skipped:", error);
|
|
423
455
|
}
|
|
424
456
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
457
|
+
// ============================================================================
|
|
458
|
+
// Sign Up / Sign In / Sign Out
|
|
459
|
+
// ============================================================================
|
|
428
460
|
async signUp(request) {
|
|
429
461
|
try {
|
|
430
|
-
const response = await this.http.post(
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
this.tokenManager.setMemoryMode();
|
|
438
|
-
setCsrfToken(response.csrfToken);
|
|
439
|
-
}
|
|
440
|
-
this.tokenManager.saveSession(session);
|
|
441
|
-
this.http.setAuthToken(response.accessToken);
|
|
462
|
+
const response = await this.http.post(
|
|
463
|
+
"/api/auth/users",
|
|
464
|
+
request,
|
|
465
|
+
{ credentials: "include" }
|
|
466
|
+
);
|
|
467
|
+
if (response.accessToken && response.user) {
|
|
468
|
+
this.saveSessionFromResponse(response);
|
|
442
469
|
}
|
|
443
|
-
return {
|
|
444
|
-
data: response,
|
|
445
|
-
error: null
|
|
446
|
-
};
|
|
470
|
+
return { data: response, error: null };
|
|
447
471
|
} catch (error) {
|
|
448
|
-
|
|
449
|
-
return { data: null, error };
|
|
450
|
-
}
|
|
451
|
-
return {
|
|
452
|
-
data: null,
|
|
453
|
-
error: new InsForgeError(
|
|
454
|
-
error instanceof Error ? error.message : "An unexpected error occurred during sign up",
|
|
455
|
-
500,
|
|
456
|
-
"UNEXPECTED_ERROR"
|
|
457
|
-
)
|
|
458
|
-
};
|
|
472
|
+
return wrapError(error, "An unexpected error occurred during sign up");
|
|
459
473
|
}
|
|
460
474
|
}
|
|
461
|
-
/**
|
|
462
|
-
* Sign in with email and password
|
|
463
|
-
*/
|
|
464
475
|
async signInWithPassword(request) {
|
|
465
476
|
try {
|
|
466
|
-
const response = await this.http.post(
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
this.tokenManager.setMemoryMode();
|
|
474
|
-
setCsrfToken(response.csrfToken);
|
|
475
|
-
}
|
|
476
|
-
this.tokenManager.saveSession(session);
|
|
477
|
-
this.http.setAuthToken(response.accessToken);
|
|
478
|
-
}
|
|
479
|
-
return {
|
|
480
|
-
data: response,
|
|
481
|
-
error: null
|
|
482
|
-
};
|
|
477
|
+
const response = await this.http.post(
|
|
478
|
+
"/api/auth/sessions",
|
|
479
|
+
request,
|
|
480
|
+
{ credentials: "include" }
|
|
481
|
+
);
|
|
482
|
+
this.saveSessionFromResponse(response);
|
|
483
|
+
return { data: response, error: null };
|
|
483
484
|
} catch (error) {
|
|
484
|
-
|
|
485
|
-
|
|
485
|
+
return wrapError(error, "An unexpected error occurred during sign in");
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
async signOut() {
|
|
489
|
+
try {
|
|
490
|
+
try {
|
|
491
|
+
await this.http.post("/api/auth/logout", void 0, { credentials: "include" });
|
|
492
|
+
} catch {
|
|
486
493
|
}
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
)
|
|
494
|
-
};
|
|
494
|
+
this.tokenManager.clearSession();
|
|
495
|
+
this.http.setAuthToken(null);
|
|
496
|
+
clearCsrfToken();
|
|
497
|
+
return { error: null };
|
|
498
|
+
} catch {
|
|
499
|
+
return { error: new InsForgeError("Failed to sign out", 500, "SIGNOUT_ERROR") };
|
|
495
500
|
}
|
|
496
501
|
}
|
|
502
|
+
// ============================================================================
|
|
503
|
+
// OAuth Authentication
|
|
504
|
+
// ============================================================================
|
|
497
505
|
/**
|
|
498
|
-
* Sign in with OAuth provider
|
|
499
|
-
* Uses PKCE (Proof Key for Code Exchange) for enhanced security
|
|
506
|
+
* Sign in with OAuth provider using PKCE flow
|
|
500
507
|
*/
|
|
501
508
|
async signInWithOAuth(options) {
|
|
502
509
|
try {
|
|
@@ -504,25 +511,18 @@ var Auth = class {
|
|
|
504
511
|
const codeVerifier = generateCodeVerifier();
|
|
505
512
|
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
506
513
|
storePkceVerifier(codeVerifier);
|
|
507
|
-
const params = {
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
params
|
|
512
|
-
|
|
513
|
-
const endpoint = `/api/auth/oauth/${provider}`;
|
|
514
|
-
const response = await this.http.get(endpoint, { params });
|
|
514
|
+
const params = { code_challenge: codeChallenge };
|
|
515
|
+
if (redirectTo) params.redirect_uri = redirectTo;
|
|
516
|
+
const response = await this.http.get(
|
|
517
|
+
`/api/auth/oauth/${provider}`,
|
|
518
|
+
{ params }
|
|
519
|
+
);
|
|
515
520
|
if (typeof window !== "undefined" && !skipBrowserRedirect) {
|
|
516
521
|
window.location.href = response.authUrl;
|
|
517
522
|
return { data: {}, error: null };
|
|
518
523
|
}
|
|
519
524
|
return {
|
|
520
|
-
data: {
|
|
521
|
-
url: response.authUrl,
|
|
522
|
-
provider,
|
|
523
|
-
codeVerifier
|
|
524
|
-
// Return verifier for manual flow (skipBrowserRedirect)
|
|
525
|
-
},
|
|
525
|
+
data: { url: response.authUrl, provider, codeVerifier },
|
|
526
526
|
error: null
|
|
527
527
|
};
|
|
528
528
|
} catch (error) {
|
|
@@ -541,30 +541,7 @@ var Auth = class {
|
|
|
541
541
|
}
|
|
542
542
|
/**
|
|
543
543
|
* Exchange OAuth authorization code for tokens (PKCE flow)
|
|
544
|
-
*
|
|
545
|
-
* After OAuth callback redirects with an `insforge_code` parameter, call this method
|
|
546
|
-
* to exchange it for access tokens. The code verifier is automatically
|
|
547
|
-
* retrieved from sessionStorage if available.
|
|
548
|
-
*
|
|
549
|
-
* Note: This is called automatically by the SDK on initialization. You typically
|
|
550
|
-
* don't need to call this directly unless using `skipBrowserRedirect: true`.
|
|
551
|
-
*
|
|
552
|
-
* @param code - The authorization code from OAuth callback URL
|
|
553
|
-
* @param codeVerifier - Optional code verifier (auto-retrieved from sessionStorage if not provided)
|
|
554
|
-
* @returns Session data with access token and user info
|
|
555
|
-
*
|
|
556
|
-
* @example
|
|
557
|
-
* ```ts
|
|
558
|
-
* // Automatic verifier retrieval (recommended for browser)
|
|
559
|
-
* const params = new URLSearchParams(window.location.search);
|
|
560
|
-
* const code = params.get('insforge_code');
|
|
561
|
-
* if (code) {
|
|
562
|
-
* const { data, error } = await insforge.auth.exchangeOAuthCode(code);
|
|
563
|
-
* }
|
|
564
|
-
*
|
|
565
|
-
* // Manual verifier (for custom flows)
|
|
566
|
-
* const { data, error } = await insforge.auth.exchangeOAuthCode(code, codeVerifier);
|
|
567
|
-
* ```
|
|
544
|
+
* Called automatically on initialization when insforge_code is in URL
|
|
568
545
|
*/
|
|
569
546
|
async exchangeOAuthCode(code, codeVerifier) {
|
|
570
547
|
try {
|
|
@@ -579,23 +556,9 @@ var Auth = class {
|
|
|
579
556
|
)
|
|
580
557
|
};
|
|
581
558
|
}
|
|
582
|
-
const request = {
|
|
583
|
-
code,
|
|
584
|
-
code_verifier: verifier
|
|
585
|
-
};
|
|
559
|
+
const request = { code, code_verifier: verifier };
|
|
586
560
|
const response = await this.http.post("/api/auth/oauth/exchange", request, { credentials: "include" });
|
|
587
|
-
|
|
588
|
-
const session = {
|
|
589
|
-
accessToken: response.accessToken,
|
|
590
|
-
user: response.user
|
|
591
|
-
};
|
|
592
|
-
if (response.csrfToken) {
|
|
593
|
-
this.tokenManager.setMemoryMode();
|
|
594
|
-
setCsrfToken(response.csrfToken);
|
|
595
|
-
}
|
|
596
|
-
this.tokenManager.saveSession(session);
|
|
597
|
-
this.http.setAuthToken(response.accessToken);
|
|
598
|
-
}
|
|
561
|
+
this.saveSessionFromResponse(response);
|
|
599
562
|
return {
|
|
600
563
|
data: {
|
|
601
564
|
accessToken: response.accessToken,
|
|
@@ -605,108 +568,14 @@ var Auth = class {
|
|
|
605
568
|
error: null
|
|
606
569
|
};
|
|
607
570
|
} catch (error) {
|
|
608
|
-
|
|
609
|
-
return { data: null, error };
|
|
610
|
-
}
|
|
611
|
-
return {
|
|
612
|
-
data: null,
|
|
613
|
-
error: new InsForgeError(
|
|
614
|
-
"An unexpected error occurred during OAuth code exchange",
|
|
615
|
-
500,
|
|
616
|
-
"UNEXPECTED_ERROR"
|
|
617
|
-
)
|
|
618
|
-
};
|
|
571
|
+
return wrapError(error, "An unexpected error occurred during OAuth code exchange");
|
|
619
572
|
}
|
|
620
573
|
}
|
|
574
|
+
// ============================================================================
|
|
575
|
+
// Session Management
|
|
576
|
+
// ============================================================================
|
|
621
577
|
/**
|
|
622
|
-
*
|
|
623
|
-
*/
|
|
624
|
-
async signOut() {
|
|
625
|
-
try {
|
|
626
|
-
try {
|
|
627
|
-
await this.http.post("/api/auth/logout", void 0, { credentials: "include" });
|
|
628
|
-
} catch {
|
|
629
|
-
}
|
|
630
|
-
this.tokenManager.clearSession();
|
|
631
|
-
this.http.setAuthToken(null);
|
|
632
|
-
clearCsrfToken();
|
|
633
|
-
return { error: null };
|
|
634
|
-
} catch (error) {
|
|
635
|
-
return {
|
|
636
|
-
error: new InsForgeError(
|
|
637
|
-
"Failed to sign out",
|
|
638
|
-
500,
|
|
639
|
-
"SIGNOUT_ERROR"
|
|
640
|
-
)
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
/**
|
|
645
|
-
* Get all public authentication configuration (OAuth + Email)
|
|
646
|
-
* Returns both OAuth providers and email authentication settings in one request
|
|
647
|
-
* This is a public endpoint that doesn't require authentication
|
|
648
|
-
*
|
|
649
|
-
* @returns Complete public authentication configuration including OAuth providers and email auth settings
|
|
650
|
-
*
|
|
651
|
-
* @example
|
|
652
|
-
* ```ts
|
|
653
|
-
* const { data, error } = await insforge.auth.getPublicAuthConfig();
|
|
654
|
-
* if (data) {
|
|
655
|
-
* console.log(`OAuth providers: ${data.oauth.data.length}`);
|
|
656
|
-
* console.log(`Password min length: ${data.email.passwordMinLength}`);
|
|
657
|
-
* }
|
|
658
|
-
* ```
|
|
659
|
-
*/
|
|
660
|
-
async getPublicAuthConfig() {
|
|
661
|
-
try {
|
|
662
|
-
const response = await this.http.get("/api/auth/public-config");
|
|
663
|
-
return {
|
|
664
|
-
data: response,
|
|
665
|
-
error: null
|
|
666
|
-
};
|
|
667
|
-
} catch (error) {
|
|
668
|
-
if (error instanceof InsForgeError) {
|
|
669
|
-
return { data: null, error };
|
|
670
|
-
}
|
|
671
|
-
return {
|
|
672
|
-
data: null,
|
|
673
|
-
error: new InsForgeError(
|
|
674
|
-
"An unexpected error occurred while fetching public authentication configuration",
|
|
675
|
-
500,
|
|
676
|
-
"UNEXPECTED_ERROR"
|
|
677
|
-
)
|
|
678
|
-
};
|
|
679
|
-
}
|
|
680
|
-
}
|
|
681
|
-
/**
|
|
682
|
-
* Get any user's profile by ID
|
|
683
|
-
* Returns profile information from the users table
|
|
684
|
-
*/
|
|
685
|
-
async getProfile(userId) {
|
|
686
|
-
try {
|
|
687
|
-
const response = await this.http.get(`/api/auth/profiles/${userId}`);
|
|
688
|
-
return {
|
|
689
|
-
data: response,
|
|
690
|
-
error: null
|
|
691
|
-
};
|
|
692
|
-
} catch (error) {
|
|
693
|
-
if (error instanceof InsForgeError) {
|
|
694
|
-
return { data: null, error };
|
|
695
|
-
}
|
|
696
|
-
return {
|
|
697
|
-
data: null,
|
|
698
|
-
error: new InsForgeError(
|
|
699
|
-
"An unexpected error occurred while fetching user profile",
|
|
700
|
-
500,
|
|
701
|
-
"UNEXPECTED_ERROR"
|
|
702
|
-
)
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
}
|
|
706
|
-
/**
|
|
707
|
-
* Get the current session (only session data, no API call)
|
|
708
|
-
* Returns the stored JWT token and basic user info from local storage
|
|
709
|
-
* Automatically waits for any pending OAuth callback to complete first
|
|
578
|
+
* Get current session, automatically waits for pending OAuth callback
|
|
710
579
|
*/
|
|
711
580
|
async getCurrentSession() {
|
|
712
581
|
await this.authCallbackHandled;
|
|
@@ -722,38 +591,24 @@ var Auth = class {
|
|
|
722
591
|
if (typeof window !== "undefined") {
|
|
723
592
|
try {
|
|
724
593
|
const csrfToken = getCsrfToken();
|
|
725
|
-
const response = await this.http.post(
|
|
726
|
-
"
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
headers: csrfToken ? { "X-CSRF-Token": csrfToken } : {},
|
|
730
|
-
credentials: "include"
|
|
731
|
-
}
|
|
732
|
-
);
|
|
594
|
+
const response = await this.http.post("/api/auth/refresh", void 0, {
|
|
595
|
+
headers: csrfToken ? { "X-CSRF-Token": csrfToken } : {},
|
|
596
|
+
credentials: "include"
|
|
597
|
+
});
|
|
733
598
|
if (response.accessToken) {
|
|
734
599
|
this.tokenManager.setMemoryMode();
|
|
735
600
|
this.tokenManager.setAccessToken(response.accessToken);
|
|
736
601
|
this.http.setAuthToken(response.accessToken);
|
|
737
|
-
if (response.user)
|
|
738
|
-
|
|
739
|
-
}
|
|
740
|
-
if (response.csrfToken) {
|
|
741
|
-
setCsrfToken(response.csrfToken);
|
|
742
|
-
}
|
|
743
|
-
return {
|
|
744
|
-
data: { session: this.tokenManager.getSession() },
|
|
745
|
-
error: null
|
|
746
|
-
};
|
|
602
|
+
if (response.user) this.tokenManager.setUser(response.user);
|
|
603
|
+
if (response.csrfToken) setCsrfToken(response.csrfToken);
|
|
604
|
+
return { data: { session: this.tokenManager.getSession() }, error: null };
|
|
747
605
|
}
|
|
748
606
|
} catch (error) {
|
|
749
607
|
if (error instanceof InsForgeError) {
|
|
750
608
|
if (error.statusCode === 404) {
|
|
751
609
|
this.tokenManager.setStorageMode();
|
|
752
610
|
const session2 = this.tokenManager.getSession();
|
|
753
|
-
|
|
754
|
-
return { data: { session: session2 }, error: null };
|
|
755
|
-
}
|
|
756
|
-
return { data: { session: null }, error: null };
|
|
611
|
+
return { data: { session: session2 }, error: null };
|
|
757
612
|
}
|
|
758
613
|
return { data: { session: null }, error };
|
|
759
614
|
}
|
|
@@ -774,11 +629,17 @@ var Auth = class {
|
|
|
774
629
|
};
|
|
775
630
|
}
|
|
776
631
|
}
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
632
|
+
// ============================================================================
|
|
633
|
+
// Profile Management
|
|
634
|
+
// ============================================================================
|
|
635
|
+
async getProfile(userId) {
|
|
636
|
+
try {
|
|
637
|
+
const response = await this.http.get(`/api/auth/profiles/${userId}`);
|
|
638
|
+
return { data: response, error: null };
|
|
639
|
+
} catch (error) {
|
|
640
|
+
return wrapError(error, "An unexpected error occurred while fetching user profile");
|
|
641
|
+
}
|
|
642
|
+
}
|
|
782
643
|
async setProfile(profile) {
|
|
783
644
|
try {
|
|
784
645
|
const response = await this.http.patch(
|
|
@@ -787,217 +648,89 @@ var Auth = class {
|
|
|
787
648
|
);
|
|
788
649
|
const currentUser = this.tokenManager.getUser();
|
|
789
650
|
if (currentUser && response.profile !== void 0) {
|
|
790
|
-
this.tokenManager.setUser({
|
|
791
|
-
...currentUser,
|
|
792
|
-
profile: response.profile
|
|
793
|
-
});
|
|
651
|
+
this.tokenManager.setUser({ ...currentUser, profile: response.profile });
|
|
794
652
|
}
|
|
795
|
-
return {
|
|
796
|
-
data: response,
|
|
797
|
-
error: null
|
|
798
|
-
};
|
|
653
|
+
return { data: response, error: null };
|
|
799
654
|
} catch (error) {
|
|
800
|
-
|
|
801
|
-
return { data: null, error };
|
|
802
|
-
}
|
|
803
|
-
return {
|
|
804
|
-
data: null,
|
|
805
|
-
error: new InsForgeError(
|
|
806
|
-
"An unexpected error occurred while updating user profile",
|
|
807
|
-
500,
|
|
808
|
-
"UNEXPECTED_ERROR"
|
|
809
|
-
)
|
|
810
|
-
};
|
|
655
|
+
return wrapError(error, "An unexpected error occurred while updating user profile");
|
|
811
656
|
}
|
|
812
657
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
* Resend email verification when the previous OTP has expired or was not received.
|
|
817
|
-
* Uses the method configured in auth settings (verifyEmailMethod).
|
|
818
|
-
* When method is 'code', sends a 6-digit numeric code. When method is 'link', sends a magic link.
|
|
819
|
-
* Prevents user enumeration by returning success even if email doesn't exist.
|
|
820
|
-
*/
|
|
658
|
+
// ============================================================================
|
|
659
|
+
// Email Verification
|
|
660
|
+
// ============================================================================
|
|
821
661
|
async resendVerificationEmail(request) {
|
|
822
662
|
try {
|
|
823
663
|
const response = await this.http.post(
|
|
824
664
|
"/api/auth/email/send-verification",
|
|
825
665
|
request
|
|
826
666
|
);
|
|
827
|
-
return {
|
|
828
|
-
data: response,
|
|
829
|
-
error: null
|
|
830
|
-
};
|
|
667
|
+
return { data: response, error: null };
|
|
831
668
|
} catch (error) {
|
|
832
|
-
|
|
833
|
-
return { data: null, error };
|
|
834
|
-
}
|
|
835
|
-
return {
|
|
836
|
-
data: null,
|
|
837
|
-
error: new InsForgeError(
|
|
838
|
-
"An unexpected error occurred while sending verification code",
|
|
839
|
-
500,
|
|
840
|
-
"UNEXPECTED_ERROR"
|
|
841
|
-
)
|
|
842
|
-
};
|
|
669
|
+
return wrapError(error, "An unexpected error occurred while sending verification code");
|
|
843
670
|
}
|
|
844
671
|
}
|
|
845
|
-
/**
|
|
846
|
-
* @deprecated Use `resendVerificationEmail` instead. This method will be removed in a future version.
|
|
847
|
-
*/
|
|
672
|
+
/** @deprecated Use `resendVerificationEmail` instead */
|
|
848
673
|
async sendVerificationEmail(request) {
|
|
849
674
|
return this.resendVerificationEmail(request);
|
|
850
675
|
}
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
676
|
+
async verifyEmail(request) {
|
|
677
|
+
try {
|
|
678
|
+
const response = await this.http.post(
|
|
679
|
+
"/api/auth/email/verify",
|
|
680
|
+
request,
|
|
681
|
+
{ credentials: "include" }
|
|
682
|
+
);
|
|
683
|
+
this.saveSessionFromResponse(response);
|
|
684
|
+
return { data: response, error: null };
|
|
685
|
+
} catch (error) {
|
|
686
|
+
return wrapError(error, "An unexpected error occurred while verifying email");
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
// ============================================================================
|
|
690
|
+
// Password Reset
|
|
691
|
+
// ============================================================================
|
|
859
692
|
async sendResetPasswordEmail(request) {
|
|
860
693
|
try {
|
|
861
694
|
const response = await this.http.post(
|
|
862
695
|
"/api/auth/email/send-reset-password",
|
|
863
696
|
request
|
|
864
697
|
);
|
|
865
|
-
return {
|
|
866
|
-
data: response,
|
|
867
|
-
error: null
|
|
868
|
-
};
|
|
698
|
+
return { data: response, error: null };
|
|
869
699
|
} catch (error) {
|
|
870
|
-
|
|
871
|
-
return { data: null, error };
|
|
872
|
-
}
|
|
873
|
-
return {
|
|
874
|
-
data: null,
|
|
875
|
-
error: new InsForgeError(
|
|
876
|
-
"An unexpected error occurred while sending password reset code",
|
|
877
|
-
500,
|
|
878
|
-
"UNEXPECTED_ERROR"
|
|
879
|
-
)
|
|
880
|
-
};
|
|
700
|
+
return wrapError(error, "An unexpected error occurred while sending password reset code");
|
|
881
701
|
}
|
|
882
702
|
}
|
|
883
|
-
/**
|
|
884
|
-
* Exchange reset password code for reset token
|
|
885
|
-
*
|
|
886
|
-
* Step 1 of two-step password reset flow (only used when resetPasswordMethod is 'code'):
|
|
887
|
-
* 1. Verify the 6-digit code sent to user's email
|
|
888
|
-
* 2. Return a reset token that can be used to actually reset the password
|
|
889
|
-
*
|
|
890
|
-
* This endpoint is not used when resetPasswordMethod is 'link' (magic link flow is direct).
|
|
891
|
-
*/
|
|
892
703
|
async exchangeResetPasswordToken(request) {
|
|
893
704
|
try {
|
|
894
705
|
const response = await this.http.post(
|
|
895
706
|
"/api/auth/email/exchange-reset-password-token",
|
|
896
707
|
request
|
|
897
708
|
);
|
|
898
|
-
return {
|
|
899
|
-
data: response,
|
|
900
|
-
error: null
|
|
901
|
-
};
|
|
709
|
+
return { data: response, error: null };
|
|
902
710
|
} catch (error) {
|
|
903
|
-
|
|
904
|
-
return { data: null, error };
|
|
905
|
-
}
|
|
906
|
-
return {
|
|
907
|
-
data: null,
|
|
908
|
-
error: new InsForgeError(
|
|
909
|
-
"An unexpected error occurred while verifying reset code",
|
|
910
|
-
500,
|
|
911
|
-
"UNEXPECTED_ERROR"
|
|
912
|
-
)
|
|
913
|
-
};
|
|
711
|
+
return wrapError(error, "An unexpected error occurred while verifying reset code");
|
|
914
712
|
}
|
|
915
713
|
}
|
|
916
|
-
/**
|
|
917
|
-
* Reset password with token
|
|
918
|
-
*
|
|
919
|
-
* Reset user password with a token. The token can be:
|
|
920
|
-
* - Magic link token (64-character hex token from send-reset-password when method is 'link')
|
|
921
|
-
* - Reset token (from exchange-reset-password-token after code verification when method is 'code')
|
|
922
|
-
*
|
|
923
|
-
* Both token types use RESET_PASSWORD purpose and are verified the same way.
|
|
924
|
-
*
|
|
925
|
-
* Flow summary:
|
|
926
|
-
* - Code method: send-reset-password → exchange-reset-password-token → reset-password (with resetToken)
|
|
927
|
-
* - Link method: send-reset-password → reset-password (with link token directly)
|
|
928
|
-
*/
|
|
929
714
|
async resetPassword(request) {
|
|
930
715
|
try {
|
|
931
716
|
const response = await this.http.post(
|
|
932
717
|
"/api/auth/email/reset-password",
|
|
933
718
|
request
|
|
934
719
|
);
|
|
935
|
-
return {
|
|
936
|
-
data: response,
|
|
937
|
-
error: null
|
|
938
|
-
};
|
|
720
|
+
return { data: response, error: null };
|
|
939
721
|
} catch (error) {
|
|
940
|
-
|
|
941
|
-
return { data: null, error };
|
|
942
|
-
}
|
|
943
|
-
return {
|
|
944
|
-
data: null,
|
|
945
|
-
error: new InsForgeError(
|
|
946
|
-
"An unexpected error occurred while resetting password",
|
|
947
|
-
500,
|
|
948
|
-
"UNEXPECTED_ERROR"
|
|
949
|
-
)
|
|
950
|
-
};
|
|
722
|
+
return wrapError(error, "An unexpected error occurred while resetting password");
|
|
951
723
|
}
|
|
952
724
|
}
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
* - Code verification: Provide both `email` and `otp` (6-digit numeric code)
|
|
958
|
-
* - Link verification: Provide only `otp` (64-character hex token from magic link)
|
|
959
|
-
*
|
|
960
|
-
* Successfully verified users will receive a session token.
|
|
961
|
-
*
|
|
962
|
-
* The email verification link sent to users always points to the backend API endpoint.
|
|
963
|
-
* If `verifyEmailRedirectTo` is configured, the backend will redirect to that URL after successful verification.
|
|
964
|
-
* Otherwise, a default success page is displayed.
|
|
965
|
-
*/
|
|
966
|
-
async verifyEmail(request) {
|
|
725
|
+
// ============================================================================
|
|
726
|
+
// Configuration
|
|
727
|
+
// ============================================================================
|
|
728
|
+
async getPublicAuthConfig() {
|
|
967
729
|
try {
|
|
968
|
-
const response = await this.http.
|
|
969
|
-
|
|
970
|
-
request,
|
|
971
|
-
{ credentials: "include" }
|
|
972
|
-
);
|
|
973
|
-
if (!isHostedAuthEnvironment()) {
|
|
974
|
-
const session = {
|
|
975
|
-
accessToken: response.accessToken,
|
|
976
|
-
user: response.user
|
|
977
|
-
};
|
|
978
|
-
if (response.csrfToken) {
|
|
979
|
-
this.tokenManager.setMemoryMode();
|
|
980
|
-
setCsrfToken(response.csrfToken);
|
|
981
|
-
}
|
|
982
|
-
this.tokenManager.saveSession(session);
|
|
983
|
-
this.http.setAuthToken(response.accessToken);
|
|
984
|
-
}
|
|
985
|
-
return {
|
|
986
|
-
data: response,
|
|
987
|
-
error: null
|
|
988
|
-
};
|
|
730
|
+
const response = await this.http.get("/api/auth/public-config");
|
|
731
|
+
return { data: response, error: null };
|
|
989
732
|
} catch (error) {
|
|
990
|
-
|
|
991
|
-
return { data: null, error };
|
|
992
|
-
}
|
|
993
|
-
return {
|
|
994
|
-
data: null,
|
|
995
|
-
error: new InsForgeError(
|
|
996
|
-
"An unexpected error occurred while verifying email",
|
|
997
|
-
500,
|
|
998
|
-
"UNEXPECTED_ERROR"
|
|
999
|
-
)
|
|
1000
|
-
};
|
|
733
|
+
return wrapError(error, "An unexpected error occurred while fetching auth configuration");
|
|
1001
734
|
}
|
|
1002
735
|
}
|
|
1003
736
|
};
|