mailsentry-auth 0.1.5 → 0.1.6
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 +36 -40
- package/dist/index.d.ts +36 -40
- package/dist/index.js +86 -108
- package/dist/index.mjs +86 -108
- package/dist/middleware.mjs +115 -73
- package/dist/utils/cookie-utils.d.mts +86 -0
- package/dist/utils/cookie-utils.d.ts +86 -0
- package/dist/utils/cookie-utils.js +97 -22
- package/dist/utils/cookie-utils.mjs +97 -22
- package/package.json +3 -3
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cookie utility for managing authentication tokens with automatic SSR and client-side support
|
|
3
|
+
* Automatically chooses the right method based on environment
|
|
4
|
+
*/
|
|
5
|
+
declare class CookieUtils {
|
|
6
|
+
/**
|
|
7
|
+
* Get the access token cookie key
|
|
8
|
+
*/
|
|
9
|
+
static getAccessTokenKey(): string;
|
|
10
|
+
/**
|
|
11
|
+
* Get the refresh token cookie key
|
|
12
|
+
*/
|
|
13
|
+
static getRefreshTokenKey(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Get root domain for subdomain support
|
|
16
|
+
* Must match the domain used by backend when setting cookies
|
|
17
|
+
*/
|
|
18
|
+
private static getRootDomain;
|
|
19
|
+
private static readonly COOKIE_DOMAIN;
|
|
20
|
+
/**
|
|
21
|
+
* Get common cookie options
|
|
22
|
+
*/
|
|
23
|
+
private static getCookieOptions;
|
|
24
|
+
/**
|
|
25
|
+
* Check if running on client side
|
|
26
|
+
*/
|
|
27
|
+
private static isClientSide;
|
|
28
|
+
/**
|
|
29
|
+
* Check if running on server side
|
|
30
|
+
*/
|
|
31
|
+
private static isServerSide;
|
|
32
|
+
/**
|
|
33
|
+
* Dynamically import server action for server-side operations
|
|
34
|
+
*/
|
|
35
|
+
private static getServerTokens;
|
|
36
|
+
/**
|
|
37
|
+
* Set access token in cookie (client-side only)
|
|
38
|
+
*/
|
|
39
|
+
static setAccessToken(token: string): void;
|
|
40
|
+
/**
|
|
41
|
+
* Set refresh token in cookie (client-side only)
|
|
42
|
+
*/
|
|
43
|
+
static setRefreshToken(token: string): void;
|
|
44
|
+
/**
|
|
45
|
+
* Get access token - automatically handles client/server side
|
|
46
|
+
*/
|
|
47
|
+
static getAccessToken(): Promise<string | null>;
|
|
48
|
+
/**
|
|
49
|
+
* Get refresh token - automatically handles client/server side
|
|
50
|
+
*/
|
|
51
|
+
static getRefreshToken(): Promise<string | null>;
|
|
52
|
+
/**
|
|
53
|
+
* Get both tokens - automatically handles client/server side
|
|
54
|
+
*/
|
|
55
|
+
static getTokens(): Promise<{
|
|
56
|
+
accessToken: string | null;
|
|
57
|
+
refreshToken: string | null;
|
|
58
|
+
}>;
|
|
59
|
+
/**
|
|
60
|
+
* Clear all authentication cookies (client-side only)
|
|
61
|
+
* Clears cookies from both current domain and root domain
|
|
62
|
+
*/
|
|
63
|
+
static clearAuthCookies(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Check if cookies are supported/enabled (client-side only)
|
|
66
|
+
*/
|
|
67
|
+
static areCookiesEnabled(): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Get all authentication cookies - automatically handles client/server side
|
|
70
|
+
*/
|
|
71
|
+
static getAllAuthCookies(): Promise<Record<string, string>>;
|
|
72
|
+
/**
|
|
73
|
+
* Set multiple tokens at once (client-side only)
|
|
74
|
+
*/
|
|
75
|
+
static setTokens(accessToken: string, refreshToken: string): void;
|
|
76
|
+
/**
|
|
77
|
+
* Check if user has valid tokens - automatically handles client/server side
|
|
78
|
+
*/
|
|
79
|
+
static hasValidTokens(): Promise<boolean>;
|
|
80
|
+
/**
|
|
81
|
+
* Get current domain information for debugging
|
|
82
|
+
*/
|
|
83
|
+
static getDomainInfo(): Record<string, string>;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export { CookieUtils };
|
|
@@ -1,17 +1,108 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }// src/services/utils/cookie-utils.ts
|
|
2
2
|
var _jscookie = require('js-cookie'); var _jscookie2 = _interopRequireDefault(_jscookie);
|
|
3
|
+
|
|
4
|
+
// src/config/middleware.ts
|
|
5
|
+
var _MiddlewareConfig = class _MiddlewareConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Get the base domain from environment or use default
|
|
8
|
+
*/
|
|
9
|
+
static getBaseDomain() {
|
|
10
|
+
return process.env.NEXT_PUBLIC_BASE_DOMAIN;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get the protocol based on environment
|
|
14
|
+
*/
|
|
15
|
+
static getProtocol() {
|
|
16
|
+
return process.env.NODE_ENV === "production" ? "https" : "http";
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
// Common constants
|
|
20
|
+
_MiddlewareConfig.CONSTANTS = {
|
|
21
|
+
LOGIN_PATH: "/login",
|
|
22
|
+
DASHBOARD_SUBDOMAIN: "dashboard",
|
|
23
|
+
PUBLIC_PATH: "/public",
|
|
24
|
+
PUBLIC_API_PATH: "/api/public"
|
|
25
|
+
};
|
|
26
|
+
// Route Protection Configuration
|
|
27
|
+
// PATTERNS_TO_PROTECT: Routes that require authentication (whitelist approach recommended for security)
|
|
28
|
+
// PATTERNS_TO_EXCLUDE: Routes to explicitly exclude from protection (e.g., login page, public assets)
|
|
29
|
+
_MiddlewareConfig.PROTECTED_ROUTES = {
|
|
30
|
+
// Routes that MUST be protected
|
|
31
|
+
INCLUDE: [
|
|
32
|
+
"/"
|
|
33
|
+
// Protect everything by default (since dashboard.cutly.io/ is the root)
|
|
34
|
+
],
|
|
35
|
+
// Routes that should NEVER be protected (public)
|
|
36
|
+
EXCLUDE: [
|
|
37
|
+
_MiddlewareConfig.CONSTANTS.LOGIN_PATH,
|
|
38
|
+
_MiddlewareConfig.CONSTANTS.PUBLIC_PATH,
|
|
39
|
+
_MiddlewareConfig.CONSTANTS.PUBLIC_API_PATH
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
// HTTP methods to process
|
|
43
|
+
_MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
|
|
44
|
+
// Query parameters
|
|
45
|
+
_MiddlewareConfig.QUERY_PARAMS = {
|
|
46
|
+
LOGIN_REQUIRED: "sign_in_required",
|
|
47
|
+
AUTH_CHECKED: "auth_checked",
|
|
48
|
+
REDIRECT_URL: "redirect_url"
|
|
49
|
+
};
|
|
50
|
+
// Query parameter values
|
|
51
|
+
_MiddlewareConfig.QUERY_VALUES = {
|
|
52
|
+
LOGIN_REQUIRED: "true",
|
|
53
|
+
AUTH_CHECKED: "1"
|
|
54
|
+
};
|
|
55
|
+
var MiddlewareConfig = _MiddlewareConfig;
|
|
56
|
+
|
|
57
|
+
// src/services/utils/url-utils.ts
|
|
58
|
+
var UrlUtils = class {
|
|
59
|
+
/**
|
|
60
|
+
* Extract subdomain from hostname
|
|
61
|
+
* Example: "dashboard.cutly.io" -> "dashboard"
|
|
62
|
+
*/
|
|
63
|
+
static getSubdomain(hostname) {
|
|
64
|
+
if (!hostname || /^\d{1,3}(\.\d{1,3}){3}/.test(hostname) || hostname.startsWith(MiddlewareConfig.getBaseDomain())) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const parts = hostname.split(".");
|
|
68
|
+
return parts.length >= 2 ? parts[0] : null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get root domain for cookie scope
|
|
72
|
+
* Example: "dashboard.cutly.io" -> ".cutly.io"
|
|
73
|
+
* Example: "cutly.io" -> ".cutly.io"
|
|
74
|
+
*/
|
|
75
|
+
static getRootDomain(hostname) {
|
|
76
|
+
if (!hostname || /^\d+\.\d+\.\d+\.\d+$/.test(hostname)) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const parts = hostname.split(".");
|
|
80
|
+
if (parts.length >= 2) {
|
|
81
|
+
return `.${parts.slice(-2).join(".")}`;
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Check if URL has auth-related query parameters
|
|
87
|
+
*/
|
|
88
|
+
static hasAuthParams(url) {
|
|
89
|
+
return url.includes(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// src/services/utils/cookie-utils.ts
|
|
3
94
|
var _CookieUtils = class _CookieUtils {
|
|
4
95
|
/**
|
|
5
|
-
* Get the access token cookie key
|
|
96
|
+
* Get the access token cookie key
|
|
6
97
|
*/
|
|
7
98
|
static getAccessTokenKey() {
|
|
8
|
-
return
|
|
99
|
+
return "auth_access_token";
|
|
9
100
|
}
|
|
10
101
|
/**
|
|
11
|
-
* Get the refresh token cookie key
|
|
102
|
+
* Get the refresh token cookie key
|
|
12
103
|
*/
|
|
13
104
|
static getRefreshTokenKey() {
|
|
14
|
-
return
|
|
105
|
+
return "auth_refresh_token";
|
|
15
106
|
}
|
|
16
107
|
/**
|
|
17
108
|
* Get root domain for subdomain support
|
|
@@ -19,26 +110,10 @@ var _CookieUtils = class _CookieUtils {
|
|
|
19
110
|
*/
|
|
20
111
|
static getRootDomain() {
|
|
21
112
|
if (typeof window === "undefined") {
|
|
22
|
-
const baseDomain = process.env.NEXT_PUBLIC_BASE_DOMAIN;
|
|
23
|
-
if (baseDomain && process.env.NODE_ENV === "production") {
|
|
24
|
-
return `.${baseDomain}`;
|
|
25
|
-
}
|
|
26
|
-
return void 0;
|
|
27
|
-
}
|
|
28
|
-
const hostname = window.location.hostname;
|
|
29
|
-
if (hostname === "localhost" || hostname === "127.0.0.1") {
|
|
30
|
-
return void 0;
|
|
31
|
-
}
|
|
32
|
-
if (/^\d+\.\d+\.\d+\.\d+$/.test(hostname)) {
|
|
33
113
|
return void 0;
|
|
34
114
|
}
|
|
35
|
-
|
|
36
|
-
if (parts.length >= 2) {
|
|
37
|
-
return `.${parts.slice(-2).join(".")}`;
|
|
38
|
-
}
|
|
39
|
-
return void 0;
|
|
115
|
+
return UrlUtils.getRootDomain(window.location.hostname) || void 0;
|
|
40
116
|
}
|
|
41
|
-
// Use current domain in development
|
|
42
117
|
/**
|
|
43
118
|
* Get common cookie options
|
|
44
119
|
*/
|
|
@@ -237,7 +312,7 @@ var _CookieUtils = class _CookieUtils {
|
|
|
237
312
|
}
|
|
238
313
|
};
|
|
239
314
|
// Domain configuration - computed once
|
|
240
|
-
_CookieUtils.COOKIE_DOMAIN =
|
|
315
|
+
_CookieUtils.COOKIE_DOMAIN = _CookieUtils.getRootDomain();
|
|
241
316
|
var CookieUtils = _CookieUtils;
|
|
242
317
|
|
|
243
318
|
|
|
@@ -1,17 +1,108 @@
|
|
|
1
1
|
// src/services/utils/cookie-utils.ts
|
|
2
2
|
import Cookies from "js-cookie";
|
|
3
|
+
|
|
4
|
+
// src/config/middleware.ts
|
|
5
|
+
var _MiddlewareConfig = class _MiddlewareConfig {
|
|
6
|
+
/**
|
|
7
|
+
* Get the base domain from environment or use default
|
|
8
|
+
*/
|
|
9
|
+
static getBaseDomain() {
|
|
10
|
+
return process.env.NEXT_PUBLIC_BASE_DOMAIN;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Get the protocol based on environment
|
|
14
|
+
*/
|
|
15
|
+
static getProtocol() {
|
|
16
|
+
return process.env.NODE_ENV === "production" ? "https" : "http";
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
// Common constants
|
|
20
|
+
_MiddlewareConfig.CONSTANTS = {
|
|
21
|
+
LOGIN_PATH: "/login",
|
|
22
|
+
DASHBOARD_SUBDOMAIN: "dashboard",
|
|
23
|
+
PUBLIC_PATH: "/public",
|
|
24
|
+
PUBLIC_API_PATH: "/api/public"
|
|
25
|
+
};
|
|
26
|
+
// Route Protection Configuration
|
|
27
|
+
// PATTERNS_TO_PROTECT: Routes that require authentication (whitelist approach recommended for security)
|
|
28
|
+
// PATTERNS_TO_EXCLUDE: Routes to explicitly exclude from protection (e.g., login page, public assets)
|
|
29
|
+
_MiddlewareConfig.PROTECTED_ROUTES = {
|
|
30
|
+
// Routes that MUST be protected
|
|
31
|
+
INCLUDE: [
|
|
32
|
+
"/"
|
|
33
|
+
// Protect everything by default (since dashboard.cutly.io/ is the root)
|
|
34
|
+
],
|
|
35
|
+
// Routes that should NEVER be protected (public)
|
|
36
|
+
EXCLUDE: [
|
|
37
|
+
_MiddlewareConfig.CONSTANTS.LOGIN_PATH,
|
|
38
|
+
_MiddlewareConfig.CONSTANTS.PUBLIC_PATH,
|
|
39
|
+
_MiddlewareConfig.CONSTANTS.PUBLIC_API_PATH
|
|
40
|
+
]
|
|
41
|
+
};
|
|
42
|
+
// HTTP methods to process
|
|
43
|
+
_MiddlewareConfig.ALLOWED_METHODS = ["GET", "HEAD"];
|
|
44
|
+
// Query parameters
|
|
45
|
+
_MiddlewareConfig.QUERY_PARAMS = {
|
|
46
|
+
LOGIN_REQUIRED: "sign_in_required",
|
|
47
|
+
AUTH_CHECKED: "auth_checked",
|
|
48
|
+
REDIRECT_URL: "redirect_url"
|
|
49
|
+
};
|
|
50
|
+
// Query parameter values
|
|
51
|
+
_MiddlewareConfig.QUERY_VALUES = {
|
|
52
|
+
LOGIN_REQUIRED: "true",
|
|
53
|
+
AUTH_CHECKED: "1"
|
|
54
|
+
};
|
|
55
|
+
var MiddlewareConfig = _MiddlewareConfig;
|
|
56
|
+
|
|
57
|
+
// src/services/utils/url-utils.ts
|
|
58
|
+
var UrlUtils = class {
|
|
59
|
+
/**
|
|
60
|
+
* Extract subdomain from hostname
|
|
61
|
+
* Example: "dashboard.cutly.io" -> "dashboard"
|
|
62
|
+
*/
|
|
63
|
+
static getSubdomain(hostname) {
|
|
64
|
+
if (!hostname || /^\d{1,3}(\.\d{1,3}){3}/.test(hostname) || hostname.startsWith(MiddlewareConfig.getBaseDomain())) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const parts = hostname.split(".");
|
|
68
|
+
return parts.length >= 2 ? parts[0] : null;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Get root domain for cookie scope
|
|
72
|
+
* Example: "dashboard.cutly.io" -> ".cutly.io"
|
|
73
|
+
* Example: "cutly.io" -> ".cutly.io"
|
|
74
|
+
*/
|
|
75
|
+
static getRootDomain(hostname) {
|
|
76
|
+
if (!hostname || /^\d+\.\d+\.\d+\.\d+$/.test(hostname)) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const parts = hostname.split(".");
|
|
80
|
+
if (parts.length >= 2) {
|
|
81
|
+
return `.${parts.slice(-2).join(".")}`;
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Check if URL has auth-related query parameters
|
|
87
|
+
*/
|
|
88
|
+
static hasAuthParams(url) {
|
|
89
|
+
return url.includes(MiddlewareConfig.QUERY_PARAMS.AUTH_CHECKED);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// src/services/utils/cookie-utils.ts
|
|
3
94
|
var _CookieUtils = class _CookieUtils {
|
|
4
95
|
/**
|
|
5
|
-
* Get the access token cookie key
|
|
96
|
+
* Get the access token cookie key
|
|
6
97
|
*/
|
|
7
98
|
static getAccessTokenKey() {
|
|
8
|
-
return
|
|
99
|
+
return "auth_access_token";
|
|
9
100
|
}
|
|
10
101
|
/**
|
|
11
|
-
* Get the refresh token cookie key
|
|
102
|
+
* Get the refresh token cookie key
|
|
12
103
|
*/
|
|
13
104
|
static getRefreshTokenKey() {
|
|
14
|
-
return
|
|
105
|
+
return "auth_refresh_token";
|
|
15
106
|
}
|
|
16
107
|
/**
|
|
17
108
|
* Get root domain for subdomain support
|
|
@@ -19,26 +110,10 @@ var _CookieUtils = class _CookieUtils {
|
|
|
19
110
|
*/
|
|
20
111
|
static getRootDomain() {
|
|
21
112
|
if (typeof window === "undefined") {
|
|
22
|
-
const baseDomain = process.env.NEXT_PUBLIC_BASE_DOMAIN;
|
|
23
|
-
if (baseDomain && process.env.NODE_ENV === "production") {
|
|
24
|
-
return `.${baseDomain}`;
|
|
25
|
-
}
|
|
26
|
-
return void 0;
|
|
27
|
-
}
|
|
28
|
-
const hostname = window.location.hostname;
|
|
29
|
-
if (hostname === "localhost" || hostname === "127.0.0.1") {
|
|
30
|
-
return void 0;
|
|
31
|
-
}
|
|
32
|
-
if (/^\d+\.\d+\.\d+\.\d+$/.test(hostname)) {
|
|
33
113
|
return void 0;
|
|
34
114
|
}
|
|
35
|
-
|
|
36
|
-
if (parts.length >= 2) {
|
|
37
|
-
return `.${parts.slice(-2).join(".")}`;
|
|
38
|
-
}
|
|
39
|
-
return void 0;
|
|
115
|
+
return UrlUtils.getRootDomain(window.location.hostname) || void 0;
|
|
40
116
|
}
|
|
41
|
-
// Use current domain in development
|
|
42
117
|
/**
|
|
43
118
|
* Get common cookie options
|
|
44
119
|
*/
|
|
@@ -237,7 +312,7 @@ var _CookieUtils = class _CookieUtils {
|
|
|
237
312
|
}
|
|
238
313
|
};
|
|
239
314
|
// Domain configuration - computed once
|
|
240
|
-
_CookieUtils.COOKIE_DOMAIN =
|
|
315
|
+
_CookieUtils.COOKIE_DOMAIN = _CookieUtils.getRootDomain();
|
|
241
316
|
var CookieUtils = _CookieUtils;
|
|
242
317
|
export {
|
|
243
318
|
CookieUtils
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mailsentry-auth",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
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",
|
|
@@ -22,11 +22,11 @@
|
|
|
22
22
|
},
|
|
23
23
|
"./utils": {
|
|
24
24
|
"import": {
|
|
25
|
-
"types": "./dist/
|
|
25
|
+
"types": "./dist/utils/cookie-utils.d.ts",
|
|
26
26
|
"default": "./dist/utils/cookie-utils.mjs"
|
|
27
27
|
},
|
|
28
28
|
"require": {
|
|
29
|
-
"types": "./dist/
|
|
29
|
+
"types": "./dist/utils/cookie-utils.d.ts",
|
|
30
30
|
"default": "./dist/utils/cookie-utils.js"
|
|
31
31
|
}
|
|
32
32
|
}
|