@mindfulauth/core 2.0.0-beta.3 → 2.0.0-beta.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/config.d.ts +16 -55
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +37 -172
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +8 -11
- package/dist/security.d.ts +0 -6
- package/dist/security.d.ts.map +1 -1
- package/dist/security.js +1 -11
- package/dist/types.d.ts +0 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -1
- package/package.json +2 -2
package/dist/config.d.ts
CHANGED
|
@@ -6,39 +6,17 @@ export declare const AUTH_PROXY_TIMEOUT_MS = 15000;
|
|
|
6
6
|
export declare const SESSION_VALIDATION_TIMEOUT_MS = 10000;
|
|
7
7
|
/**
|
|
8
8
|
* Returns the combined list of assets to skip session validation for.
|
|
9
|
-
* Merges defaults with any custom assets configured via mauthSecurityConfig().
|
|
9
|
+
* Merges defaults with any custom assets configured via mauthSecurityConfig() in astro.config.mjs.
|
|
10
10
|
*/
|
|
11
11
|
export declare function GET_SKIP_ASSETS(): string[];
|
|
12
|
-
export declare const PUBLIC_ROUTES: string[];
|
|
13
|
-
export declare const PUBLIC_PREFIXES: string[];
|
|
14
12
|
/**
|
|
15
|
-
* Configure Mindful Auth security settings including
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* IMPORTANT: A nonce must be provided for inline styles to work. Without a nonce, inline styles will be blocked by CSP. If you need 'unsafe-inline' for development or testing, explicitly add it to styleSources in mauthSecurityConfig().
|
|
19
|
-
*
|
|
20
|
-
* IMPORTANT: Do not use Astro 6 security.csp in astro.config.mjs alongside this function. Astro's CSP will override these headers. Use mauthSecurityConfig() exclusively.
|
|
21
|
-
*
|
|
22
|
-
* Call in astro.config.mjs and pass the result to vite.define:
|
|
13
|
+
* Configure Mindful Auth security settings including custom skip assets.
|
|
14
|
+
* Call in astro.config.mjs and pass the result to getMauthViteDefines().
|
|
23
15
|
*
|
|
24
16
|
* @example
|
|
25
17
|
* // astro.config.mjs
|
|
26
18
|
* const mauthCfg = mauthSecurityConfig({
|
|
27
|
-
* skipAssets: ['/sitemap.xml', '/manifest.webmanifest']
|
|
28
|
-
* csp: {
|
|
29
|
-
* scriptSources: ['https://analytics.example.com'],
|
|
30
|
-
* connectSources: ['https://api.example.com'],
|
|
31
|
-
* frameSources: ['https://stripe.com'],
|
|
32
|
-
* fontSources: ['https://fonts.googleapis.com'],
|
|
33
|
-
* styleSources: ['https://cdn.example.com/styles'],
|
|
34
|
-
* imageSources: ['https://images.example.com'],
|
|
35
|
-
* frameAncestors: ["'self'"],
|
|
36
|
-
* workerSources: ["'self'"],
|
|
37
|
-
* manifestSources: ["'self'"],
|
|
38
|
-
* objectSources: ["'none'"],
|
|
39
|
-
* baseUris: ["'self'"],
|
|
40
|
-
* formActions: ["'self'"]
|
|
41
|
-
* }
|
|
19
|
+
* skipAssets: ['/sitemap.xml', '/manifest.webmanifest']
|
|
42
20
|
* });
|
|
43
21
|
*
|
|
44
22
|
* export default defineConfig({
|
|
@@ -47,20 +25,6 @@ export declare const PUBLIC_PREFIXES: string[];
|
|
|
47
25
|
*/
|
|
48
26
|
export declare function mauthSecurityConfig(options?: {
|
|
49
27
|
skipAssets?: string[];
|
|
50
|
-
csp?: {
|
|
51
|
-
scriptSources?: string[];
|
|
52
|
-
connectSources?: string[];
|
|
53
|
-
frameSources?: string[];
|
|
54
|
-
fontSources?: string[];
|
|
55
|
-
styleSources?: string[];
|
|
56
|
-
imageSources?: string[];
|
|
57
|
-
frameAncestors?: string[];
|
|
58
|
-
workerSources?: string[];
|
|
59
|
-
manifestSources?: string[];
|
|
60
|
-
objectSources?: string[];
|
|
61
|
-
baseUris?: string[];
|
|
62
|
-
formActions?: string[];
|
|
63
|
-
};
|
|
64
28
|
}): typeof options;
|
|
65
29
|
/**
|
|
66
30
|
* Converts the result of mauthSecurityConfig() into Vite define entries.
|
|
@@ -69,20 +33,17 @@ export declare function mauthSecurityConfig(options?: {
|
|
|
69
33
|
*/
|
|
70
34
|
export declare function getMauthViteDefines(options?: {
|
|
71
35
|
skipAssets?: string[];
|
|
72
|
-
csp?: {
|
|
73
|
-
scriptSources?: string[];
|
|
74
|
-
connectSources?: string[];
|
|
75
|
-
frameSources?: string[];
|
|
76
|
-
fontSources?: string[];
|
|
77
|
-
styleSources?: string[];
|
|
78
|
-
imageSources?: string[];
|
|
79
|
-
frameAncestors?: string[];
|
|
80
|
-
workerSources?: string[];
|
|
81
|
-
manifestSources?: string[];
|
|
82
|
-
objectSources?: string[];
|
|
83
|
-
baseUris?: string[];
|
|
84
|
-
formActions?: string[];
|
|
85
|
-
};
|
|
86
36
|
}): Record<string, string>;
|
|
87
|
-
export declare
|
|
37
|
+
export declare const PUBLIC_ROUTES: string[];
|
|
38
|
+
export declare const PUBLIC_PREFIXES: string[];
|
|
39
|
+
/**
|
|
40
|
+
* Returns security headers to be added to every SSR response.
|
|
41
|
+
* CSP (Content-Security-Policy) for script-src and style-src is handled by
|
|
42
|
+
* Astro 6's native security.csp in astro.config.mjs using hashes.
|
|
43
|
+
* The remaining headers here cover transport security, framing, and permissions.
|
|
44
|
+
*
|
|
45
|
+
* Note: X-Frame-Options: SAMEORIGIN covers clickjacking protection
|
|
46
|
+
* (equivalent to CSP frame-ancestors 'self', which cannot be set via meta tag).
|
|
47
|
+
*/
|
|
48
|
+
export declare function GET_SECURITY_HEADERS(): Record<string, string>;
|
|
88
49
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,gCAAgC,CAAC;AACjE,eAAO,MAAM,UAAU,gCAAgC,CAAC;AAGxD,eAAO,MAAM,oBAAoB,UAAkB,CAAC;AACpD,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAC3C,eAAO,MAAM,qBAAqB,QAAQ,CAAC;AAC3C,eAAO,MAAM,6BAA6B,QAAQ,CAAC;AAenD;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,gCAAgC,CAAC;AACjE,eAAO,MAAM,UAAU,gCAAgC,CAAC;AAGxD,eAAO,MAAM,oBAAoB,UAAkB,CAAC;AACpD,eAAO,MAAM,mBAAmB,UAAU,CAAC;AAC3C,eAAO,MAAM,qBAAqB,QAAQ,CAAC;AAC3C,eAAO,MAAM,6BAA6B,QAAQ,CAAC;AAenD;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,EAAE,CAE1C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAC1C,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB,GAAG,OAAO,OAAO,CAEjB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAC1C,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAIzB;AAID,eAAO,MAAM,aAAa,UAQzB,CAAC;AAIF,eAAO,MAAM,eAAe,UAO3B,CAAC;AAMF;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ7D"}
|
package/dist/config.js
CHANGED
|
@@ -15,15 +15,42 @@ export const SESSION_VALIDATION_TIMEOUT_MS = 10000;
|
|
|
15
15
|
// Static assets to skip session validation (favicon, robots.txt, etc.)
|
|
16
16
|
// SECURITY CRITICAL: Only add actual static file requests here.
|
|
17
17
|
// Examples of safe entries: /favicon.ico, /robots.txt, /sitemap.xml
|
|
18
|
-
// NEVER add application routes like /dashboard,
|
|
18
|
+
// NEVER add application routes like [memberid]/dashboard, [memberid]/profile, [memberid]/secure/* - this COMPLETELY bypasses authentication. If you add a route here, unauthenticated users can access it without logging in.
|
|
19
19
|
const DEFAULT_SKIP_ASSETS = ['/favicon.ico', '/robots.txt', '/.well-known/security.txt'];
|
|
20
20
|
/**
|
|
21
21
|
* Returns the combined list of assets to skip session validation for.
|
|
22
|
-
* Merges defaults with any custom assets configured via mauthSecurityConfig().
|
|
22
|
+
* Merges defaults with any custom assets configured via mauthSecurityConfig() in astro.config.mjs.
|
|
23
23
|
*/
|
|
24
24
|
export function GET_SKIP_ASSETS() {
|
|
25
25
|
return [...DEFAULT_SKIP_ASSETS, ...__MAUTH_SKIP_ASSETS__];
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Configure Mindful Auth security settings including custom skip assets.
|
|
29
|
+
* Call in astro.config.mjs and pass the result to getMauthViteDefines().
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* // astro.config.mjs
|
|
33
|
+
* const mauthCfg = mauthSecurityConfig({
|
|
34
|
+
* skipAssets: ['/sitemap.xml', '/manifest.webmanifest']
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* export default defineConfig({
|
|
38
|
+
* vite: { define: getMauthViteDefines(mauthCfg) }
|
|
39
|
+
* });
|
|
40
|
+
*/
|
|
41
|
+
export function mauthSecurityConfig(options) {
|
|
42
|
+
return options;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Converts the result of mauthSecurityConfig() into Vite define entries.
|
|
46
|
+
* Pass the output to vite.define in astro.config.mjs so custom values are
|
|
47
|
+
* baked into the SSR bundle at build time.
|
|
48
|
+
*/
|
|
49
|
+
export function getMauthViteDefines(options) {
|
|
50
|
+
return {
|
|
51
|
+
__MAUTH_SKIP_ASSETS__: JSON.stringify(options?.skipAssets ?? []),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
27
54
|
// Public routes that do not require authentication
|
|
28
55
|
// ⚠️ DO NOT EDIT - These are critical for the authentication system to work correctly
|
|
29
56
|
export const PUBLIC_ROUTES = [
|
|
@@ -46,185 +73,23 @@ export const PUBLIC_PREFIXES = [
|
|
|
46
73
|
'/api/public/',
|
|
47
74
|
];
|
|
48
75
|
// ============================================================================
|
|
49
|
-
// Security Headers
|
|
76
|
+
// Security Headers
|
|
50
77
|
// ============================================================================
|
|
51
|
-
// Default allowed script sources for CSP
|
|
52
|
-
// ⚠️ IMPORTANT: Do not remove these domains - they are critical for authentication:
|
|
53
|
-
// Removing these will break authentication and user will be unable to log in.
|
|
54
|
-
const DEFAULT_SCRIPT_SOURCES = [
|
|
55
|
-
"'self'",
|
|
56
|
-
'https://*.cloudflare.com',
|
|
57
|
-
'https://*.cloudflareinsights.com',
|
|
58
|
-
'https://cdn.mindfulauth.com',
|
|
59
|
-
'https://api.mindfulauth.com'
|
|
60
|
-
];
|
|
61
|
-
// Default allowed connection sources for CSP
|
|
62
|
-
const DEFAULT_CONNECT_SOURCES = [
|
|
63
|
-
"'self'",
|
|
64
|
-
'https://*.cloudflare.com',
|
|
65
|
-
'https://api.mindfulauth.com'
|
|
66
|
-
];
|
|
67
|
-
// Default allowed frame sources for CSP
|
|
68
|
-
const DEFAULT_FRAME_SOURCES = [
|
|
69
|
-
"'self'",
|
|
70
|
-
'https://*.cloudflare.com'
|
|
71
|
-
];
|
|
72
|
-
// Default allowed font sources for CSP
|
|
73
|
-
const DEFAULT_FONT_SOURCES = [
|
|
74
|
-
"'self'",
|
|
75
|
-
'data:'
|
|
76
|
-
];
|
|
77
|
-
// Default allowed style sources for CSP
|
|
78
|
-
const DEFAULT_STYLE_SOURCES = [
|
|
79
|
-
"'self'",
|
|
80
|
-
];
|
|
81
|
-
// Default allowed image sources for CSP
|
|
82
|
-
const DEFAULT_IMAGE_SOURCES = [
|
|
83
|
-
"'self'",
|
|
84
|
-
'https:'
|
|
85
|
-
];
|
|
86
|
-
// Default allowed frame ancestors for CSP (clickjacking protection)
|
|
87
|
-
const DEFAULT_FRAME_ANCESTORS = [
|
|
88
|
-
"'self'"
|
|
89
|
-
];
|
|
90
|
-
// Default allowed worker sources for CSP (Web Workers, Service Workers)
|
|
91
|
-
const DEFAULT_WORKER_SOURCES = [
|
|
92
|
-
"'self'"
|
|
93
|
-
];
|
|
94
|
-
// Default allowed manifest sources for CSP (web app manifest)
|
|
95
|
-
const DEFAULT_MANIFEST_SOURCES = [
|
|
96
|
-
"'self'"
|
|
97
|
-
];
|
|
98
|
-
// Default allowed object sources for CSP (disallow plugins like Flash/Java)
|
|
99
|
-
const DEFAULT_OBJECT_SOURCES = [
|
|
100
|
-
"'none'"
|
|
101
|
-
];
|
|
102
|
-
// Default allowed base URIs for CSP
|
|
103
|
-
const DEFAULT_BASE_URIS = [
|
|
104
|
-
"'self'"
|
|
105
|
-
];
|
|
106
|
-
// Default allowed form actions for CSP
|
|
107
|
-
const DEFAULT_FORM_ACTIONS = [
|
|
108
|
-
"'self'"
|
|
109
|
-
];
|
|
110
78
|
/**
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
* IMPORTANT: Do not use Astro 6 security.csp in astro.config.mjs alongside this function. Astro's CSP will override these headers. Use mauthSecurityConfig() exclusively.
|
|
79
|
+
* Returns security headers to be added to every SSR response.
|
|
80
|
+
* CSP (Content-Security-Policy) for script-src and style-src is handled by
|
|
81
|
+
* Astro 6's native security.csp in astro.config.mjs using hashes.
|
|
82
|
+
* The remaining headers here cover transport security, framing, and permissions.
|
|
117
83
|
*
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
* @example
|
|
121
|
-
* // astro.config.mjs
|
|
122
|
-
* const mauthCfg = mauthSecurityConfig({
|
|
123
|
-
* skipAssets: ['/sitemap.xml', '/manifest.webmanifest'],
|
|
124
|
-
* csp: {
|
|
125
|
-
* scriptSources: ['https://analytics.example.com'],
|
|
126
|
-
* connectSources: ['https://api.example.com'],
|
|
127
|
-
* frameSources: ['https://stripe.com'],
|
|
128
|
-
* fontSources: ['https://fonts.googleapis.com'],
|
|
129
|
-
* styleSources: ['https://cdn.example.com/styles'],
|
|
130
|
-
* imageSources: ['https://images.example.com'],
|
|
131
|
-
* frameAncestors: ["'self'"],
|
|
132
|
-
* workerSources: ["'self'"],
|
|
133
|
-
* manifestSources: ["'self'"],
|
|
134
|
-
* objectSources: ["'none'"],
|
|
135
|
-
* baseUris: ["'self'"],
|
|
136
|
-
* formActions: ["'self'"]
|
|
137
|
-
* }
|
|
138
|
-
* });
|
|
139
|
-
*
|
|
140
|
-
* export default defineConfig({
|
|
141
|
-
* vite: { define: getMauthViteDefines(mauthCfg) }
|
|
142
|
-
* });
|
|
84
|
+
* Note: X-Frame-Options: SAMEORIGIN covers clickjacking protection
|
|
85
|
+
* (equivalent to CSP frame-ancestors 'self', which cannot be set via meta tag).
|
|
143
86
|
*/
|
|
144
|
-
export function
|
|
145
|
-
return options;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Converts the result of mauthSecurityConfig() into Vite define entries.
|
|
149
|
-
* Pass the output to vite.define in astro.config.mjs so custom values are
|
|
150
|
-
* baked into the SSR bundle at build time.
|
|
151
|
-
*/
|
|
152
|
-
export function getMauthViteDefines(options) {
|
|
153
|
-
return {
|
|
154
|
-
__MAUTH_SKIP_ASSETS__: JSON.stringify(options?.skipAssets ?? []),
|
|
155
|
-
__MAUTH_SCRIPT_SOURCES__: JSON.stringify(options?.csp?.scriptSources ?? []),
|
|
156
|
-
__MAUTH_CONNECT_SOURCES__: JSON.stringify(options?.csp?.connectSources ?? []),
|
|
157
|
-
__MAUTH_FRAME_SOURCES__: JSON.stringify(options?.csp?.frameSources ?? []),
|
|
158
|
-
__MAUTH_FONT_SOURCES__: JSON.stringify(options?.csp?.fontSources ?? []),
|
|
159
|
-
__MAUTH_STYLE_SOURCES__: JSON.stringify(options?.csp?.styleSources ?? []),
|
|
160
|
-
__MAUTH_IMAGE_SOURCES__: JSON.stringify(options?.csp?.imageSources ?? []),
|
|
161
|
-
__MAUTH_FRAME_ANCESTORS__: JSON.stringify(options?.csp?.frameAncestors ?? []),
|
|
162
|
-
__MAUTH_WORKER_SOURCES__: JSON.stringify(options?.csp?.workerSources ?? []),
|
|
163
|
-
__MAUTH_MANIFEST_SOURCES__: JSON.stringify(options?.csp?.manifestSources ?? []),
|
|
164
|
-
__MAUTH_OBJECT_SOURCES__: JSON.stringify(options?.csp?.objectSources ?? []),
|
|
165
|
-
__MAUTH_BASE_URIS__: JSON.stringify(options?.csp?.baseUris ?? []),
|
|
166
|
-
__MAUTH_FORM_ACTIONS__: JSON.stringify(options?.csp?.formActions ?? []),
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
export function GET_SECURITY_HEADERS(nonce) {
|
|
170
|
-
// Custom sources are baked in at build time via vite.define
|
|
171
|
-
// Using Set to deduplicate sources while preserving order
|
|
172
|
-
const SCRIPT_SOURCES = [...new Set([
|
|
173
|
-
...DEFAULT_SCRIPT_SOURCES,
|
|
174
|
-
...__MAUTH_SCRIPT_SOURCES__,
|
|
175
|
-
...(nonce ? [`'nonce-${nonce}'`] : []),
|
|
176
|
-
])];
|
|
177
|
-
const STYLE_SOURCES = [...new Set([
|
|
178
|
-
...DEFAULT_STYLE_SOURCES,
|
|
179
|
-
...__MAUTH_STYLE_SOURCES__,
|
|
180
|
-
...(nonce ? [`'nonce-${nonce}'`] : []),
|
|
181
|
-
])];
|
|
182
|
-
const CONNECT_SOURCES = [...new Set([...DEFAULT_CONNECT_SOURCES, ...__MAUTH_CONNECT_SOURCES__])];
|
|
183
|
-
const FRAME_SOURCES = [...new Set([...DEFAULT_FRAME_SOURCES, ...__MAUTH_FRAME_SOURCES__])];
|
|
184
|
-
const FONT_SOURCES = [...new Set([...DEFAULT_FONT_SOURCES, ...__MAUTH_FONT_SOURCES__])];
|
|
185
|
-
const IMAGE_SOURCES = [...new Set([...DEFAULT_IMAGE_SOURCES, ...__MAUTH_IMAGE_SOURCES__])];
|
|
186
|
-
const FRAME_ANCESTORS = [...new Set([...DEFAULT_FRAME_ANCESTORS, ...__MAUTH_FRAME_ANCESTORS__])];
|
|
187
|
-
const WORKER_SOURCES = [...new Set([...DEFAULT_WORKER_SOURCES, ...__MAUTH_WORKER_SOURCES__])];
|
|
188
|
-
const MANIFEST_SOURCES = [...new Set([...DEFAULT_MANIFEST_SOURCES, ...__MAUTH_MANIFEST_SOURCES__])];
|
|
189
|
-
const OBJECT_SOURCES = [...new Set([...DEFAULT_OBJECT_SOURCES, ...__MAUTH_OBJECT_SOURCES__])];
|
|
190
|
-
const BASE_URIS = [...new Set([...DEFAULT_BASE_URIS, ...__MAUTH_BASE_URIS__])];
|
|
191
|
-
const FORM_ACTIONS = [...new Set([...DEFAULT_FORM_ACTIONS, ...__MAUTH_FORM_ACTIONS__])];
|
|
87
|
+
export function GET_SECURITY_HEADERS() {
|
|
192
88
|
return {
|
|
193
89
|
'X-Content-Type-Options': 'nosniff',
|
|
194
90
|
'X-Frame-Options': 'SAMEORIGIN',
|
|
195
91
|
'Referrer-Policy': 'strict-origin-when-cross-origin',
|
|
196
92
|
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
|
|
197
93
|
'Permissions-Policy': 'geolocation=(), microphone=(), camera=()',
|
|
198
|
-
'Content-Security-Policy': [
|
|
199
|
-
// Deny by default - only allow explicitly defined sources
|
|
200
|
-
"default-src 'none'",
|
|
201
|
-
// Scripts
|
|
202
|
-
`script-src ${SCRIPT_SOURCES.join(' ')}`,
|
|
203
|
-
// Styles
|
|
204
|
-
`style-src ${STYLE_SOURCES.join(' ')}`,
|
|
205
|
-
// Images
|
|
206
|
-
`img-src ${IMAGE_SOURCES.join(' ')}`,
|
|
207
|
-
// Connections
|
|
208
|
-
`connect-src ${CONNECT_SOURCES.join(' ')}`,
|
|
209
|
-
// Frames
|
|
210
|
-
`frame-src ${FRAME_SOURCES.join(' ')}`,
|
|
211
|
-
// Frame ancestors (clickjacking protection)
|
|
212
|
-
`frame-ancestors ${FRAME_ANCESTORS.join(' ')}`,
|
|
213
|
-
// Fonts
|
|
214
|
-
`font-src ${FONT_SOURCES.join(' ')}`,
|
|
215
|
-
// Web Workers and Service Workers
|
|
216
|
-
`worker-src ${WORKER_SOURCES.join(' ')}`,
|
|
217
|
-
// Web app manifest
|
|
218
|
-
`manifest-src ${MANIFEST_SOURCES.join(' ')}`,
|
|
219
|
-
// Disallow object/embed tags (Flash, Java, etc.)
|
|
220
|
-
`object-src ${OBJECT_SOURCES.join(' ')}`,
|
|
221
|
-
// Base URI
|
|
222
|
-
`base-uri ${BASE_URIS.join(' ')}`,
|
|
223
|
-
// Form action
|
|
224
|
-
`form-action ${FORM_ACTIONS.join(' ')}`,
|
|
225
|
-
// Security directives
|
|
226
|
-
"upgrade-insecure-requests",
|
|
227
|
-
"block-all-mixed-content"
|
|
228
|
-
].join('; ')
|
|
229
94
|
};
|
|
230
95
|
}
|
package/dist/middleware.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAqCA,eAAO,MAAM,SAAS,mCAqFpB,CAAC"}
|
package/dist/middleware.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
import { defineMiddleware } from 'astro:middleware';
|
|
9
9
|
import { env } from 'cloudflare:workers';
|
|
10
10
|
import { PUBLIC_ROUTES, PUBLIC_PREFIXES, GET_SECURITY_HEADERS, GET_SKIP_ASSETS } from './config';
|
|
11
|
-
import { sanitizePath
|
|
11
|
+
import { sanitizePath } from './security';
|
|
12
12
|
import { validateSession, validateMemberIdInUrl } from './auth';
|
|
13
13
|
/** Check if a path is a public route (no auth required) */
|
|
14
14
|
function isPublicRoute(pathname) {
|
|
@@ -18,9 +18,10 @@ function isPublicRoute(pathname) {
|
|
|
18
18
|
/** Add security headers to a response */
|
|
19
19
|
// NOTE: In Cloudflare Workers, Response.headers is immutable.
|
|
20
20
|
// We must create a new Response with a fresh Headers object instead of mutating.
|
|
21
|
-
|
|
21
|
+
// CSP for script-src/style-src is handled by Astro 6's native security.csp (via <meta> tag).
|
|
22
|
+
function addSecurityHeaders(response) {
|
|
22
23
|
const newHeaders = new Headers(response.headers);
|
|
23
|
-
Object.entries(GET_SECURITY_HEADERS(
|
|
24
|
+
Object.entries(GET_SECURITY_HEADERS()).forEach(([key, value]) => {
|
|
24
25
|
newHeaders.set(key, value);
|
|
25
26
|
});
|
|
26
27
|
return new Response(response.body, {
|
|
@@ -38,10 +39,6 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
38
39
|
const httpsUrl = url.toString().replace('http://', 'https://');
|
|
39
40
|
return redirect(httpsUrl, 307);
|
|
40
41
|
}
|
|
41
|
-
// Generate a per-request nonce for CSP. Exposed as locals.cspNonce so
|
|
42
|
-
// layouts can add nonce={Astro.locals.cspNonce} to inline <script> tags.
|
|
43
|
-
const nonce = generateNonce();
|
|
44
|
-
locals.cspNonce = nonce;
|
|
45
42
|
// Skip middleware for static assets FIRST (before dev mode)
|
|
46
43
|
if (GET_SKIP_ASSETS().includes(pathname)) {
|
|
47
44
|
return next();
|
|
@@ -69,11 +66,11 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
69
66
|
if (url.hostname === 'localhost' || url.hostname === '127.0.0.1') {
|
|
70
67
|
if (isPublicRoute(pathname)) {
|
|
71
68
|
locals.recordId = null;
|
|
72
|
-
return addSecurityHeaders(await next()
|
|
69
|
+
return addSecurityHeaders(await next());
|
|
73
70
|
}
|
|
74
71
|
const match = pathname.match(/^\/([a-zA-Z0-9-]+)(?:\/|$)/);
|
|
75
72
|
locals.recordId = match ? match[1] : 'preview-user-123';
|
|
76
|
-
return addSecurityHeaders(await next()
|
|
73
|
+
return addSecurityHeaders(await next());
|
|
77
74
|
}
|
|
78
75
|
// Sanitize path
|
|
79
76
|
const safePath = sanitizePath(pathname);
|
|
@@ -83,7 +80,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
83
80
|
// Public routes - no auth needed
|
|
84
81
|
if (isPublicRoute(safePath)) {
|
|
85
82
|
locals.recordId = null;
|
|
86
|
-
return addSecurityHeaders(await next()
|
|
83
|
+
return addSecurityHeaders(await next());
|
|
87
84
|
}
|
|
88
85
|
// Protected route - validate session
|
|
89
86
|
// ASTRO 6 CHANGE: Environment variables are accessed directly from 'cloudflare:workers' env,
|
|
@@ -107,5 +104,5 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
107
104
|
return new Response('Forbidden: Invalid user ID in URL', { status: 403 });
|
|
108
105
|
}
|
|
109
106
|
locals.recordId = session.recordId;
|
|
110
|
-
return addSecurityHeaders(await next()
|
|
107
|
+
return addSecurityHeaders(await next());
|
|
111
108
|
});
|
package/dist/security.d.ts
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generate a cryptographically secure random nonce for use in CSP headers.
|
|
3
|
-
* The same nonce must be added as a `nonce` attribute on every inline <script>
|
|
4
|
-
* tag so the browser allows it to execute.
|
|
5
|
-
*/
|
|
6
|
-
export declare function generateNonce(): string;
|
|
7
1
|
/** Sanitize endpoint path (prevents ../ traversal and encoded variants) */
|
|
8
2
|
export declare function sanitizeEndpoint(endpoint: string): string | null;
|
|
9
3
|
/** Sanitize URL path (prevents ../ traversal and encoded variants) */
|
package/dist/security.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"security.d.ts","sourceRoot":"","sources":["../src/security.ts"],"names":[],"mappings":"AAkBA,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIhE;AAED,sEAAsE;AACtE,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI5D"}
|
package/dist/security.js
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
|
-
// Security utilities - path traversal prevention
|
|
1
|
+
// Security utilities - path traversal prevention
|
|
2
2
|
const MAX_PATH_LENGTH = 2048;
|
|
3
|
-
/**
|
|
4
|
-
* Generate a cryptographically secure random nonce for use in CSP headers.
|
|
5
|
-
* The same nonce must be added as a `nonce` attribute on every inline <script>
|
|
6
|
-
* tag so the browser allows it to execute.
|
|
7
|
-
*/
|
|
8
|
-
export function generateNonce() {
|
|
9
|
-
const bytes = new Uint8Array(16);
|
|
10
|
-
crypto.getRandomValues(bytes);
|
|
11
|
-
return btoa(String.fromCharCode(...bytes));
|
|
12
|
-
}
|
|
13
3
|
/** Decode and check for traversal attacks */
|
|
14
4
|
function decodeAndValidate(str) {
|
|
15
5
|
if (!str || typeof str !== 'string' || str.length > MAX_PATH_LENGTH)
|
package/dist/types.d.ts
CHANGED
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAG/C,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,CAAC,EAAE;QACR,GAAG,CAAC,EAAE;YACJ,gBAAgB,CAAC,EAAE,MAAM,CAAC;SAC3B,CAAC;KACH,CAAC;CACH;AAGD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,GAAG,CAAC;QACZ,UAAU,MAAO,SAAQ,iBAAiB;SAAG;KAC9C;CACF;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,CAAC"}
|
package/dist/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mindfulauth/core",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.4",
|
|
4
4
|
"description": "Mindful Auth core authentication library for Astro 6",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"astro": "^6.0.0-beta.14"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@cloudflare/workers-types": "^4.
|
|
48
|
+
"@cloudflare/workers-types": "^4.20260304.0",
|
|
49
49
|
"astro": "^6.0.0-beta.15",
|
|
50
50
|
"typescript": "^5.9.3"
|
|
51
51
|
}
|