mailsentry-auth 0.2.6 → 0.2.7

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 CHANGED
@@ -1405,22 +1405,38 @@ declare const getForgotPasswordField: (options?: ButtonProps) => BaseFormField;
1405
1405
  /**
1406
1406
  * Middleware configuration constants for routing and protection
1407
1407
  */
1408
+ interface ProtectionRule {
1409
+ hostPattern: string | null;
1410
+ pathPattern: string;
1411
+ }
1408
1412
  declare class MiddlewareConfig {
1409
1413
  static readonly CONSTANTS: {
1410
1414
  readonly LOGIN_PATH: "/login";
1411
1415
  readonly DASHBOARD_SUBDOMAIN: "dashboard";
1412
- readonly PUBLIC_PATH: "/public";
1413
- readonly PUBLIC_API_PATH: "/api/public";
1414
1416
  };
1415
1417
  /**
1416
- * Get public routes whitelist from environment variable
1417
- * Expected format: comma-separated paths like "/public,/links/new,/about"
1418
+ * Get dynamic protection rules from environment variable
1419
+ * Format: "host:path" or "path"
1418
1420
  */
1419
- static getPublicRoutesWhitelist(): string[];
1420
- static readonly PROTECTED_ROUTES: {
1421
- INCLUDE: string[];
1422
- EXCLUDE: string[];
1423
- };
1421
+ static getProtectedRules(): ProtectionRule[];
1422
+ /**
1423
+ * Get public routes whitelist (Exclusions)
1424
+ * Format: "host:path" or "path"
1425
+ */
1426
+ static getWhitelistRules(): ProtectionRule[];
1427
+ /**
1428
+ * Get guest-only routes (redirects authenticated users away)
1429
+ * Format: "host:path" or "path"
1430
+ */
1431
+ static getGuestOnlyRules(): ProtectionRule[];
1432
+ /**
1433
+ * Generic parser for environment variables containing rule lists
1434
+ */
1435
+ private static parseRules;
1436
+ /**
1437
+ * Parse a single rule string into a ProtectionRule object
1438
+ */
1439
+ private static parseSingleRule;
1424
1440
  static readonly ALLOWED_METHODS: readonly ["GET", "HEAD"];
1425
1441
  static readonly QUERY_PARAMS: {
1426
1442
  readonly LOGIN_REQUIRED: "sign_in_required";
@@ -1442,12 +1458,9 @@ declare class MiddlewareConfig {
1442
1458
  }
1443
1459
  /**
1444
1460
  * Middleware matcher patterns
1445
- * Matches all routes except API routes, Next.js internals, and static assets
1461
+ * Already excludes /api routes and static files automatically
1446
1462
  */
1447
1463
  declare const middlewareMatcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
1448
- /**
1449
- * Middleware configuration
1450
- */
1451
1464
  declare const config: {
1452
1465
  matcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
1453
1466
  };
@@ -1768,4 +1781,4 @@ declare const useAuthFlowModal: () => {
1768
1781
  openModal: () => void;
1769
1782
  };
1770
1783
 
1771
- export { AUTH_ENDPOINTS, AlertDisplay, type AlertDisplayProps, type AnyStepProps, type ApiErrorResponse, type ApiKeyConfig, type AuthActionCallbacks, type AuthActionOptions, type AuthActionResult, type AuthActionResultFailure, type AuthActionResultSuccess, type AuthActionState, type AuthEvent, AuthEventType, AuthFlowContainer, type AuthFlowContainerProps, AuthFlowModal, type AuthFlowModalProps, type AuthFlowProps, AuthFlowStep, AuthFlowVariant, AuthInitializer, AuthOrchestrator, AuthOrchestratorFactory, AuthResultFactory, AuthService, type AuthState, AuthenticatedState, type AuthenticatedStateProps, AuthenticationStatusContext, type BaseComponentProps, BaseErrorHandler, BaseEventBus, BaseForm, type BaseFormField, type BaseFormProps, type BaseResponse, BaseService, type BaseStepProps, BroadcastChannelEventBus, Channel, CookieUtils, CrossTabBehaviorConfig, CrossTabBehaviorHandler, CrossTabDemo, DevelopmentLogger, EMAIL_SUBMISSION_NAVIGATION, type EmailCheckResult, type EmailExistResponse, type EmailProviderConfig, EmailProviderUtils, EmailStep, type EmailStepProps, EndpointBuilder, type EventBus, ExistingUserLoginStrategy, type ForgotPasswordStepProps, FormFields, type FormFieldsProps, FormHeader, type FormHeaderProps, GenericErrorHandler, HttpClient, type HttpClientConfig, type HttpError, HttpMethod, type HttpRequestOptions, type HttpResponse, type IAuthOrchestrator, type IAuthService, type IAuthStatusState, type ICleanupStrategy, type IErrorHandler, type ILogger, type ILoginFlowStrategy, type ITokenManager, LocalStorageUtils, LoggerFactory, type LoginData, LoginFlowStrategyFactory, type LoginRequest, type LoginResponse, LoginStrategyResolver, LoginVerificationStrategy, MiddlewareConfig, type MiddlewareContext, type MiddlewareHandler, NavigationAction, NetworkErrorHandler, NextAction, PASSWORD_SUBMISSION_NAVIGATION, PageType, PageTypePatterns, PasswordInputWithStrength, type PasswordInputWithStrengthProps, PasswordStep, type PasswordStepProps, type PasswordStrengthRule, ProductionLogger, ProfileStateRenderer, ProfileUIState, type PropsFactory, type PublicUserProfile, type PublicUserProfileResponse, RoleType, SignupFlowStrategy, type Step, type StepComponent, type StepComponentRetriever, type StepConfig, type StepPropsFactoryRegistry, type StepRegistry, type StepRegistryBaseProps, type StepRegistryConfigs, type StepRegistryHandlers, type StepRegistryParams, type StepRegistryState, type StepperActions, type StepperState$1 as StepperState, StrategyResolutionMode, type StrengthResult, type Subscription, TokenManager, UnauthenticatedState, UrlCleanupHandler, UrlUtils, type UseAuthActionHandler, type UseAuthEventBusProps, type UseFormSubmissionProps, type UseStepRegistryParams, type UseStepperReturn, type UserProfile, type UserProfileResponse, type UserSession, type UserState, UserStorageManager, type UserStoreState, VERIFICATION_SUBMISSION_NAVIGATION, ValidationErrorHandler, VerificationStep, type VerificationStepProps, type VerifyEmailRequest, type VerifyEmailResponse, config, createAuthSteps, createPropsFactoryRegistry, createStepRegistry, getAuthPageStepMessage, getEmailField, getForgotPasswordField, getPasswordField, getStepForEmailSubmission, getStepForPasswordSubmission, getStepForVerificationSubmission, getStepProgressMessage, getTermsCheckboxField, getVerificationField, isPublicUser, isPublicUserEmail, middlewareMatcher, useAuth, useAuthActionHandler, useAuthEventBus, useAuthFlowModal, useAuthInitializer, useIsAuthenticated, useLogout, usePublicUserSession, useRefreshUser, useSharedEventBus, useSignInRequiredParams, useStepRegistry, useStepRenderer, useStepper, useUser, useUserActions, useUserData, useUserError, useUserLoading, useUserProfile, useUserSelectors, useUserStore, userSelectors };
1784
+ export { AUTH_ENDPOINTS, AlertDisplay, type AlertDisplayProps, type AnyStepProps, type ApiErrorResponse, type ApiKeyConfig, type AuthActionCallbacks, type AuthActionOptions, type AuthActionResult, type AuthActionResultFailure, type AuthActionResultSuccess, type AuthActionState, type AuthEvent, AuthEventType, AuthFlowContainer, type AuthFlowContainerProps, AuthFlowModal, type AuthFlowModalProps, type AuthFlowProps, AuthFlowStep, AuthFlowVariant, AuthInitializer, AuthOrchestrator, AuthOrchestratorFactory, AuthResultFactory, AuthService, type AuthState, AuthenticatedState, type AuthenticatedStateProps, AuthenticationStatusContext, type BaseComponentProps, BaseErrorHandler, BaseEventBus, BaseForm, type BaseFormField, type BaseFormProps, type BaseResponse, BaseService, type BaseStepProps, BroadcastChannelEventBus, Channel, CookieUtils, CrossTabBehaviorConfig, CrossTabBehaviorHandler, CrossTabDemo, DevelopmentLogger, EMAIL_SUBMISSION_NAVIGATION, type EmailCheckResult, type EmailExistResponse, type EmailProviderConfig, EmailProviderUtils, EmailStep, type EmailStepProps, EndpointBuilder, type EventBus, ExistingUserLoginStrategy, type ForgotPasswordStepProps, FormFields, type FormFieldsProps, FormHeader, type FormHeaderProps, GenericErrorHandler, HttpClient, type HttpClientConfig, type HttpError, HttpMethod, type HttpRequestOptions, type HttpResponse, type IAuthOrchestrator, type IAuthService, type IAuthStatusState, type ICleanupStrategy, type IErrorHandler, type ILogger, type ILoginFlowStrategy, type ITokenManager, LocalStorageUtils, LoggerFactory, type LoginData, LoginFlowStrategyFactory, type LoginRequest, type LoginResponse, LoginStrategyResolver, LoginVerificationStrategy, MiddlewareConfig, type MiddlewareContext, type MiddlewareHandler, NavigationAction, NetworkErrorHandler, NextAction, PASSWORD_SUBMISSION_NAVIGATION, PageType, PageTypePatterns, PasswordInputWithStrength, type PasswordInputWithStrengthProps, PasswordStep, type PasswordStepProps, type PasswordStrengthRule, ProductionLogger, ProfileStateRenderer, ProfileUIState, type PropsFactory, type ProtectionRule, type PublicUserProfile, type PublicUserProfileResponse, RoleType, SignupFlowStrategy, type Step, type StepComponent, type StepComponentRetriever, type StepConfig, type StepPropsFactoryRegistry, type StepRegistry, type StepRegistryBaseProps, type StepRegistryConfigs, type StepRegistryHandlers, type StepRegistryParams, type StepRegistryState, type StepperActions, type StepperState$1 as StepperState, StrategyResolutionMode, type StrengthResult, type Subscription, TokenManager, UnauthenticatedState, UrlCleanupHandler, UrlUtils, type UseAuthActionHandler, type UseAuthEventBusProps, type UseFormSubmissionProps, type UseStepRegistryParams, type UseStepperReturn, type UserProfile, type UserProfileResponse, type UserSession, type UserState, UserStorageManager, type UserStoreState, VERIFICATION_SUBMISSION_NAVIGATION, ValidationErrorHandler, VerificationStep, type VerificationStepProps, type VerifyEmailRequest, type VerifyEmailResponse, config, createAuthSteps, createPropsFactoryRegistry, createStepRegistry, getAuthPageStepMessage, getEmailField, getForgotPasswordField, getPasswordField, getStepForEmailSubmission, getStepForPasswordSubmission, getStepForVerificationSubmission, getStepProgressMessage, getTermsCheckboxField, getVerificationField, isPublicUser, isPublicUserEmail, middlewareMatcher, useAuth, useAuthActionHandler, useAuthEventBus, useAuthFlowModal, useAuthInitializer, useIsAuthenticated, useLogout, usePublicUserSession, useRefreshUser, useSharedEventBus, useSignInRequiredParams, useStepRegistry, useStepRenderer, useStepper, useUser, useUserActions, useUserData, useUserError, useUserLoading, useUserProfile, useUserSelectors, useUserStore, userSelectors };
package/dist/index.d.ts CHANGED
@@ -1405,22 +1405,38 @@ declare const getForgotPasswordField: (options?: ButtonProps) => BaseFormField;
1405
1405
  /**
1406
1406
  * Middleware configuration constants for routing and protection
1407
1407
  */
1408
+ interface ProtectionRule {
1409
+ hostPattern: string | null;
1410
+ pathPattern: string;
1411
+ }
1408
1412
  declare class MiddlewareConfig {
1409
1413
  static readonly CONSTANTS: {
1410
1414
  readonly LOGIN_PATH: "/login";
1411
1415
  readonly DASHBOARD_SUBDOMAIN: "dashboard";
1412
- readonly PUBLIC_PATH: "/public";
1413
- readonly PUBLIC_API_PATH: "/api/public";
1414
1416
  };
1415
1417
  /**
1416
- * Get public routes whitelist from environment variable
1417
- * Expected format: comma-separated paths like "/public,/links/new,/about"
1418
+ * Get dynamic protection rules from environment variable
1419
+ * Format: "host:path" or "path"
1418
1420
  */
1419
- static getPublicRoutesWhitelist(): string[];
1420
- static readonly PROTECTED_ROUTES: {
1421
- INCLUDE: string[];
1422
- EXCLUDE: string[];
1423
- };
1421
+ static getProtectedRules(): ProtectionRule[];
1422
+ /**
1423
+ * Get public routes whitelist (Exclusions)
1424
+ * Format: "host:path" or "path"
1425
+ */
1426
+ static getWhitelistRules(): ProtectionRule[];
1427
+ /**
1428
+ * Get guest-only routes (redirects authenticated users away)
1429
+ * Format: "host:path" or "path"
1430
+ */
1431
+ static getGuestOnlyRules(): ProtectionRule[];
1432
+ /**
1433
+ * Generic parser for environment variables containing rule lists
1434
+ */
1435
+ private static parseRules;
1436
+ /**
1437
+ * Parse a single rule string into a ProtectionRule object
1438
+ */
1439
+ private static parseSingleRule;
1424
1440
  static readonly ALLOWED_METHODS: readonly ["GET", "HEAD"];
1425
1441
  static readonly QUERY_PARAMS: {
1426
1442
  readonly LOGIN_REQUIRED: "sign_in_required";
@@ -1442,12 +1458,9 @@ declare class MiddlewareConfig {
1442
1458
  }
1443
1459
  /**
1444
1460
  * Middleware matcher patterns
1445
- * Matches all routes except API routes, Next.js internals, and static assets
1461
+ * Already excludes /api routes and static files automatically
1446
1462
  */
1447
1463
  declare const middlewareMatcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
1448
- /**
1449
- * Middleware configuration
1450
- */
1451
1464
  declare const config: {
1452
1465
  matcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
1453
1466
  };
@@ -1768,4 +1781,4 @@ declare const useAuthFlowModal: () => {
1768
1781
  openModal: () => void;
1769
1782
  };
1770
1783
 
1771
- export { AUTH_ENDPOINTS, AlertDisplay, type AlertDisplayProps, type AnyStepProps, type ApiErrorResponse, type ApiKeyConfig, type AuthActionCallbacks, type AuthActionOptions, type AuthActionResult, type AuthActionResultFailure, type AuthActionResultSuccess, type AuthActionState, type AuthEvent, AuthEventType, AuthFlowContainer, type AuthFlowContainerProps, AuthFlowModal, type AuthFlowModalProps, type AuthFlowProps, AuthFlowStep, AuthFlowVariant, AuthInitializer, AuthOrchestrator, AuthOrchestratorFactory, AuthResultFactory, AuthService, type AuthState, AuthenticatedState, type AuthenticatedStateProps, AuthenticationStatusContext, type BaseComponentProps, BaseErrorHandler, BaseEventBus, BaseForm, type BaseFormField, type BaseFormProps, type BaseResponse, BaseService, type BaseStepProps, BroadcastChannelEventBus, Channel, CookieUtils, CrossTabBehaviorConfig, CrossTabBehaviorHandler, CrossTabDemo, DevelopmentLogger, EMAIL_SUBMISSION_NAVIGATION, type EmailCheckResult, type EmailExistResponse, type EmailProviderConfig, EmailProviderUtils, EmailStep, type EmailStepProps, EndpointBuilder, type EventBus, ExistingUserLoginStrategy, type ForgotPasswordStepProps, FormFields, type FormFieldsProps, FormHeader, type FormHeaderProps, GenericErrorHandler, HttpClient, type HttpClientConfig, type HttpError, HttpMethod, type HttpRequestOptions, type HttpResponse, type IAuthOrchestrator, type IAuthService, type IAuthStatusState, type ICleanupStrategy, type IErrorHandler, type ILogger, type ILoginFlowStrategy, type ITokenManager, LocalStorageUtils, LoggerFactory, type LoginData, LoginFlowStrategyFactory, type LoginRequest, type LoginResponse, LoginStrategyResolver, LoginVerificationStrategy, MiddlewareConfig, type MiddlewareContext, type MiddlewareHandler, NavigationAction, NetworkErrorHandler, NextAction, PASSWORD_SUBMISSION_NAVIGATION, PageType, PageTypePatterns, PasswordInputWithStrength, type PasswordInputWithStrengthProps, PasswordStep, type PasswordStepProps, type PasswordStrengthRule, ProductionLogger, ProfileStateRenderer, ProfileUIState, type PropsFactory, type PublicUserProfile, type PublicUserProfileResponse, RoleType, SignupFlowStrategy, type Step, type StepComponent, type StepComponentRetriever, type StepConfig, type StepPropsFactoryRegistry, type StepRegistry, type StepRegistryBaseProps, type StepRegistryConfigs, type StepRegistryHandlers, type StepRegistryParams, type StepRegistryState, type StepperActions, type StepperState$1 as StepperState, StrategyResolutionMode, type StrengthResult, type Subscription, TokenManager, UnauthenticatedState, UrlCleanupHandler, UrlUtils, type UseAuthActionHandler, type UseAuthEventBusProps, type UseFormSubmissionProps, type UseStepRegistryParams, type UseStepperReturn, type UserProfile, type UserProfileResponse, type UserSession, type UserState, UserStorageManager, type UserStoreState, VERIFICATION_SUBMISSION_NAVIGATION, ValidationErrorHandler, VerificationStep, type VerificationStepProps, type VerifyEmailRequest, type VerifyEmailResponse, config, createAuthSteps, createPropsFactoryRegistry, createStepRegistry, getAuthPageStepMessage, getEmailField, getForgotPasswordField, getPasswordField, getStepForEmailSubmission, getStepForPasswordSubmission, getStepForVerificationSubmission, getStepProgressMessage, getTermsCheckboxField, getVerificationField, isPublicUser, isPublicUserEmail, middlewareMatcher, useAuth, useAuthActionHandler, useAuthEventBus, useAuthFlowModal, useAuthInitializer, useIsAuthenticated, useLogout, usePublicUserSession, useRefreshUser, useSharedEventBus, useSignInRequiredParams, useStepRegistry, useStepRenderer, useStepper, useUser, useUserActions, useUserData, useUserError, useUserLoading, useUserProfile, useUserSelectors, useUserStore, userSelectors };
1784
+ export { AUTH_ENDPOINTS, AlertDisplay, type AlertDisplayProps, type AnyStepProps, type ApiErrorResponse, type ApiKeyConfig, type AuthActionCallbacks, type AuthActionOptions, type AuthActionResult, type AuthActionResultFailure, type AuthActionResultSuccess, type AuthActionState, type AuthEvent, AuthEventType, AuthFlowContainer, type AuthFlowContainerProps, AuthFlowModal, type AuthFlowModalProps, type AuthFlowProps, AuthFlowStep, AuthFlowVariant, AuthInitializer, AuthOrchestrator, AuthOrchestratorFactory, AuthResultFactory, AuthService, type AuthState, AuthenticatedState, type AuthenticatedStateProps, AuthenticationStatusContext, type BaseComponentProps, BaseErrorHandler, BaseEventBus, BaseForm, type BaseFormField, type BaseFormProps, type BaseResponse, BaseService, type BaseStepProps, BroadcastChannelEventBus, Channel, CookieUtils, CrossTabBehaviorConfig, CrossTabBehaviorHandler, CrossTabDemo, DevelopmentLogger, EMAIL_SUBMISSION_NAVIGATION, type EmailCheckResult, type EmailExistResponse, type EmailProviderConfig, EmailProviderUtils, EmailStep, type EmailStepProps, EndpointBuilder, type EventBus, ExistingUserLoginStrategy, type ForgotPasswordStepProps, FormFields, type FormFieldsProps, FormHeader, type FormHeaderProps, GenericErrorHandler, HttpClient, type HttpClientConfig, type HttpError, HttpMethod, type HttpRequestOptions, type HttpResponse, type IAuthOrchestrator, type IAuthService, type IAuthStatusState, type ICleanupStrategy, type IErrorHandler, type ILogger, type ILoginFlowStrategy, type ITokenManager, LocalStorageUtils, LoggerFactory, type LoginData, LoginFlowStrategyFactory, type LoginRequest, type LoginResponse, LoginStrategyResolver, LoginVerificationStrategy, MiddlewareConfig, type MiddlewareContext, type MiddlewareHandler, NavigationAction, NetworkErrorHandler, NextAction, PASSWORD_SUBMISSION_NAVIGATION, PageType, PageTypePatterns, PasswordInputWithStrength, type PasswordInputWithStrengthProps, PasswordStep, type PasswordStepProps, type PasswordStrengthRule, ProductionLogger, ProfileStateRenderer, ProfileUIState, type PropsFactory, type ProtectionRule, type PublicUserProfile, type PublicUserProfileResponse, RoleType, SignupFlowStrategy, type Step, type StepComponent, type StepComponentRetriever, type StepConfig, type StepPropsFactoryRegistry, type StepRegistry, type StepRegistryBaseProps, type StepRegistryConfigs, type StepRegistryHandlers, type StepRegistryParams, type StepRegistryState, type StepperActions, type StepperState$1 as StepperState, StrategyResolutionMode, type StrengthResult, type Subscription, TokenManager, UnauthenticatedState, UrlCleanupHandler, UrlUtils, type UseAuthActionHandler, type UseAuthEventBusProps, type UseFormSubmissionProps, type UseStepRegistryParams, type UseStepperReturn, type UserProfile, type UserProfileResponse, type UserSession, type UserState, UserStorageManager, type UserStoreState, VERIFICATION_SUBMISSION_NAVIGATION, ValidationErrorHandler, VerificationStep, type VerificationStepProps, type VerifyEmailRequest, type VerifyEmailResponse, config, createAuthSteps, createPropsFactoryRegistry, createStepRegistry, getAuthPageStepMessage, getEmailField, getForgotPasswordField, getPasswordField, getStepForEmailSubmission, getStepForPasswordSubmission, getStepForVerificationSubmission, getStepProgressMessage, getTermsCheckboxField, getVerificationField, isPublicUser, isPublicUserEmail, middlewareMatcher, useAuth, useAuthActionHandler, useAuthEventBus, useAuthFlowModal, useAuthInitializer, useIsAuthenticated, useLogout, usePublicUserSession, useRefreshUser, useSharedEventBus, useSignInRequiredParams, useStepRegistry, useStepRenderer, useStepper, useUser, useUserActions, useUserData, useUserError, useUserLoading, useUserProfile, useUserSelectors, useUserStore, userSelectors };
package/dist/index.js CHANGED
@@ -1105,18 +1105,54 @@ function init(converter, defaultAttributes) {
1105
1105
  var api = init(defaultConverter, { path: "/" });
1106
1106
 
1107
1107
  // src/config/middleware.ts
1108
- var _MiddlewareConfig = class _MiddlewareConfig {
1109
- // Route Protection Configuration
1110
- // PATTERNS_TO_PROTECT: Routes that require authentication (whitelist approach recommended for security)
1111
- // PATTERNS_TO_EXCLUDE: Routes to explicitly exclude from protection (e.g., login page, public assets)
1108
+ var MiddlewareConfig = class {
1112
1109
  /**
1113
- * Get public routes whitelist from environment variable
1114
- * Expected format: comma-separated paths like "/public,/links/new,/about"
1110
+ * Get dynamic protection rules from environment variable
1111
+ * Format: "host:path" or "path"
1115
1112
  */
1116
- static getPublicRoutesWhitelist() {
1117
- const envWhitelist = process.env.NEXT_PUBLIC_AUTH_WHITELIST_ROUTES || "";
1118
- const customRoutes = envWhitelist.split(",").map((route) => route.trim()).filter((route) => route.length > 0);
1119
- return customRoutes;
1113
+ static getProtectedRules() {
1114
+ return this.parseRules(process.env.NEXT_PUBLIC_PROTECTED_ROUTES, [
1115
+ { hostPattern: this.CONSTANTS.DASHBOARD_SUBDOMAIN, pathPattern: "*" }
1116
+ ]);
1117
+ }
1118
+ /**
1119
+ * Get public routes whitelist (Exclusions)
1120
+ * Format: "host:path" or "path"
1121
+ */
1122
+ static getWhitelistRules() {
1123
+ return this.parseRules(process.env.NEXT_PUBLIC_AUTH_WHITELIST_ROUTES, [
1124
+ { hostPattern: null, pathPattern: this.CONSTANTS.LOGIN_PATH }
1125
+ ]);
1126
+ }
1127
+ /**
1128
+ * Get guest-only routes (redirects authenticated users away)
1129
+ * Format: "host:path" or "path"
1130
+ */
1131
+ static getGuestOnlyRules() {
1132
+ return this.parseRules(process.env.NEXT_PUBLIC_GUEST_ONLY_ROUTES, [
1133
+ { hostPattern: null, pathPattern: this.CONSTANTS.LOGIN_PATH }
1134
+ ]);
1135
+ }
1136
+ /**
1137
+ * Generic parser for environment variables containing rule lists
1138
+ */
1139
+ static parseRules(envVar, defaults) {
1140
+ if (envVar === void 0) return defaults;
1141
+ return envVar.split(",").map((rule) => this.parseSingleRule(rule)).filter((r) => r.pathPattern.length > 0);
1142
+ }
1143
+ /**
1144
+ * Parse a single rule string into a ProtectionRule object
1145
+ */
1146
+ static parseSingleRule(ruleString) {
1147
+ const trimmed = ruleString.trim();
1148
+ const separatorIndex = trimmed.indexOf(":");
1149
+ if (separatorIndex === -1) {
1150
+ return { hostPattern: null, pathPattern: trimmed };
1151
+ }
1152
+ return {
1153
+ hostPattern: trimmed.substring(0, separatorIndex).trim(),
1154
+ pathPattern: trimmed.substring(separatorIndex + 1).trim()
1155
+ };
1120
1156
  }
1121
1157
  /**
1122
1158
  * Get the base domain from environment or use default
@@ -1132,41 +1168,23 @@ var _MiddlewareConfig = class _MiddlewareConfig {
1132
1168
  }
1133
1169
  };
1134
1170
  // Common constants
1135
- _MiddlewareConfig.CONSTANTS = {
1171
+ MiddlewareConfig.CONSTANTS = {
1136
1172
  LOGIN_PATH: "/login",
1137
- DASHBOARD_SUBDOMAIN: "dashboard",
1138
- PUBLIC_PATH: "/public",
1139
- PUBLIC_API_PATH: "/api/public"
1140
- };
1141
- _MiddlewareConfig.PROTECTED_ROUTES = {
1142
- // Routes that MUST be protected
1143
- INCLUDE: [
1144
- "/"
1145
- // Protect everything by default (since dashboard.cutly.io/ is the root)
1146
- ],
1147
- // Routes that should NEVER be protected (public)
1148
- EXCLUDE: [
1149
- _MiddlewareConfig.CONSTANTS.LOGIN_PATH,
1150
- _MiddlewareConfig.CONSTANTS.PUBLIC_PATH,
1151
- _MiddlewareConfig.CONSTANTS.PUBLIC_API_PATH,
1152
- ..._MiddlewareConfig.getPublicRoutesWhitelist()
1153
- // Add custom whitelist from env
1154
- ]
1173
+ DASHBOARD_SUBDOMAIN: "dashboard"
1155
1174
  };
1156
1175
  // HTTP methods to process
1157
- _MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
1176
+ MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
1158
1177
  // Query parameters
1159
- _MiddlewareConfig.QUERY_PARAMS = {
1178
+ MiddlewareConfig.QUERY_PARAMS = {
1160
1179
  LOGIN_REQUIRED: "sign_in_required",
1161
1180
  AUTH_CHECKED: "auth_checked",
1162
1181
  REDIRECT_URL: "redirect_url"
1163
1182
  };
1164
1183
  // Query parameter values
1165
- _MiddlewareConfig.QUERY_VALUES = {
1184
+ MiddlewareConfig.QUERY_VALUES = {
1166
1185
  LOGIN_REQUIRED: "true",
1167
1186
  AUTH_CHECKED: "1"
1168
1187
  };
1169
- var MiddlewareConfig = _MiddlewareConfig;
1170
1188
  var middlewareMatcher = [
1171
1189
  "/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
1172
1190
  ];
@@ -3001,9 +3019,6 @@ var userSelectors = {
3001
3019
  // src/middlewares/handlers/base-middleware-handler.ts
3002
3020
  var _server = require('next/server');
3003
3021
 
3004
- // src/middlewares/handlers/middleware-chain.ts
3005
-
3006
-
3007
3022
  // src/middlewares/utils/email-validator.ts
3008
3023
  var isPublicUserEmail = (email) => {
3009
3024
  if (!email || typeof email !== "string") return false;
@@ -3020,6 +3035,12 @@ var isPublicUserEmail = (email) => {
3020
3035
  return true;
3021
3036
  };
3022
3037
 
3038
+ // src/middlewares/handlers/authentication-handler.ts
3039
+
3040
+
3041
+ // src/middlewares/handlers/middleware-chain.ts
3042
+
3043
+
3023
3044
  // src/hooks/use-user.ts
3024
3045
  var useUser = () => {
3025
3046
  const userState = userSelectors.useUserState();
package/dist/index.mjs CHANGED
@@ -1105,18 +1105,54 @@ function init(converter, defaultAttributes) {
1105
1105
  var api = init(defaultConverter, { path: "/" });
1106
1106
 
1107
1107
  // src/config/middleware.ts
1108
- var _MiddlewareConfig = class _MiddlewareConfig {
1109
- // Route Protection Configuration
1110
- // PATTERNS_TO_PROTECT: Routes that require authentication (whitelist approach recommended for security)
1111
- // PATTERNS_TO_EXCLUDE: Routes to explicitly exclude from protection (e.g., login page, public assets)
1108
+ var MiddlewareConfig = class {
1112
1109
  /**
1113
- * Get public routes whitelist from environment variable
1114
- * Expected format: comma-separated paths like "/public,/links/new,/about"
1110
+ * Get dynamic protection rules from environment variable
1111
+ * Format: "host:path" or "path"
1115
1112
  */
1116
- static getPublicRoutesWhitelist() {
1117
- const envWhitelist = process.env.NEXT_PUBLIC_AUTH_WHITELIST_ROUTES || "";
1118
- const customRoutes = envWhitelist.split(",").map((route) => route.trim()).filter((route) => route.length > 0);
1119
- return customRoutes;
1113
+ static getProtectedRules() {
1114
+ return this.parseRules(process.env.NEXT_PUBLIC_PROTECTED_ROUTES, [
1115
+ { hostPattern: this.CONSTANTS.DASHBOARD_SUBDOMAIN, pathPattern: "*" }
1116
+ ]);
1117
+ }
1118
+ /**
1119
+ * Get public routes whitelist (Exclusions)
1120
+ * Format: "host:path" or "path"
1121
+ */
1122
+ static getWhitelistRules() {
1123
+ return this.parseRules(process.env.NEXT_PUBLIC_AUTH_WHITELIST_ROUTES, [
1124
+ { hostPattern: null, pathPattern: this.CONSTANTS.LOGIN_PATH }
1125
+ ]);
1126
+ }
1127
+ /**
1128
+ * Get guest-only routes (redirects authenticated users away)
1129
+ * Format: "host:path" or "path"
1130
+ */
1131
+ static getGuestOnlyRules() {
1132
+ return this.parseRules(process.env.NEXT_PUBLIC_GUEST_ONLY_ROUTES, [
1133
+ { hostPattern: null, pathPattern: this.CONSTANTS.LOGIN_PATH }
1134
+ ]);
1135
+ }
1136
+ /**
1137
+ * Generic parser for environment variables containing rule lists
1138
+ */
1139
+ static parseRules(envVar, defaults) {
1140
+ if (envVar === void 0) return defaults;
1141
+ return envVar.split(",").map((rule) => this.parseSingleRule(rule)).filter((r) => r.pathPattern.length > 0);
1142
+ }
1143
+ /**
1144
+ * Parse a single rule string into a ProtectionRule object
1145
+ */
1146
+ static parseSingleRule(ruleString) {
1147
+ const trimmed = ruleString.trim();
1148
+ const separatorIndex = trimmed.indexOf(":");
1149
+ if (separatorIndex === -1) {
1150
+ return { hostPattern: null, pathPattern: trimmed };
1151
+ }
1152
+ return {
1153
+ hostPattern: trimmed.substring(0, separatorIndex).trim(),
1154
+ pathPattern: trimmed.substring(separatorIndex + 1).trim()
1155
+ };
1120
1156
  }
1121
1157
  /**
1122
1158
  * Get the base domain from environment or use default
@@ -1132,41 +1168,23 @@ var _MiddlewareConfig = class _MiddlewareConfig {
1132
1168
  }
1133
1169
  };
1134
1170
  // Common constants
1135
- _MiddlewareConfig.CONSTANTS = {
1171
+ MiddlewareConfig.CONSTANTS = {
1136
1172
  LOGIN_PATH: "/login",
1137
- DASHBOARD_SUBDOMAIN: "dashboard",
1138
- PUBLIC_PATH: "/public",
1139
- PUBLIC_API_PATH: "/api/public"
1140
- };
1141
- _MiddlewareConfig.PROTECTED_ROUTES = {
1142
- // Routes that MUST be protected
1143
- INCLUDE: [
1144
- "/"
1145
- // Protect everything by default (since dashboard.cutly.io/ is the root)
1146
- ],
1147
- // Routes that should NEVER be protected (public)
1148
- EXCLUDE: [
1149
- _MiddlewareConfig.CONSTANTS.LOGIN_PATH,
1150
- _MiddlewareConfig.CONSTANTS.PUBLIC_PATH,
1151
- _MiddlewareConfig.CONSTANTS.PUBLIC_API_PATH,
1152
- ..._MiddlewareConfig.getPublicRoutesWhitelist()
1153
- // Add custom whitelist from env
1154
- ]
1173
+ DASHBOARD_SUBDOMAIN: "dashboard"
1155
1174
  };
1156
1175
  // HTTP methods to process
1157
- _MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
1176
+ MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
1158
1177
  // Query parameters
1159
- _MiddlewareConfig.QUERY_PARAMS = {
1178
+ MiddlewareConfig.QUERY_PARAMS = {
1160
1179
  LOGIN_REQUIRED: "sign_in_required",
1161
1180
  AUTH_CHECKED: "auth_checked",
1162
1181
  REDIRECT_URL: "redirect_url"
1163
1182
  };
1164
1183
  // Query parameter values
1165
- _MiddlewareConfig.QUERY_VALUES = {
1184
+ MiddlewareConfig.QUERY_VALUES = {
1166
1185
  LOGIN_REQUIRED: "true",
1167
1186
  AUTH_CHECKED: "1"
1168
1187
  };
1169
- var MiddlewareConfig = _MiddlewareConfig;
1170
1188
  var middlewareMatcher = [
1171
1189
  "/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
1172
1190
  ];
@@ -3001,9 +3019,6 @@ var userSelectors = {
3001
3019
  // src/middlewares/handlers/base-middleware-handler.ts
3002
3020
  import { NextResponse } from "next/server";
3003
3021
 
3004
- // src/middlewares/handlers/middleware-chain.ts
3005
- import { NextResponse as NextResponse2 } from "next/server";
3006
-
3007
3022
  // src/middlewares/utils/email-validator.ts
3008
3023
  var isPublicUserEmail = (email) => {
3009
3024
  if (!email || typeof email !== "string") return false;
@@ -3020,6 +3035,12 @@ var isPublicUserEmail = (email) => {
3020
3035
  return true;
3021
3036
  };
3022
3037
 
3038
+ // src/middlewares/handlers/authentication-handler.ts
3039
+ import { NextResponse as NextResponse2 } from "next/server";
3040
+
3041
+ // src/middlewares/handlers/middleware-chain.ts
3042
+ import { NextResponse as NextResponse3 } from "next/server";
3043
+
3023
3044
  // src/hooks/use-user.ts
3024
3045
  var useUser = () => {
3025
3046
  const userState = userSelectors.useUserState();
@@ -2,12 +2,9 @@ import { NextRequest, NextResponse } from 'next/server';
2
2
 
3
3
  /**
4
4
  * Middleware matcher patterns
5
- * Matches all routes except API routes, Next.js internals, and static assets
5
+ * Already excludes /api routes and static files automatically
6
6
  */
7
7
  declare const middlewareMatcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
8
- /**
9
- * Middleware configuration
10
- */
11
8
  declare const config: {
12
9
  matcher: readonly ["/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"];
13
10
  };
@@ -16,7 +13,7 @@ declare const config: {
16
13
  * Authentication middleware for subdomain-based routing
17
14
  * Chain order:
18
15
  * 1. MethodFilterHandler - filters HTTP methods (GET/HEAD only)
19
- * 2. AuthenticationHandler - validates JWT and adds login params if needed
16
+ * 2. AuthenticationHandler - handles guest-only redirection and auth protection
20
17
  */
21
18
  declare function middleware(req: NextRequest): Promise<NextResponse>;
22
19
 
@@ -4,18 +4,54 @@ import Cookies from 'js-cookie';
4
4
  // src/middlewares/handlers/base-middleware-handler.ts
5
5
 
6
6
  // src/config/middleware.ts
7
- var _MiddlewareConfig = class _MiddlewareConfig {
8
- // Route Protection Configuration
9
- // PATTERNS_TO_PROTECT: Routes that require authentication (whitelist approach recommended for security)
10
- // PATTERNS_TO_EXCLUDE: Routes to explicitly exclude from protection (e.g., login page, public assets)
7
+ var MiddlewareConfig = class {
11
8
  /**
12
- * Get public routes whitelist from environment variable
13
- * Expected format: comma-separated paths like "/public,/links/new,/about"
9
+ * Get dynamic protection rules from environment variable
10
+ * Format: "host:path" or "path"
14
11
  */
15
- static getPublicRoutesWhitelist() {
16
- const envWhitelist = process.env.NEXT_PUBLIC_AUTH_WHITELIST_ROUTES || "";
17
- const customRoutes = envWhitelist.split(",").map((route) => route.trim()).filter((route) => route.length > 0);
18
- return customRoutes;
12
+ static getProtectedRules() {
13
+ return this.parseRules(process.env.NEXT_PUBLIC_PROTECTED_ROUTES, [
14
+ { hostPattern: this.CONSTANTS.DASHBOARD_SUBDOMAIN, pathPattern: "*" }
15
+ ]);
16
+ }
17
+ /**
18
+ * Get public routes whitelist (Exclusions)
19
+ * Format: "host:path" or "path"
20
+ */
21
+ static getWhitelistRules() {
22
+ return this.parseRules(process.env.NEXT_PUBLIC_AUTH_WHITELIST_ROUTES, [
23
+ { hostPattern: null, pathPattern: this.CONSTANTS.LOGIN_PATH }
24
+ ]);
25
+ }
26
+ /**
27
+ * Get guest-only routes (redirects authenticated users away)
28
+ * Format: "host:path" or "path"
29
+ */
30
+ static getGuestOnlyRules() {
31
+ return this.parseRules(process.env.NEXT_PUBLIC_GUEST_ONLY_ROUTES, [
32
+ { hostPattern: null, pathPattern: this.CONSTANTS.LOGIN_PATH }
33
+ ]);
34
+ }
35
+ /**
36
+ * Generic parser for environment variables containing rule lists
37
+ */
38
+ static parseRules(envVar, defaults) {
39
+ if (envVar === void 0) return defaults;
40
+ return envVar.split(",").map((rule) => this.parseSingleRule(rule)).filter((r) => r.pathPattern.length > 0);
41
+ }
42
+ /**
43
+ * Parse a single rule string into a ProtectionRule object
44
+ */
45
+ static parseSingleRule(ruleString) {
46
+ const trimmed = ruleString.trim();
47
+ const separatorIndex = trimmed.indexOf(":");
48
+ if (separatorIndex === -1) {
49
+ return { hostPattern: null, pathPattern: trimmed };
50
+ }
51
+ return {
52
+ hostPattern: trimmed.substring(0, separatorIndex).trim(),
53
+ pathPattern: trimmed.substring(separatorIndex + 1).trim()
54
+ };
19
55
  }
20
56
  /**
21
57
  * Get the base domain from environment or use default
@@ -31,41 +67,23 @@ var _MiddlewareConfig = class _MiddlewareConfig {
31
67
  }
32
68
  };
33
69
  // Common constants
34
- _MiddlewareConfig.CONSTANTS = {
70
+ MiddlewareConfig.CONSTANTS = {
35
71
  LOGIN_PATH: "/login",
36
- DASHBOARD_SUBDOMAIN: "dashboard",
37
- PUBLIC_PATH: "/public",
38
- PUBLIC_API_PATH: "/api/public"
39
- };
40
- _MiddlewareConfig.PROTECTED_ROUTES = {
41
- // Routes that MUST be protected
42
- INCLUDE: [
43
- "/"
44
- // Protect everything by default (since dashboard.cutly.io/ is the root)
45
- ],
46
- // Routes that should NEVER be protected (public)
47
- EXCLUDE: [
48
- _MiddlewareConfig.CONSTANTS.LOGIN_PATH,
49
- _MiddlewareConfig.CONSTANTS.PUBLIC_PATH,
50
- _MiddlewareConfig.CONSTANTS.PUBLIC_API_PATH,
51
- ..._MiddlewareConfig.getPublicRoutesWhitelist()
52
- // Add custom whitelist from env
53
- ]
72
+ DASHBOARD_SUBDOMAIN: "dashboard"
54
73
  };
55
74
  // HTTP methods to process
56
- _MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
75
+ MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
57
76
  // Query parameters
58
- _MiddlewareConfig.QUERY_PARAMS = {
77
+ MiddlewareConfig.QUERY_PARAMS = {
59
78
  LOGIN_REQUIRED: "sign_in_required",
60
79
  AUTH_CHECKED: "auth_checked",
61
80
  REDIRECT_URL: "redirect_url"
62
81
  };
63
82
  // Query parameter values
64
- _MiddlewareConfig.QUERY_VALUES = {
83
+ MiddlewareConfig.QUERY_VALUES = {
65
84
  LOGIN_REQUIRED: "true",
66
85
  AUTH_CHECKED: "1"
67
86
  };
68
- var MiddlewareConfig = _MiddlewareConfig;
69
87
  var middlewareMatcher = [
70
88
  "/((?!api|_next/static|_next/image|_next/webpack-hmr|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js)$).*)"
71
89
  ];
@@ -350,23 +368,83 @@ var _CookieUtils = class _CookieUtils {
350
368
  _CookieUtils.COOKIE_DOMAIN = _CookieUtils.getRootDomain();
351
369
  var CookieUtils = _CookieUtils;
352
370
 
371
+ // src/middlewares/utils/email-validator.ts
372
+ var isPublicUserEmail = (email) => {
373
+ if (!email || typeof email !== "string") return false;
374
+ const parts = email.split("@");
375
+ if (parts.length !== 2) return false;
376
+ const localPart = parts[0];
377
+ const ipv4Pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
378
+ const match = localPart.match(ipv4Pattern);
379
+ if (!match) return false;
380
+ for (let i = 1; i <= 4; i++) {
381
+ const octet = parseInt(match[i], 10);
382
+ if (octet < 0 || octet > 255) return false;
383
+ }
384
+ return true;
385
+ };
386
+
353
387
  // src/middlewares/handlers/base-middleware-handler.ts
354
388
  var BaseMiddlewareHandler = class {
355
389
  /**
356
390
  * Check if current route requires authentication
357
- * Uses inclusive (PROTECTED_ROUTES.INCLUDE) and exclusive (PROTECTED_ROUTES.EXCLUDE) lists
358
391
  */
359
- requiresAuthentication(pathname) {
360
- const isExcluded = MiddlewareConfig.PROTECTED_ROUTES.EXCLUDE.some(
361
- (route) => pathname.startsWith(route) || pathname === route
362
- );
363
- if (isExcluded) {
392
+ requiresAuthentication(pathname, hostname) {
393
+ if (this.isExcludedRoute(pathname, hostname)) {
364
394
  return false;
365
395
  }
366
- return MiddlewareConfig.PROTECTED_ROUTES.INCLUDE.some(
367
- (route) => pathname.startsWith(route) || pathname === route
396
+ return MiddlewareConfig.getProtectedRules().some(
397
+ (rule) => this.isRuleMatch(rule, pathname, hostname)
368
398
  );
369
399
  }
400
+ /**
401
+ * Check if current route is guest-only (authenticated users should be redirected away)
402
+ */
403
+ isGuestOnlyRoute(pathname, hostname) {
404
+ return MiddlewareConfig.getGuestOnlyRules().some(
405
+ (rule) => this.isRuleMatch(rule, pathname, hostname)
406
+ );
407
+ }
408
+ /**
409
+ * Check if the route is explicitly excluded from authentication
410
+ */
411
+ isExcludedRoute(pathname, hostname) {
412
+ return MiddlewareConfig.getWhitelistRules().some(
413
+ (rule) => this.isRuleMatch(rule, pathname, hostname)
414
+ );
415
+ }
416
+ /**
417
+ * Check if a single protection rule matches the current request
418
+ */
419
+ isRuleMatch(rule, pathname, hostname) {
420
+ if (rule.hostPattern && (!hostname || !hostname.startsWith(`${rule.hostPattern}.`) && hostname !== rule.hostPattern)) {
421
+ return false;
422
+ }
423
+ return rule.pathPattern === "*" || pathname === rule.pathPattern || pathname.startsWith(rule.pathPattern);
424
+ }
425
+ /**
426
+ * Validates authentication and returns user info if valid
427
+ * Used by both AuthenticationHandler and GuestOnlyHandler to avoid duplication
428
+ */
429
+ async getAuthenticatedUser(cookies) {
430
+ var _a, _b;
431
+ if (!this.hasAuthenticationCookies(cookies)) {
432
+ return null;
433
+ }
434
+ try {
435
+ const authResponse = await this.validateUserAuth(cookies);
436
+ if (!authResponse.ok) {
437
+ return null;
438
+ }
439
+ const data = await authResponse.json();
440
+ const userEmail = ((_b = (_a = data == null ? void 0 : data.data) == null ? void 0 : _a.user) == null ? void 0 : _b.email) || "";
441
+ const isPublic = isPublicUserEmail(userEmail);
442
+ return { email: userEmail, isPublic };
443
+ } catch (error) {
444
+ console.log("Auth validation error:", error instanceof Error ? error.message : "Unknown error");
445
+ return null;
446
+ }
447
+ }
370
448
  /**
371
449
  * Check if user has both access and refresh tokens
372
450
  */
@@ -478,26 +556,27 @@ var MethodFilterHandler = class extends BaseMiddlewareHandler {
478
556
  return this.continue();
479
557
  }
480
558
  };
481
-
482
- // src/middlewares/handlers/authentication-handler.ts
483
559
  var AuthenticationHandler = class extends BaseMiddlewareHandler {
484
560
  async handle(context) {
485
- var _a, _b;
486
- const { cookies, pathname } = context;
487
- if (!this.requiresAuthentication(pathname)) {
488
- return this.continue();
489
- }
490
- const hasAuthCookies = this.hasAuthenticationCookies(cookies);
491
- if (!hasAuthCookies) {
492
- return this.addLoginModalParams(context);
493
- }
561
+ const { cookies, pathname, hostname } = context;
494
562
  try {
495
- const authResponse = await this.validateUserAuth(cookies);
496
- if (authResponse.ok) {
497
- const data = await authResponse.json();
498
- const userEmail = ((_b = (_a = data == null ? void 0 : data.data) == null ? void 0 : _a.user) == null ? void 0 : _b.email) || "";
499
- const isPublicUserFlag = isPublicUserEmail(userEmail);
500
- if (isPublicUserFlag) {
563
+ const isGuestOnly = this.isGuestOnlyRoute(pathname, hostname);
564
+ const isProtected = this.requiresAuthentication(pathname, hostname);
565
+ if (!isGuestOnly && !isProtected) {
566
+ return this.continue();
567
+ }
568
+ const user = this.hasAuthenticationCookies(cookies) ? await this.getAuthenticatedUser(cookies) : null;
569
+ if (isGuestOnly) {
570
+ if (user && !user.isPublic) {
571
+ return NextResponse.redirect(new URL("/", context.request.url));
572
+ }
573
+ return this.continue();
574
+ }
575
+ if (isProtected) {
576
+ if (!user) {
577
+ return this.addLoginModalParams(context);
578
+ }
579
+ if (user.isPublic) {
501
580
  console.log("Public session user detected (IP-based email) - requiring authentication");
502
581
  return this.addLoginModalParams(context);
503
582
  }
@@ -506,10 +585,9 @@ var AuthenticationHandler = class extends BaseMiddlewareHandler {
506
585
  }
507
586
  return this.allow();
508
587
  }
509
- console.log("Authentication failed - requiring login for protected route");
510
- return this.addLoginModalParams(context);
588
+ return this.continue();
511
589
  } catch (error) {
512
- console.log("Authentication validation failed:", error instanceof Error ? error.message : "Unknown error");
590
+ console.error("AuthenticationHandler error:", error);
513
591
  return this.addLoginModalParams(context);
514
592
  }
515
593
  }
@@ -533,22 +611,6 @@ var MiddlewareChain = class {
533
611
  }
534
612
  };
535
613
 
536
- // src/middlewares/utils/email-validator.ts
537
- var isPublicUserEmail = (email) => {
538
- if (!email || typeof email !== "string") return false;
539
- const parts = email.split("@");
540
- if (parts.length !== 2) return false;
541
- const localPart = parts[0];
542
- const ipv4Pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
543
- const match = localPart.match(ipv4Pattern);
544
- if (!match) return false;
545
- for (let i = 1; i <= 4; i++) {
546
- const octet = parseInt(match[i], 10);
547
- if (octet < 0 || octet > 255) return false;
548
- }
549
- return true;
550
- };
551
-
552
614
  // src/middleware.ts
553
615
  async function middleware(req) {
554
616
  const hostname = req.headers.get("host") || req.nextUrl.hostname;
@@ -2,18 +2,54 @@
2
2
  var _jscookie = require('js-cookie'); var _jscookie2 = _interopRequireDefault(_jscookie);
3
3
 
4
4
  // src/config/middleware.ts
5
- var _MiddlewareConfig = class _MiddlewareConfig {
6
- // Route Protection Configuration
7
- // PATTERNS_TO_PROTECT: Routes that require authentication (whitelist approach recommended for security)
8
- // PATTERNS_TO_EXCLUDE: Routes to explicitly exclude from protection (e.g., login page, public assets)
5
+ var MiddlewareConfig = class {
9
6
  /**
10
- * Get public routes whitelist from environment variable
11
- * Expected format: comma-separated paths like "/public,/links/new,/about"
7
+ * Get dynamic protection rules from environment variable
8
+ * Format: "host:path" or "path"
12
9
  */
13
- static getPublicRoutesWhitelist() {
14
- const envWhitelist = process.env.NEXT_PUBLIC_AUTH_WHITELIST_ROUTES || "";
15
- const customRoutes = envWhitelist.split(",").map((route) => route.trim()).filter((route) => route.length > 0);
16
- return customRoutes;
10
+ static getProtectedRules() {
11
+ return this.parseRules(process.env.NEXT_PUBLIC_PROTECTED_ROUTES, [
12
+ { hostPattern: this.CONSTANTS.DASHBOARD_SUBDOMAIN, pathPattern: "*" }
13
+ ]);
14
+ }
15
+ /**
16
+ * Get public routes whitelist (Exclusions)
17
+ * Format: "host:path" or "path"
18
+ */
19
+ static getWhitelistRules() {
20
+ return this.parseRules(process.env.NEXT_PUBLIC_AUTH_WHITELIST_ROUTES, [
21
+ { hostPattern: null, pathPattern: this.CONSTANTS.LOGIN_PATH }
22
+ ]);
23
+ }
24
+ /**
25
+ * Get guest-only routes (redirects authenticated users away)
26
+ * Format: "host:path" or "path"
27
+ */
28
+ static getGuestOnlyRules() {
29
+ return this.parseRules(process.env.NEXT_PUBLIC_GUEST_ONLY_ROUTES, [
30
+ { hostPattern: null, pathPattern: this.CONSTANTS.LOGIN_PATH }
31
+ ]);
32
+ }
33
+ /**
34
+ * Generic parser for environment variables containing rule lists
35
+ */
36
+ static parseRules(envVar, defaults) {
37
+ if (envVar === void 0) return defaults;
38
+ return envVar.split(",").map((rule) => this.parseSingleRule(rule)).filter((r) => r.pathPattern.length > 0);
39
+ }
40
+ /**
41
+ * Parse a single rule string into a ProtectionRule object
42
+ */
43
+ static parseSingleRule(ruleString) {
44
+ const trimmed = ruleString.trim();
45
+ const separatorIndex = trimmed.indexOf(":");
46
+ if (separatorIndex === -1) {
47
+ return { hostPattern: null, pathPattern: trimmed };
48
+ }
49
+ return {
50
+ hostPattern: trimmed.substring(0, separatorIndex).trim(),
51
+ pathPattern: trimmed.substring(separatorIndex + 1).trim()
52
+ };
17
53
  }
18
54
  /**
19
55
  * Get the base domain from environment or use default
@@ -29,41 +65,23 @@ var _MiddlewareConfig = class _MiddlewareConfig {
29
65
  }
30
66
  };
31
67
  // Common constants
32
- _MiddlewareConfig.CONSTANTS = {
68
+ MiddlewareConfig.CONSTANTS = {
33
69
  LOGIN_PATH: "/login",
34
- DASHBOARD_SUBDOMAIN: "dashboard",
35
- PUBLIC_PATH: "/public",
36
- PUBLIC_API_PATH: "/api/public"
37
- };
38
- _MiddlewareConfig.PROTECTED_ROUTES = {
39
- // Routes that MUST be protected
40
- INCLUDE: [
41
- "/"
42
- // Protect everything by default (since dashboard.cutly.io/ is the root)
43
- ],
44
- // Routes that should NEVER be protected (public)
45
- EXCLUDE: [
46
- _MiddlewareConfig.CONSTANTS.LOGIN_PATH,
47
- _MiddlewareConfig.CONSTANTS.PUBLIC_PATH,
48
- _MiddlewareConfig.CONSTANTS.PUBLIC_API_PATH,
49
- ..._MiddlewareConfig.getPublicRoutesWhitelist()
50
- // Add custom whitelist from env
51
- ]
70
+ DASHBOARD_SUBDOMAIN: "dashboard"
52
71
  };
53
72
  // HTTP methods to process
54
- _MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
73
+ MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
55
74
  // Query parameters
56
- _MiddlewareConfig.QUERY_PARAMS = {
75
+ MiddlewareConfig.QUERY_PARAMS = {
57
76
  LOGIN_REQUIRED: "sign_in_required",
58
77
  AUTH_CHECKED: "auth_checked",
59
78
  REDIRECT_URL: "redirect_url"
60
79
  };
61
80
  // Query parameter values
62
- _MiddlewareConfig.QUERY_VALUES = {
81
+ MiddlewareConfig.QUERY_VALUES = {
63
82
  LOGIN_REQUIRED: "true",
64
83
  AUTH_CHECKED: "1"
65
84
  };
66
- var MiddlewareConfig = _MiddlewareConfig;
67
85
 
68
86
  // src/services/utils/url-utils.ts
69
87
  var UrlUtils = class {
@@ -2,18 +2,54 @@
2
2
  import Cookies from "js-cookie";
3
3
 
4
4
  // src/config/middleware.ts
5
- var _MiddlewareConfig = class _MiddlewareConfig {
6
- // Route Protection Configuration
7
- // PATTERNS_TO_PROTECT: Routes that require authentication (whitelist approach recommended for security)
8
- // PATTERNS_TO_EXCLUDE: Routes to explicitly exclude from protection (e.g., login page, public assets)
5
+ var MiddlewareConfig = class {
9
6
  /**
10
- * Get public routes whitelist from environment variable
11
- * Expected format: comma-separated paths like "/public,/links/new,/about"
7
+ * Get dynamic protection rules from environment variable
8
+ * Format: "host:path" or "path"
12
9
  */
13
- static getPublicRoutesWhitelist() {
14
- const envWhitelist = process.env.NEXT_PUBLIC_AUTH_WHITELIST_ROUTES || "";
15
- const customRoutes = envWhitelist.split(",").map((route) => route.trim()).filter((route) => route.length > 0);
16
- return customRoutes;
10
+ static getProtectedRules() {
11
+ return this.parseRules(process.env.NEXT_PUBLIC_PROTECTED_ROUTES, [
12
+ { hostPattern: this.CONSTANTS.DASHBOARD_SUBDOMAIN, pathPattern: "*" }
13
+ ]);
14
+ }
15
+ /**
16
+ * Get public routes whitelist (Exclusions)
17
+ * Format: "host:path" or "path"
18
+ */
19
+ static getWhitelistRules() {
20
+ return this.parseRules(process.env.NEXT_PUBLIC_AUTH_WHITELIST_ROUTES, [
21
+ { hostPattern: null, pathPattern: this.CONSTANTS.LOGIN_PATH }
22
+ ]);
23
+ }
24
+ /**
25
+ * Get guest-only routes (redirects authenticated users away)
26
+ * Format: "host:path" or "path"
27
+ */
28
+ static getGuestOnlyRules() {
29
+ return this.parseRules(process.env.NEXT_PUBLIC_GUEST_ONLY_ROUTES, [
30
+ { hostPattern: null, pathPattern: this.CONSTANTS.LOGIN_PATH }
31
+ ]);
32
+ }
33
+ /**
34
+ * Generic parser for environment variables containing rule lists
35
+ */
36
+ static parseRules(envVar, defaults) {
37
+ if (envVar === void 0) return defaults;
38
+ return envVar.split(",").map((rule) => this.parseSingleRule(rule)).filter((r) => r.pathPattern.length > 0);
39
+ }
40
+ /**
41
+ * Parse a single rule string into a ProtectionRule object
42
+ */
43
+ static parseSingleRule(ruleString) {
44
+ const trimmed = ruleString.trim();
45
+ const separatorIndex = trimmed.indexOf(":");
46
+ if (separatorIndex === -1) {
47
+ return { hostPattern: null, pathPattern: trimmed };
48
+ }
49
+ return {
50
+ hostPattern: trimmed.substring(0, separatorIndex).trim(),
51
+ pathPattern: trimmed.substring(separatorIndex + 1).trim()
52
+ };
17
53
  }
18
54
  /**
19
55
  * Get the base domain from environment or use default
@@ -29,41 +65,23 @@ var _MiddlewareConfig = class _MiddlewareConfig {
29
65
  }
30
66
  };
31
67
  // Common constants
32
- _MiddlewareConfig.CONSTANTS = {
68
+ MiddlewareConfig.CONSTANTS = {
33
69
  LOGIN_PATH: "/login",
34
- DASHBOARD_SUBDOMAIN: "dashboard",
35
- PUBLIC_PATH: "/public",
36
- PUBLIC_API_PATH: "/api/public"
37
- };
38
- _MiddlewareConfig.PROTECTED_ROUTES = {
39
- // Routes that MUST be protected
40
- INCLUDE: [
41
- "/"
42
- // Protect everything by default (since dashboard.cutly.io/ is the root)
43
- ],
44
- // Routes that should NEVER be protected (public)
45
- EXCLUDE: [
46
- _MiddlewareConfig.CONSTANTS.LOGIN_PATH,
47
- _MiddlewareConfig.CONSTANTS.PUBLIC_PATH,
48
- _MiddlewareConfig.CONSTANTS.PUBLIC_API_PATH,
49
- ..._MiddlewareConfig.getPublicRoutesWhitelist()
50
- // Add custom whitelist from env
51
- ]
70
+ DASHBOARD_SUBDOMAIN: "dashboard"
52
71
  };
53
72
  // HTTP methods to process
54
- _MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
73
+ MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
55
74
  // Query parameters
56
- _MiddlewareConfig.QUERY_PARAMS = {
75
+ MiddlewareConfig.QUERY_PARAMS = {
57
76
  LOGIN_REQUIRED: "sign_in_required",
58
77
  AUTH_CHECKED: "auth_checked",
59
78
  REDIRECT_URL: "redirect_url"
60
79
  };
61
80
  // Query parameter values
62
- _MiddlewareConfig.QUERY_VALUES = {
81
+ MiddlewareConfig.QUERY_VALUES = {
63
82
  LOGIN_REQUIRED: "true",
64
83
  AUTH_CHECKED: "1"
65
84
  };
66
- var MiddlewareConfig = _MiddlewareConfig;
67
85
 
68
86
  // src/services/utils/url-utils.ts
69
87
  var UrlUtils = class {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mailsentry-auth",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "description": "Next.js 15 authentication package with multi-step auth flow, cross-tab sync, and Zustand state management",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",