mailsentry-auth 0.1.1 → 0.1.4
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 +67 -44
- package/dist/index.d.ts +67 -44
- package/dist/index.js +121 -46
- package/dist/index.mjs +120 -45
- package/dist/middleware.d.mts +7 -12
- package/dist/middleware.mjs +120 -103
- package/dist/utils/cookie-utils.js +28 -9
- package/dist/utils/cookie-utils.mjs +28 -9
- package/package.json +20 -18
package/dist/index.js
CHANGED
|
@@ -83,8 +83,8 @@ var AuthEventType = /* @__PURE__ */ ((AuthEventType3) => {
|
|
|
83
83
|
return AuthEventType3;
|
|
84
84
|
})(AuthEventType || {});
|
|
85
85
|
var PageType = /* @__PURE__ */ ((PageType3) => {
|
|
86
|
-
PageType3["LOGIN"] = "
|
|
87
|
-
PageType3["DASHBOARD"] = "
|
|
86
|
+
PageType3["LOGIN"] = "login";
|
|
87
|
+
PageType3["DASHBOARD"] = "dashboard";
|
|
88
88
|
PageType3["HOME"] = "/";
|
|
89
89
|
return PageType3;
|
|
90
90
|
})(PageType || {});
|
|
@@ -92,30 +92,30 @@ var NavigationAction = /* @__PURE__ */ ((NavigationAction2) => {
|
|
|
92
92
|
NavigationAction2["NONE"] = "none";
|
|
93
93
|
NavigationAction2["REDIRECT"] = "redirect";
|
|
94
94
|
NavigationAction2["MODAL"] = "modal";
|
|
95
|
+
NavigationAction2["CURRENT"] = "current";
|
|
95
96
|
return NavigationAction2;
|
|
96
97
|
})(NavigationAction || {});
|
|
97
98
|
var PageTypePatterns = {
|
|
98
|
-
["
|
|
99
|
-
["
|
|
100
|
-
["/" /* HOME */]: "/" /* HOME */
|
|
99
|
+
["login" /* LOGIN */]: "login" /* LOGIN */,
|
|
100
|
+
["dashboard" /* DASHBOARD */]: "dashboard" /* DASHBOARD */
|
|
101
101
|
};
|
|
102
102
|
var CrossTabBehaviorConfig = {
|
|
103
|
-
["
|
|
104
|
-
["auth.logged_in" /* LoggedIn */]: { action: "redirect" /* REDIRECT */, target: "
|
|
103
|
+
["login" /* LOGIN */]: {
|
|
104
|
+
["auth.logged_in" /* LoggedIn */]: { action: "redirect" /* REDIRECT */, target: "dashboard" /* DASHBOARD */ },
|
|
105
105
|
["auth.logged_out" /* LoggedOut */]: { action: "none" /* NONE */ },
|
|
106
106
|
["auth.email_verified" /* EmailVerified */]: { action: "none" /* NONE */ },
|
|
107
107
|
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "none" /* NONE */ }
|
|
108
108
|
},
|
|
109
|
-
["
|
|
110
|
-
["auth.logged_in" /* LoggedIn */]: { action: "
|
|
111
|
-
["auth.logged_out" /* LoggedOut */]: { action: "
|
|
112
|
-
["auth.email_verified" /* EmailVerified */]: { action: "
|
|
113
|
-
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "
|
|
109
|
+
["dashboard" /* DASHBOARD */]: {
|
|
110
|
+
["auth.logged_in" /* LoggedIn */]: { action: "current" /* CURRENT */ },
|
|
111
|
+
["auth.logged_out" /* LoggedOut */]: { action: "current" /* CURRENT */ },
|
|
112
|
+
["auth.email_verified" /* EmailVerified */]: { action: "current" /* CURRENT */ },
|
|
113
|
+
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "current" /* CURRENT */ }
|
|
114
114
|
},
|
|
115
115
|
["/" /* HOME */]: {
|
|
116
|
-
["auth.logged_in" /* LoggedIn */]: { action: "
|
|
117
|
-
["auth.logged_out" /* LoggedOut */]: { action: "
|
|
118
|
-
["auth.email_verified" /* EmailVerified */]: { action: "
|
|
116
|
+
["auth.logged_in" /* LoggedIn */]: { action: "none" /* NONE */ },
|
|
117
|
+
["auth.logged_out" /* LoggedOut */]: { action: "none" /* NONE */ },
|
|
118
|
+
["auth.email_verified" /* EmailVerified */]: { action: "none" /* NONE */ },
|
|
119
119
|
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "none" /* NONE */ }
|
|
120
120
|
}
|
|
121
121
|
};
|
|
@@ -254,13 +254,32 @@ var getVerificationField = (codeLength = 5, options = {}) => ({
|
|
|
254
254
|
|
|
255
255
|
// src/config/middleware.ts
|
|
256
256
|
var MiddlewareConfig = class {
|
|
257
|
+
/**
|
|
258
|
+
* Get the base domain from environment or use default
|
|
259
|
+
*/
|
|
260
|
+
static getBaseDomain() {
|
|
261
|
+
return process.env.NEXT_PUBLIC_BASE_DOMAIN || "cutly.io";
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Get the protocol based on environment
|
|
265
|
+
*/
|
|
266
|
+
static getProtocol() {
|
|
267
|
+
return process.env.NODE_ENV === "production" ? "https" : "http";
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Get the dashboard subdomain URL
|
|
271
|
+
*/
|
|
272
|
+
static getDashboardUrl(path = "") {
|
|
273
|
+
return `${this.getProtocol()}://${this.SUBDOMAINS.DASHBOARD}.${this.getBaseDomain()}${path}`;
|
|
274
|
+
}
|
|
257
275
|
};
|
|
258
|
-
//
|
|
259
|
-
MiddlewareConfig.
|
|
260
|
-
DASHBOARD: "
|
|
276
|
+
// Subdomain configuration
|
|
277
|
+
MiddlewareConfig.SUBDOMAINS = {
|
|
278
|
+
DASHBOARD: "dashboard"
|
|
261
279
|
};
|
|
262
|
-
//
|
|
263
|
-
MiddlewareConfig.
|
|
280
|
+
// Routes
|
|
281
|
+
MiddlewareConfig.ROUTES = {
|
|
282
|
+
ROOT: "/",
|
|
264
283
|
LOGIN: "/login"
|
|
265
284
|
};
|
|
266
285
|
// HTTP methods to process
|
|
@@ -268,7 +287,8 @@ MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
|
|
|
268
287
|
// Query parameters
|
|
269
288
|
MiddlewareConfig.QUERY_PARAMS = {
|
|
270
289
|
LOGIN_REQUIRED: "sign_in_required",
|
|
271
|
-
AUTH_CHECKED: "auth_checked"
|
|
290
|
+
AUTH_CHECKED: "auth_checked",
|
|
291
|
+
REDIRECT_URL: "redirect_url"
|
|
272
292
|
};
|
|
273
293
|
// Query parameter values
|
|
274
294
|
MiddlewareConfig.QUERY_VALUES = {
|
|
@@ -276,8 +296,7 @@ MiddlewareConfig.QUERY_VALUES = {
|
|
|
276
296
|
AUTH_CHECKED: "1"
|
|
277
297
|
};
|
|
278
298
|
var middlewareMatcher = [
|
|
279
|
-
"/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
280
|
-
"/login"
|
|
299
|
+
"/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
281
300
|
];
|
|
282
301
|
var config = {
|
|
283
302
|
matcher: middlewareMatcher
|
|
@@ -401,12 +420,18 @@ var _CookieUtils = class _CookieUtils {
|
|
|
401
420
|
static getRefreshTokenKey() {
|
|
402
421
|
return process.env.AUTH_REFRESH_TOKEN_KEY || "auth_refresh_token";
|
|
403
422
|
}
|
|
404
|
-
// Use current domain in development
|
|
405
423
|
/**
|
|
406
424
|
* Get root domain for subdomain support
|
|
425
|
+
* Must match the domain used by backend when setting cookies
|
|
407
426
|
*/
|
|
408
427
|
static getRootDomain() {
|
|
409
|
-
if (typeof window === "undefined")
|
|
428
|
+
if (typeof window === "undefined") {
|
|
429
|
+
const baseDomain = process.env.NEXT_PUBLIC_BASE_DOMAIN;
|
|
430
|
+
if (baseDomain && process.env.NODE_ENV === "production") {
|
|
431
|
+
return `.${baseDomain}`;
|
|
432
|
+
}
|
|
433
|
+
return void 0;
|
|
434
|
+
}
|
|
410
435
|
const hostname = window.location.hostname;
|
|
411
436
|
if (hostname === "localhost" || hostname === "127.0.0.1") {
|
|
412
437
|
return void 0;
|
|
@@ -420,13 +445,15 @@ var _CookieUtils = class _CookieUtils {
|
|
|
420
445
|
}
|
|
421
446
|
return void 0;
|
|
422
447
|
}
|
|
448
|
+
// Use current domain in development
|
|
423
449
|
/**
|
|
424
450
|
* Get common cookie options
|
|
425
451
|
*/
|
|
426
452
|
static getCookieOptions() {
|
|
427
453
|
return {
|
|
428
454
|
path: "/",
|
|
429
|
-
sameSite: "
|
|
455
|
+
sameSite: "lax",
|
|
456
|
+
// Changed from 'strict' to 'lax' for cross-subdomain
|
|
430
457
|
secure: process.env.NODE_ENV === "production",
|
|
431
458
|
// Only secure in production
|
|
432
459
|
domain: this.COOKIE_DOMAIN
|
|
@@ -516,18 +543,26 @@ var _CookieUtils = class _CookieUtils {
|
|
|
516
543
|
}
|
|
517
544
|
/**
|
|
518
545
|
* Clear all authentication cookies (client-side only)
|
|
546
|
+
* Clears cookies from both current domain and root domain
|
|
519
547
|
*/
|
|
520
548
|
static clearAuthCookies() {
|
|
521
549
|
if (this.isServerSide()) {
|
|
522
550
|
console.warn("clearAuthCookies called on server side - use server actions instead");
|
|
523
551
|
return;
|
|
524
552
|
}
|
|
525
|
-
const
|
|
553
|
+
const accessKey = this.getAccessTokenKey();
|
|
554
|
+
const refreshKey = this.getRefreshTokenKey();
|
|
555
|
+
const rootDomainOptions = {
|
|
526
556
|
path: "/",
|
|
527
557
|
domain: this.COOKIE_DOMAIN
|
|
528
558
|
};
|
|
529
|
-
api.remove(
|
|
530
|
-
api.remove(
|
|
559
|
+
api.remove(accessKey, rootDomainOptions);
|
|
560
|
+
api.remove(refreshKey, rootDomainOptions);
|
|
561
|
+
const currentDomainOptions = {
|
|
562
|
+
path: "/"
|
|
563
|
+
};
|
|
564
|
+
api.remove(accessKey, currentDomainOptions);
|
|
565
|
+
api.remove(refreshKey, currentDomainOptions);
|
|
531
566
|
}
|
|
532
567
|
/**
|
|
533
568
|
* Check if cookies are supported/enabled (client-side only)
|
|
@@ -594,18 +629,21 @@ var _CookieUtils = class _CookieUtils {
|
|
|
594
629
|
return {
|
|
595
630
|
error: "Server-side rendering - no domain info available",
|
|
596
631
|
environment: process.env.NODE_ENV || "unknown",
|
|
632
|
+
cookieDomain: this.COOKIE_DOMAIN || "undefined",
|
|
633
|
+
baseDomain: process.env.NEXT_PUBLIC_BASE_DOMAIN || "undefined",
|
|
597
634
|
recommendation: "Use server actions for server-side cookie access"
|
|
598
635
|
};
|
|
599
636
|
}
|
|
600
637
|
return {
|
|
601
638
|
hostname: window.location.hostname,
|
|
602
|
-
|
|
639
|
+
cookieDomain: this.COOKIE_DOMAIN || "current domain",
|
|
603
640
|
environment: process.env.NODE_ENV || "unknown",
|
|
604
|
-
protocol: window.location.protocol
|
|
641
|
+
protocol: window.location.protocol,
|
|
642
|
+
sameSite: "lax"
|
|
605
643
|
};
|
|
606
644
|
}
|
|
607
645
|
};
|
|
608
|
-
// Domain configuration
|
|
646
|
+
// Domain configuration - computed once
|
|
609
647
|
_CookieUtils.COOKIE_DOMAIN = process.env.NODE_ENV === "production" ? _CookieUtils.getRootDomain() : void 0;
|
|
610
648
|
var CookieUtils = _CookieUtils;
|
|
611
649
|
|
|
@@ -744,18 +782,53 @@ var BroadcastChannelEventBus = class _BroadcastChannelEventBus {
|
|
|
744
782
|
}
|
|
745
783
|
};
|
|
746
784
|
|
|
785
|
+
// src/services/utils/url-utils.ts
|
|
786
|
+
var UrlUtils = class {
|
|
787
|
+
/**
|
|
788
|
+
* Extract subdomain from hostname or URL
|
|
789
|
+
* Example: "dashboard.cutly.io" -> "dashboard"
|
|
790
|
+
* Example: "dashboard.localhost" -> "dashboard"
|
|
791
|
+
*/
|
|
792
|
+
static getSubdomain(url) {
|
|
793
|
+
try {
|
|
794
|
+
const domain = new URL(`http://${url}`).hostname;
|
|
795
|
+
const parts = domain.split(".");
|
|
796
|
+
if (parts.length < 2 || domain === "localhost" || /^\d{1,3}(\.\d{1,3}){3}/.test(domain) || domain.startsWith(MiddlewareConfig.getBaseDomain())) {
|
|
797
|
+
return null;
|
|
798
|
+
}
|
|
799
|
+
return parts[0] || null;
|
|
800
|
+
} catch (e) {
|
|
801
|
+
return null;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Check if URL has auth-related query parameters
|
|
806
|
+
*/
|
|
807
|
+
static hasAuthParams(url) {
|
|
808
|
+
return url.includes(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED);
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
|
|
747
812
|
// src/services/utils/cross-tab-behavior-handler.ts
|
|
748
813
|
var CrossTabBehaviorHandler = class {
|
|
749
814
|
/**
|
|
750
|
-
* Get current page type
|
|
815
|
+
* Get current page type using object lookup pattern
|
|
751
816
|
*/
|
|
752
817
|
static getCurrentPageType() {
|
|
753
|
-
var _a
|
|
818
|
+
var _a;
|
|
754
819
|
if (typeof window === "undefined") return "/" /* HOME */;
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
820
|
+
try {
|
|
821
|
+
const pathname = window.location.pathname;
|
|
822
|
+
const subdomain = UrlUtils.getSubdomain(window.location.hostname);
|
|
823
|
+
const pageTypeMatchers = {
|
|
824
|
+
["login" /* LOGIN */]: pathname === MiddlewareConfig.ROUTES.LOGIN,
|
|
825
|
+
["dashboard" /* DASHBOARD */]: subdomain === MiddlewareConfig.SUBDOMAINS.DASHBOARD
|
|
826
|
+
};
|
|
827
|
+
const matchedPageType = (_a = Object.entries(pageTypeMatchers).find(([, matches]) => matches)) == null ? void 0 : _a[0];
|
|
828
|
+
return matchedPageType != null ? matchedPageType : "dashboard" /* DASHBOARD */;
|
|
829
|
+
} catch (e) {
|
|
830
|
+
return "dashboard" /* DASHBOARD */;
|
|
831
|
+
}
|
|
759
832
|
}
|
|
760
833
|
/**
|
|
761
834
|
* Get the action configuration for current route and event
|
|
@@ -766,18 +839,12 @@ var CrossTabBehaviorHandler = class {
|
|
|
766
839
|
}
|
|
767
840
|
/**
|
|
768
841
|
* Check if current route requires redirect for given event
|
|
842
|
+
* Returns PageType to redirect to, or null if no redirect needed
|
|
769
843
|
*/
|
|
770
844
|
static shouldRedirect(currentPageType, eventType) {
|
|
771
845
|
const action = this.getAction(currentPageType, eventType);
|
|
772
846
|
return action.action === "redirect" /* REDIRECT */ ? action.target : null;
|
|
773
847
|
}
|
|
774
|
-
/**
|
|
775
|
-
* Check if current route should show modal for given event
|
|
776
|
-
*/
|
|
777
|
-
static shouldShowModal(currentPageType, eventType) {
|
|
778
|
-
const action = this.getAction(currentPageType, eventType);
|
|
779
|
-
return action.action === "modal" /* MODAL */;
|
|
780
|
-
}
|
|
781
848
|
};
|
|
782
849
|
|
|
783
850
|
// src/services/auth/manager/token-manager.ts
|
|
@@ -2315,6 +2382,13 @@ var useAuthEventBus = ({ onLoggedOut, onLoggedIn } = {}) => {
|
|
|
2315
2382
|
window.location.replace(target);
|
|
2316
2383
|
}
|
|
2317
2384
|
},
|
|
2385
|
+
["current" /* CURRENT */]: () => {
|
|
2386
|
+
const isAuthAction = e.type === "auth.logged_in" /* LoggedIn */ || e.type === "auth.logged_out" /* LoggedOut */;
|
|
2387
|
+
const hasParams = UrlUtils.hasAuthParams(window.location.href);
|
|
2388
|
+
if (isAuthAction || !hasParams) {
|
|
2389
|
+
window.location.reload();
|
|
2390
|
+
}
|
|
2391
|
+
},
|
|
2318
2392
|
["modal" /* MODAL */]: () => {
|
|
2319
2393
|
if (e.type === "auth.logged_in" /* LoggedIn */) {
|
|
2320
2394
|
window.location.replace(window.location.href);
|
|
@@ -2988,7 +3062,8 @@ var CrossTabDemo = () => {
|
|
|
2988
3062
|
|
|
2989
3063
|
|
|
2990
3064
|
|
|
2991
|
-
|
|
3065
|
+
|
|
3066
|
+
exports.AUTH_ENDPOINTS = AUTH_ENDPOINTS; exports.AlertDisplay = AlertDisplay; exports.AuthEventType = AuthEventType; exports.AuthFlowContainer = AuthFlowContainer; exports.AuthFlowModal = AuthFlowModal; exports.AuthFlowStep = AuthFlowStep; exports.AuthInitializer = AuthInitializer; exports.AuthOrchestrator = AuthOrchestrator; exports.AuthOrchestratorFactory = AuthOrchestratorFactory; exports.AuthResultFactory = AuthResultFactory; exports.AuthService = AuthService; exports.AuthenticatedState = AuthenticatedState; exports.AuthenticationStatusContext = AuthenticationStatusContext; exports.BaseErrorHandler = BaseErrorHandler; exports.BaseEventBus = BaseEventBus; exports.BaseForm = BaseForm; exports.BaseService = BaseService; exports.BroadcastChannelEventBus = BroadcastChannelEventBus; exports.Channel = Channel; exports.CookieUtils = CookieUtils; exports.CrossTabBehaviorConfig = CrossTabBehaviorConfig; exports.CrossTabBehaviorHandler = CrossTabBehaviorHandler; exports.CrossTabDemo = CrossTabDemo; exports.DevelopmentLogger = DevelopmentLogger; exports.EMAIL_SUBMISSION_NAVIGATION = EMAIL_SUBMISSION_NAVIGATION; exports.EmailStep = EmailStep; exports.EndpointBuilder = EndpointBuilder; exports.ExistingUserLoginStrategy = ExistingUserLoginStrategy; exports.FormFields = FormFields; exports.FormHeader = FormHeader; exports.GenericErrorHandler = GenericErrorHandler; exports.HttpClient = HttpClient; exports.HttpMethod = HttpMethod; exports.LocalStorageUtils = LocalStorageUtils; exports.LoggerFactory = LoggerFactory; exports.LoginFlowStrategyFactory = LoginFlowStrategyFactory; exports.MiddlewareConfig = MiddlewareConfig; exports.NavigationAction = NavigationAction; exports.NetworkErrorHandler = NetworkErrorHandler; exports.NextAction = NextAction; exports.PASSWORD_SUBMISSION_NAVIGATION = PASSWORD_SUBMISSION_NAVIGATION; exports.PageType = PageType; exports.PageTypePatterns = PageTypePatterns; exports.PasswordStep = PasswordStep; exports.ProductionLogger = ProductionLogger; exports.ProfileStateRenderer = ProfileStateRenderer; exports.ProfileUIState = ProfileUIState; exports.RoleType = RoleType; exports.SignupFlowStrategy = SignupFlowStrategy; exports.TokenManager = TokenManager; exports.UnauthenticatedState = UnauthenticatedState; exports.UrlUtils = UrlUtils; exports.UserStorageManager = UserStorageManager; exports.VERIFICATION_SUBMISSION_NAVIGATION = VERIFICATION_SUBMISSION_NAVIGATION; exports.ValidationErrorHandler = ValidationErrorHandler; exports.VerificationStep = VerificationStep; exports.config = config; exports.createAuthSteps = createAuthSteps; exports.createPropsFactoryRegistry = createPropsFactoryRegistry; exports.createStepRegistry = createStepRegistry; exports.getAuthPageStepMessage = getAuthPageStepMessage; exports.getEmailField = getEmailField; exports.getEmailStepComponent = getEmailStepComponent; exports.getPasswordField = getPasswordField; exports.getPasswordStepComponent = getPasswordStepComponent; exports.getStepForEmailSubmission = getStepForEmailSubmission; exports.getStepForPasswordSubmission = getStepForPasswordSubmission; exports.getStepForVerificationSubmission = getStepForVerificationSubmission; exports.getStepProgressMessage = getStepProgressMessage; exports.getVerificationField = getVerificationField; exports.getVerificationStepComponent = getVerificationStepComponent; exports.middlewareMatcher = middlewareMatcher; exports.useAuth = useAuth; exports.useAuthActionHandler = useAuthActionHandler; exports.useAuthEventBus = useAuthEventBus; exports.useAuthFlowModal = useAuthFlowModal; exports.useAuthInitializer = useAuthInitializer; exports.useIsAuthenticated = useIsAuthenticated; exports.useLogout = useLogout; exports.useRefreshUser = useRefreshUser; exports.useSharedEventBus = useSharedEventBus; exports.useSignInRequiredParams = useSignInRequiredParams; exports.useStepRegistry = useStepRegistry; exports.useStepRenderer = useStepRenderer; exports.useStepper = useStepper; exports.useUser = useUser; exports.useUserActions = useUserActions; exports.useUserData = useUserData; exports.useUserError = useUserError; exports.useUserLoading = useUserLoading; exports.useUserProfile = useUserProfile; exports.useUserStore = useUserStore; exports.userSelectors = userSelectors;
|
|
2992
3067
|
/*! Bundled license information:
|
|
2993
3068
|
|
|
2994
3069
|
js-cookie/dist/js.cookie.mjs:
|
package/dist/index.mjs
CHANGED
|
@@ -83,8 +83,8 @@ var AuthEventType = /* @__PURE__ */ ((AuthEventType3) => {
|
|
|
83
83
|
return AuthEventType3;
|
|
84
84
|
})(AuthEventType || {});
|
|
85
85
|
var PageType = /* @__PURE__ */ ((PageType3) => {
|
|
86
|
-
PageType3["LOGIN"] = "
|
|
87
|
-
PageType3["DASHBOARD"] = "
|
|
86
|
+
PageType3["LOGIN"] = "login";
|
|
87
|
+
PageType3["DASHBOARD"] = "dashboard";
|
|
88
88
|
PageType3["HOME"] = "/";
|
|
89
89
|
return PageType3;
|
|
90
90
|
})(PageType || {});
|
|
@@ -92,30 +92,30 @@ var NavigationAction = /* @__PURE__ */ ((NavigationAction2) => {
|
|
|
92
92
|
NavigationAction2["NONE"] = "none";
|
|
93
93
|
NavigationAction2["REDIRECT"] = "redirect";
|
|
94
94
|
NavigationAction2["MODAL"] = "modal";
|
|
95
|
+
NavigationAction2["CURRENT"] = "current";
|
|
95
96
|
return NavigationAction2;
|
|
96
97
|
})(NavigationAction || {});
|
|
97
98
|
var PageTypePatterns = {
|
|
98
|
-
["
|
|
99
|
-
["
|
|
100
|
-
["/" /* HOME */]: "/" /* HOME */
|
|
99
|
+
["login" /* LOGIN */]: "login" /* LOGIN */,
|
|
100
|
+
["dashboard" /* DASHBOARD */]: "dashboard" /* DASHBOARD */
|
|
101
101
|
};
|
|
102
102
|
var CrossTabBehaviorConfig = {
|
|
103
|
-
["
|
|
104
|
-
["auth.logged_in" /* LoggedIn */]: { action: "redirect" /* REDIRECT */, target: "
|
|
103
|
+
["login" /* LOGIN */]: {
|
|
104
|
+
["auth.logged_in" /* LoggedIn */]: { action: "redirect" /* REDIRECT */, target: "dashboard" /* DASHBOARD */ },
|
|
105
105
|
["auth.logged_out" /* LoggedOut */]: { action: "none" /* NONE */ },
|
|
106
106
|
["auth.email_verified" /* EmailVerified */]: { action: "none" /* NONE */ },
|
|
107
107
|
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "none" /* NONE */ }
|
|
108
108
|
},
|
|
109
|
-
["
|
|
110
|
-
["auth.logged_in" /* LoggedIn */]: { action: "
|
|
111
|
-
["auth.logged_out" /* LoggedOut */]: { action: "
|
|
112
|
-
["auth.email_verified" /* EmailVerified */]: { action: "
|
|
113
|
-
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "
|
|
109
|
+
["dashboard" /* DASHBOARD */]: {
|
|
110
|
+
["auth.logged_in" /* LoggedIn */]: { action: "current" /* CURRENT */ },
|
|
111
|
+
["auth.logged_out" /* LoggedOut */]: { action: "current" /* CURRENT */ },
|
|
112
|
+
["auth.email_verified" /* EmailVerified */]: { action: "current" /* CURRENT */ },
|
|
113
|
+
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "current" /* CURRENT */ }
|
|
114
114
|
},
|
|
115
115
|
["/" /* HOME */]: {
|
|
116
|
-
["auth.logged_in" /* LoggedIn */]: { action: "
|
|
117
|
-
["auth.logged_out" /* LoggedOut */]: { action: "
|
|
118
|
-
["auth.email_verified" /* EmailVerified */]: { action: "
|
|
116
|
+
["auth.logged_in" /* LoggedIn */]: { action: "none" /* NONE */ },
|
|
117
|
+
["auth.logged_out" /* LoggedOut */]: { action: "none" /* NONE */ },
|
|
118
|
+
["auth.email_verified" /* EmailVerified */]: { action: "none" /* NONE */ },
|
|
119
119
|
["auth.signin_required_modal" /* SignInRequiredModal */]: { action: "none" /* NONE */ }
|
|
120
120
|
}
|
|
121
121
|
};
|
|
@@ -254,13 +254,32 @@ var getVerificationField = (codeLength = 5, options = {}) => ({
|
|
|
254
254
|
|
|
255
255
|
// src/config/middleware.ts
|
|
256
256
|
var MiddlewareConfig = class {
|
|
257
|
+
/**
|
|
258
|
+
* Get the base domain from environment or use default
|
|
259
|
+
*/
|
|
260
|
+
static getBaseDomain() {
|
|
261
|
+
return process.env.NEXT_PUBLIC_BASE_DOMAIN || "cutly.io";
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Get the protocol based on environment
|
|
265
|
+
*/
|
|
266
|
+
static getProtocol() {
|
|
267
|
+
return process.env.NODE_ENV === "production" ? "https" : "http";
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Get the dashboard subdomain URL
|
|
271
|
+
*/
|
|
272
|
+
static getDashboardUrl(path = "") {
|
|
273
|
+
return `${this.getProtocol()}://${this.SUBDOMAINS.DASHBOARD}.${this.getBaseDomain()}${path}`;
|
|
274
|
+
}
|
|
257
275
|
};
|
|
258
|
-
//
|
|
259
|
-
MiddlewareConfig.
|
|
260
|
-
DASHBOARD: "
|
|
276
|
+
// Subdomain configuration
|
|
277
|
+
MiddlewareConfig.SUBDOMAINS = {
|
|
278
|
+
DASHBOARD: "dashboard"
|
|
261
279
|
};
|
|
262
|
-
//
|
|
263
|
-
MiddlewareConfig.
|
|
280
|
+
// Routes
|
|
281
|
+
MiddlewareConfig.ROUTES = {
|
|
282
|
+
ROOT: "/",
|
|
264
283
|
LOGIN: "/login"
|
|
265
284
|
};
|
|
266
285
|
// HTTP methods to process
|
|
@@ -268,7 +287,8 @@ MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
|
|
|
268
287
|
// Query parameters
|
|
269
288
|
MiddlewareConfig.QUERY_PARAMS = {
|
|
270
289
|
LOGIN_REQUIRED: "sign_in_required",
|
|
271
|
-
AUTH_CHECKED: "auth_checked"
|
|
290
|
+
AUTH_CHECKED: "auth_checked",
|
|
291
|
+
REDIRECT_URL: "redirect_url"
|
|
272
292
|
};
|
|
273
293
|
// Query parameter values
|
|
274
294
|
MiddlewareConfig.QUERY_VALUES = {
|
|
@@ -276,8 +296,7 @@ MiddlewareConfig.QUERY_VALUES = {
|
|
|
276
296
|
AUTH_CHECKED: "1"
|
|
277
297
|
};
|
|
278
298
|
var middlewareMatcher = [
|
|
279
|
-
"/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
280
|
-
"/login"
|
|
299
|
+
"/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
281
300
|
];
|
|
282
301
|
var config = {
|
|
283
302
|
matcher: middlewareMatcher
|
|
@@ -401,12 +420,18 @@ var _CookieUtils = class _CookieUtils {
|
|
|
401
420
|
static getRefreshTokenKey() {
|
|
402
421
|
return process.env.AUTH_REFRESH_TOKEN_KEY || "auth_refresh_token";
|
|
403
422
|
}
|
|
404
|
-
// Use current domain in development
|
|
405
423
|
/**
|
|
406
424
|
* Get root domain for subdomain support
|
|
425
|
+
* Must match the domain used by backend when setting cookies
|
|
407
426
|
*/
|
|
408
427
|
static getRootDomain() {
|
|
409
|
-
if (typeof window === "undefined")
|
|
428
|
+
if (typeof window === "undefined") {
|
|
429
|
+
const baseDomain = process.env.NEXT_PUBLIC_BASE_DOMAIN;
|
|
430
|
+
if (baseDomain && process.env.NODE_ENV === "production") {
|
|
431
|
+
return `.${baseDomain}`;
|
|
432
|
+
}
|
|
433
|
+
return void 0;
|
|
434
|
+
}
|
|
410
435
|
const hostname = window.location.hostname;
|
|
411
436
|
if (hostname === "localhost" || hostname === "127.0.0.1") {
|
|
412
437
|
return void 0;
|
|
@@ -420,13 +445,15 @@ var _CookieUtils = class _CookieUtils {
|
|
|
420
445
|
}
|
|
421
446
|
return void 0;
|
|
422
447
|
}
|
|
448
|
+
// Use current domain in development
|
|
423
449
|
/**
|
|
424
450
|
* Get common cookie options
|
|
425
451
|
*/
|
|
426
452
|
static getCookieOptions() {
|
|
427
453
|
return {
|
|
428
454
|
path: "/",
|
|
429
|
-
sameSite: "
|
|
455
|
+
sameSite: "lax",
|
|
456
|
+
// Changed from 'strict' to 'lax' for cross-subdomain
|
|
430
457
|
secure: process.env.NODE_ENV === "production",
|
|
431
458
|
// Only secure in production
|
|
432
459
|
domain: this.COOKIE_DOMAIN
|
|
@@ -516,18 +543,26 @@ var _CookieUtils = class _CookieUtils {
|
|
|
516
543
|
}
|
|
517
544
|
/**
|
|
518
545
|
* Clear all authentication cookies (client-side only)
|
|
546
|
+
* Clears cookies from both current domain and root domain
|
|
519
547
|
*/
|
|
520
548
|
static clearAuthCookies() {
|
|
521
549
|
if (this.isServerSide()) {
|
|
522
550
|
console.warn("clearAuthCookies called on server side - use server actions instead");
|
|
523
551
|
return;
|
|
524
552
|
}
|
|
525
|
-
const
|
|
553
|
+
const accessKey = this.getAccessTokenKey();
|
|
554
|
+
const refreshKey = this.getRefreshTokenKey();
|
|
555
|
+
const rootDomainOptions = {
|
|
526
556
|
path: "/",
|
|
527
557
|
domain: this.COOKIE_DOMAIN
|
|
528
558
|
};
|
|
529
|
-
api.remove(
|
|
530
|
-
api.remove(
|
|
559
|
+
api.remove(accessKey, rootDomainOptions);
|
|
560
|
+
api.remove(refreshKey, rootDomainOptions);
|
|
561
|
+
const currentDomainOptions = {
|
|
562
|
+
path: "/"
|
|
563
|
+
};
|
|
564
|
+
api.remove(accessKey, currentDomainOptions);
|
|
565
|
+
api.remove(refreshKey, currentDomainOptions);
|
|
531
566
|
}
|
|
532
567
|
/**
|
|
533
568
|
* Check if cookies are supported/enabled (client-side only)
|
|
@@ -594,18 +629,21 @@ var _CookieUtils = class _CookieUtils {
|
|
|
594
629
|
return {
|
|
595
630
|
error: "Server-side rendering - no domain info available",
|
|
596
631
|
environment: process.env.NODE_ENV || "unknown",
|
|
632
|
+
cookieDomain: this.COOKIE_DOMAIN || "undefined",
|
|
633
|
+
baseDomain: process.env.NEXT_PUBLIC_BASE_DOMAIN || "undefined",
|
|
597
634
|
recommendation: "Use server actions for server-side cookie access"
|
|
598
635
|
};
|
|
599
636
|
}
|
|
600
637
|
return {
|
|
601
638
|
hostname: window.location.hostname,
|
|
602
|
-
|
|
639
|
+
cookieDomain: this.COOKIE_DOMAIN || "current domain",
|
|
603
640
|
environment: process.env.NODE_ENV || "unknown",
|
|
604
|
-
protocol: window.location.protocol
|
|
641
|
+
protocol: window.location.protocol,
|
|
642
|
+
sameSite: "lax"
|
|
605
643
|
};
|
|
606
644
|
}
|
|
607
645
|
};
|
|
608
|
-
// Domain configuration
|
|
646
|
+
// Domain configuration - computed once
|
|
609
647
|
_CookieUtils.COOKIE_DOMAIN = process.env.NODE_ENV === "production" ? _CookieUtils.getRootDomain() : void 0;
|
|
610
648
|
var CookieUtils = _CookieUtils;
|
|
611
649
|
|
|
@@ -744,18 +782,53 @@ var BroadcastChannelEventBus = class _BroadcastChannelEventBus {
|
|
|
744
782
|
}
|
|
745
783
|
};
|
|
746
784
|
|
|
785
|
+
// src/services/utils/url-utils.ts
|
|
786
|
+
var UrlUtils = class {
|
|
787
|
+
/**
|
|
788
|
+
* Extract subdomain from hostname or URL
|
|
789
|
+
* Example: "dashboard.cutly.io" -> "dashboard"
|
|
790
|
+
* Example: "dashboard.localhost" -> "dashboard"
|
|
791
|
+
*/
|
|
792
|
+
static getSubdomain(url) {
|
|
793
|
+
try {
|
|
794
|
+
const domain = new URL(`http://${url}`).hostname;
|
|
795
|
+
const parts = domain.split(".");
|
|
796
|
+
if (parts.length < 2 || domain === "localhost" || /^\d{1,3}(\.\d{1,3}){3}/.test(domain) || domain.startsWith(MiddlewareConfig.getBaseDomain())) {
|
|
797
|
+
return null;
|
|
798
|
+
}
|
|
799
|
+
return parts[0] || null;
|
|
800
|
+
} catch (e) {
|
|
801
|
+
return null;
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Check if URL has auth-related query parameters
|
|
806
|
+
*/
|
|
807
|
+
static hasAuthParams(url) {
|
|
808
|
+
return url.includes(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED);
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
|
|
747
812
|
// src/services/utils/cross-tab-behavior-handler.ts
|
|
748
813
|
var CrossTabBehaviorHandler = class {
|
|
749
814
|
/**
|
|
750
|
-
* Get current page type
|
|
815
|
+
* Get current page type using object lookup pattern
|
|
751
816
|
*/
|
|
752
817
|
static getCurrentPageType() {
|
|
753
|
-
var _a
|
|
818
|
+
var _a;
|
|
754
819
|
if (typeof window === "undefined") return "/" /* HOME */;
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
820
|
+
try {
|
|
821
|
+
const pathname = window.location.pathname;
|
|
822
|
+
const subdomain = UrlUtils.getSubdomain(window.location.hostname);
|
|
823
|
+
const pageTypeMatchers = {
|
|
824
|
+
["login" /* LOGIN */]: pathname === MiddlewareConfig.ROUTES.LOGIN,
|
|
825
|
+
["dashboard" /* DASHBOARD */]: subdomain === MiddlewareConfig.SUBDOMAINS.DASHBOARD
|
|
826
|
+
};
|
|
827
|
+
const matchedPageType = (_a = Object.entries(pageTypeMatchers).find(([, matches]) => matches)) == null ? void 0 : _a[0];
|
|
828
|
+
return matchedPageType != null ? matchedPageType : "dashboard" /* DASHBOARD */;
|
|
829
|
+
} catch (e) {
|
|
830
|
+
return "dashboard" /* DASHBOARD */;
|
|
831
|
+
}
|
|
759
832
|
}
|
|
760
833
|
/**
|
|
761
834
|
* Get the action configuration for current route and event
|
|
@@ -766,18 +839,12 @@ var CrossTabBehaviorHandler = class {
|
|
|
766
839
|
}
|
|
767
840
|
/**
|
|
768
841
|
* Check if current route requires redirect for given event
|
|
842
|
+
* Returns PageType to redirect to, or null if no redirect needed
|
|
769
843
|
*/
|
|
770
844
|
static shouldRedirect(currentPageType, eventType) {
|
|
771
845
|
const action = this.getAction(currentPageType, eventType);
|
|
772
846
|
return action.action === "redirect" /* REDIRECT */ ? action.target : null;
|
|
773
847
|
}
|
|
774
|
-
/**
|
|
775
|
-
* Check if current route should show modal for given event
|
|
776
|
-
*/
|
|
777
|
-
static shouldShowModal(currentPageType, eventType) {
|
|
778
|
-
const action = this.getAction(currentPageType, eventType);
|
|
779
|
-
return action.action === "modal" /* MODAL */;
|
|
780
|
-
}
|
|
781
848
|
};
|
|
782
849
|
|
|
783
850
|
// src/services/auth/manager/token-manager.ts
|
|
@@ -2315,6 +2382,13 @@ var useAuthEventBus = ({ onLoggedOut, onLoggedIn } = {}) => {
|
|
|
2315
2382
|
window.location.replace(target);
|
|
2316
2383
|
}
|
|
2317
2384
|
},
|
|
2385
|
+
["current" /* CURRENT */]: () => {
|
|
2386
|
+
const isAuthAction = e.type === "auth.logged_in" /* LoggedIn */ || e.type === "auth.logged_out" /* LoggedOut */;
|
|
2387
|
+
const hasParams = UrlUtils.hasAuthParams(window.location.href);
|
|
2388
|
+
if (isAuthAction || !hasParams) {
|
|
2389
|
+
window.location.reload();
|
|
2390
|
+
}
|
|
2391
|
+
},
|
|
2318
2392
|
["modal" /* MODAL */]: () => {
|
|
2319
2393
|
if (e.type === "auth.logged_in" /* LoggedIn */) {
|
|
2320
2394
|
window.location.replace(window.location.href);
|
|
@@ -2947,6 +3021,7 @@ export {
|
|
|
2947
3021
|
SignupFlowStrategy,
|
|
2948
3022
|
TokenManager,
|
|
2949
3023
|
UnauthenticatedState,
|
|
3024
|
+
UrlUtils,
|
|
2950
3025
|
UserStorageManager,
|
|
2951
3026
|
VERIFICATION_SUBMISSION_NAVIGATION,
|
|
2952
3027
|
ValidationErrorHandler,
|
package/dist/middleware.d.mts
CHANGED
|
@@ -1,27 +1,22 @@
|
|
|
1
1
|
import { NextRequest, NextResponse } from 'next/server';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Middleware matcher patterns
|
|
5
|
-
*
|
|
6
|
-
* - / (home route and all other routes for authentication protection)
|
|
7
|
-
* - /login route (for authenticated user redirection)
|
|
8
|
-
* Excludes: API routes, Next.js internals, static assets, and file extensions
|
|
4
|
+
* Middleware matcher patterns
|
|
5
|
+
* Matches all routes except API routes, Next.js internals, and static assets
|
|
9
6
|
*/
|
|
10
|
-
declare const middlewareMatcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
7
|
+
declare const middlewareMatcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
|
|
11
8
|
/**
|
|
12
|
-
* Middleware configuration
|
|
9
|
+
* Middleware configuration
|
|
13
10
|
*/
|
|
14
11
|
declare const config: {
|
|
15
|
-
matcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
|
|
12
|
+
matcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
|
|
16
13
|
};
|
|
17
14
|
|
|
18
15
|
/**
|
|
19
|
-
* Authentication middleware
|
|
16
|
+
* Authentication middleware for subdomain-based routing
|
|
20
17
|
* Chain order:
|
|
21
18
|
* 1. MethodFilterHandler - filters HTTP methods (GET/HEAD only)
|
|
22
|
-
* 2.
|
|
23
|
-
* 3. LoginRedirectHandler - redirects authenticated users away from login
|
|
24
|
-
* 4. AuthenticationHandler - validates JWT and handles query parameter cleanup
|
|
19
|
+
* 2. AuthenticationHandler - validates JWT and adds login params if needed
|
|
25
20
|
*/
|
|
26
21
|
declare function middleware(req: NextRequest): Promise<NextResponse>;
|
|
27
22
|
|