@mindfulauth/core 1.2.1 → 1.3.0
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 +29 -10
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +90 -25
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +5 -0
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -15,6 +15,10 @@ export declare const PUBLIC_PREFIXES: string[];
|
|
|
15
15
|
* Configure Mindful Auth security settings including CSP sources and static
|
|
16
16
|
* assets to skip. Returns the options to be passed to getMauthViteDefines().
|
|
17
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
|
+
*
|
|
18
22
|
* Call in astro.config.mjs and pass the result to vite.define:
|
|
19
23
|
*
|
|
20
24
|
* @example
|
|
@@ -25,7 +29,15 @@ export declare const PUBLIC_PREFIXES: string[];
|
|
|
25
29
|
* scriptSources: ['https://analytics.example.com'],
|
|
26
30
|
* connectSources: ['https://api.example.com'],
|
|
27
31
|
* frameSources: ['https://stripe.com'],
|
|
28
|
-
* fontSources: ['https://fonts.googleapis.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'"]
|
|
29
41
|
* }
|
|
30
42
|
* });
|
|
31
43
|
*
|
|
@@ -40,6 +52,14 @@ export declare function mauthSecurityConfig(options?: {
|
|
|
40
52
|
connectSources?: string[];
|
|
41
53
|
frameSources?: string[];
|
|
42
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[];
|
|
43
63
|
};
|
|
44
64
|
}): typeof options;
|
|
45
65
|
/**
|
|
@@ -54,16 +74,15 @@ export declare function getMauthViteDefines(options?: {
|
|
|
54
74
|
connectSources?: string[];
|
|
55
75
|
frameSources?: string[];
|
|
56
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[];
|
|
57
85
|
};
|
|
58
86
|
}): Record<string, string>;
|
|
59
|
-
/**
|
|
60
|
-
* Get security headers with CSP sources merged from defaults and build-time
|
|
61
|
-
* custom values injected via vite.define (from getMauthViteDefines()).
|
|
62
|
-
*
|
|
63
|
-
* Pass the per-request `nonce` generated by `generateNonce()` so the
|
|
64
|
-
* Content-Security-Policy includes `'nonce-<value>'` in `script-src`.
|
|
65
|
-
* The same nonce must be set as the `nonce` attribute on every inline
|
|
66
|
-
* `<script>` tag (available via `Astro.locals.cspNonce` in layouts).
|
|
67
|
-
*/
|
|
68
87
|
export declare function GET_SECURITY_HEADERS(nonce?: string): Record<string, string>;
|
|
69
88
|
//# 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;AAID,eAAO,MAAM,aAAa,UAQzB,CAAC;AAIF,eAAO,MAAM,eAAe,UAO3B,CAAC;
|
|
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;AAID,eAAO,MAAM,aAAa,UAQzB,CAAC;AAIF,eAAO,MAAM,eAAe,UAO3B,CAAC;AA2FF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAC1C,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,CAAC,EAAE;QACF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC;CACL,GAAG,OAAO,OAAO,CAEjB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,CAAC,EAAE;IAC1C,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,CAAC,EAAE;QACF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QACvB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;QAC1B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;QAC3B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;KAC1B,CAAC;CACL,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAgBzB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA2E3E"}
|
package/dist/config.js
CHANGED
|
@@ -74,10 +74,47 @@ const DEFAULT_FONT_SOURCES = [
|
|
|
74
74
|
"'self'",
|
|
75
75
|
'data:'
|
|
76
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
|
+
];
|
|
77
110
|
/**
|
|
78
111
|
* Configure Mindful Auth security settings including CSP sources and static
|
|
79
112
|
* assets to skip. Returns the options to be passed to getMauthViteDefines().
|
|
80
113
|
*
|
|
114
|
+
* 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().
|
|
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.
|
|
117
|
+
*
|
|
81
118
|
* Call in astro.config.mjs and pass the result to vite.define:
|
|
82
119
|
*
|
|
83
120
|
* @example
|
|
@@ -88,7 +125,15 @@ const DEFAULT_FONT_SOURCES = [
|
|
|
88
125
|
* scriptSources: ['https://analytics.example.com'],
|
|
89
126
|
* connectSources: ['https://api.example.com'],
|
|
90
127
|
* frameSources: ['https://stripe.com'],
|
|
91
|
-
* fontSources: ['https://fonts.googleapis.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'"]
|
|
92
137
|
* }
|
|
93
138
|
* });
|
|
94
139
|
*
|
|
@@ -111,27 +156,39 @@ export function getMauthViteDefines(options) {
|
|
|
111
156
|
__MAUTH_CONNECT_SOURCES__: JSON.stringify(options?.csp?.connectSources ?? []),
|
|
112
157
|
__MAUTH_FRAME_SOURCES__: JSON.stringify(options?.csp?.frameSources ?? []),
|
|
113
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 ?? []),
|
|
114
167
|
};
|
|
115
168
|
}
|
|
116
|
-
/**
|
|
117
|
-
* Get security headers with CSP sources merged from defaults and build-time
|
|
118
|
-
* custom values injected via vite.define (from getMauthViteDefines()).
|
|
119
|
-
*
|
|
120
|
-
* Pass the per-request `nonce` generated by `generateNonce()` so the
|
|
121
|
-
* Content-Security-Policy includes `'nonce-<value>'` in `script-src`.
|
|
122
|
-
* The same nonce must be set as the `nonce` attribute on every inline
|
|
123
|
-
* `<script>` tag (available via `Astro.locals.cspNonce` in layouts).
|
|
124
|
-
*/
|
|
125
169
|
export function GET_SECURITY_HEADERS(nonce) {
|
|
126
170
|
// Custom sources are baked in at build time via vite.define
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
|
|
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__])];
|
|
135
192
|
return {
|
|
136
193
|
'X-Content-Type-Options': 'nosniff',
|
|
137
194
|
'X-Frame-Options': 'SAMEORIGIN',
|
|
@@ -139,25 +196,33 @@ export function GET_SECURITY_HEADERS(nonce) {
|
|
|
139
196
|
'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
|
|
140
197
|
'Permissions-Policy': 'geolocation=(), microphone=(), camera=()',
|
|
141
198
|
'Content-Security-Policy': [
|
|
142
|
-
//
|
|
143
|
-
"default-src '
|
|
199
|
+
// Deny by default - only allow explicitly defined sources
|
|
200
|
+
"default-src 'none'",
|
|
144
201
|
// Scripts
|
|
145
202
|
`script-src ${SCRIPT_SOURCES.join(' ')}`,
|
|
146
203
|
// Styles
|
|
147
|
-
|
|
204
|
+
`style-src ${STYLE_SOURCES.join(' ')}`,
|
|
148
205
|
// Images
|
|
149
|
-
|
|
206
|
+
`img-src ${IMAGE_SOURCES.join(' ')}`,
|
|
150
207
|
// Connections
|
|
151
208
|
`connect-src ${CONNECT_SOURCES.join(' ')}`,
|
|
152
209
|
// Frames
|
|
153
210
|
`frame-src ${FRAME_SOURCES.join(' ')}`,
|
|
211
|
+
// Frame ancestors (clickjacking protection)
|
|
212
|
+
`frame-ancestors ${FRAME_ANCESTORS.join(' ')}`,
|
|
154
213
|
// Fonts
|
|
155
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(' ')}`,
|
|
156
219
|
// Disallow object/embed tags (Flash, Java, etc.)
|
|
157
|
-
|
|
220
|
+
`object-src ${OBJECT_SOURCES.join(' ')}`,
|
|
221
|
+
// Base URI
|
|
222
|
+
`base-uri ${BASE_URIS.join(' ')}`,
|
|
223
|
+
// Form action
|
|
224
|
+
`form-action ${FORM_ACTIONS.join(' ')}`,
|
|
158
225
|
// Security directives
|
|
159
|
-
"base-uri 'self'",
|
|
160
|
-
"form-action 'self'",
|
|
161
226
|
"upgrade-insecure-requests",
|
|
162
227
|
"block-all-mixed-content"
|
|
163
228
|
].join('; ')
|
package/dist/middleware.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,SAAS,mCAyEpB,CAAC"}
|
package/dist/middleware.js
CHANGED
|
@@ -20,6 +20,11 @@ function addSecurityHeaders(response, nonce) {
|
|
|
20
20
|
export const onRequest = defineMiddleware(async (context, next) => {
|
|
21
21
|
const { request, url, redirect, locals } = context;
|
|
22
22
|
const pathname = url.pathname;
|
|
23
|
+
// Redirect HTTP to HTTPS (skip in dev mode and localhost)
|
|
24
|
+
if (!import.meta.env.DEV && url.protocol === 'http:' && url.hostname !== 'localhost' && url.hostname !== '127.0.0.1') {
|
|
25
|
+
const httpsUrl = url.toString().replace('http://', 'https://');
|
|
26
|
+
return redirect(httpsUrl, 307);
|
|
27
|
+
}
|
|
23
28
|
// Type assertion for locals (users should extend App.Locals in their project)
|
|
24
29
|
const authLocals = locals;
|
|
25
30
|
// Generate a per-request nonce for CSP. Exposed as locals.cspNonce so
|