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