@mindfulauth/core 1.1.0 → 1.2.1
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 +6 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +12 -2
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +10 -6
- package/dist/security.d.ts +6 -0
- package/dist/security.d.ts.map +1 -1
- package/dist/security.js +11 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -59,6 +59,11 @@ export declare function getMauthViteDefines(options?: {
|
|
|
59
59
|
/**
|
|
60
60
|
* Get security headers with CSP sources merged from defaults and build-time
|
|
61
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).
|
|
62
67
|
*/
|
|
63
|
-
export declare function GET_SECURITY_HEADERS(): Record<string, string>;
|
|
68
|
+
export declare function GET_SECURITY_HEADERS(nonce?: string): Record<string, string>;
|
|
64
69
|
//# 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;AA0CF;;;;;;;;;;;;;;;;;;;;;GAqBG;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;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;KAC1B,CAAC;CACL,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiD3E"}
|
package/dist/config.js
CHANGED
|
@@ -54,6 +54,7 @@ export const PUBLIC_PREFIXES = [
|
|
|
54
54
|
const DEFAULT_SCRIPT_SOURCES = [
|
|
55
55
|
"'self'",
|
|
56
56
|
'https://*.cloudflare.com',
|
|
57
|
+
'https://*.cloudflareinsights.com',
|
|
57
58
|
'https://cdn.mindfulauth.com',
|
|
58
59
|
'https://api.mindfulauth.com'
|
|
59
60
|
];
|
|
@@ -115,10 +116,19 @@ export function getMauthViteDefines(options) {
|
|
|
115
116
|
/**
|
|
116
117
|
* Get security headers with CSP sources merged from defaults and build-time
|
|
117
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).
|
|
118
124
|
*/
|
|
119
|
-
export function GET_SECURITY_HEADERS() {
|
|
125
|
+
export function GET_SECURITY_HEADERS(nonce) {
|
|
120
126
|
// Custom sources are baked in at build time via vite.define
|
|
121
|
-
const SCRIPT_SOURCES = [
|
|
127
|
+
const SCRIPT_SOURCES = [
|
|
128
|
+
...DEFAULT_SCRIPT_SOURCES,
|
|
129
|
+
...__MAUTH_SCRIPT_SOURCES__,
|
|
130
|
+
...(nonce ? [`'nonce-${nonce}'`] : []),
|
|
131
|
+
];
|
|
122
132
|
const CONNECT_SOURCES = [...DEFAULT_CONNECT_SOURCES, ...__MAUTH_CONNECT_SOURCES__];
|
|
123
133
|
const FRAME_SOURCES = [...DEFAULT_FRAME_SOURCES, ...__MAUTH_FRAME_SOURCES__];
|
|
124
134
|
const FONT_SOURCES = [...DEFAULT_FONT_SOURCES, ...__MAUTH_FONT_SOURCES__];
|
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,mCAmEpB,CAAC"}
|
package/dist/middleware.js
CHANGED
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
// Runs before all route handlers to enforce authentication
|
|
3
3
|
import { defineMiddleware } from 'astro:middleware';
|
|
4
4
|
import { PUBLIC_ROUTES, PUBLIC_PREFIXES, GET_SECURITY_HEADERS, GET_SKIP_ASSETS } from './config';
|
|
5
|
-
import { sanitizePath } from './security';
|
|
5
|
+
import { sanitizePath, generateNonce } from './security';
|
|
6
6
|
import { validateSession, validateMemberIdInUrl } from './auth';
|
|
7
7
|
/** Check if a path is a public route (no auth required) */
|
|
8
8
|
function isPublicRoute(pathname) {
|
|
9
9
|
return PUBLIC_ROUTES.includes(pathname) ||
|
|
10
10
|
PUBLIC_PREFIXES.some(prefix => pathname.startsWith(prefix));
|
|
11
11
|
}
|
|
12
|
-
/** Add security headers to a response */
|
|
13
|
-
function addSecurityHeaders(response) {
|
|
14
|
-
Object.entries(GET_SECURITY_HEADERS()).forEach(([key, value]) => {
|
|
12
|
+
/** Add security headers (including CSP nonce) to a response */
|
|
13
|
+
function addSecurityHeaders(response, nonce) {
|
|
14
|
+
Object.entries(GET_SECURITY_HEADERS(nonce)).forEach(([key, value]) => {
|
|
15
15
|
response.headers.set(key, value);
|
|
16
16
|
});
|
|
17
17
|
return response;
|
|
@@ -22,6 +22,10 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
22
22
|
const pathname = url.pathname;
|
|
23
23
|
// Type assertion for locals (users should extend App.Locals in their project)
|
|
24
24
|
const authLocals = locals;
|
|
25
|
+
// Generate a per-request nonce for CSP. Exposed as locals.cspNonce so
|
|
26
|
+
// layouts can add nonce={Astro.locals.cspNonce} to inline <script> tags.
|
|
27
|
+
const nonce = generateNonce();
|
|
28
|
+
authLocals.cspNonce = nonce;
|
|
25
29
|
// Skip middleware for static assets FIRST (before dev mode)
|
|
26
30
|
if (GET_SKIP_ASSETS().includes(pathname)) {
|
|
27
31
|
return next();
|
|
@@ -46,7 +50,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
46
50
|
// Public routes - no auth needed
|
|
47
51
|
if (isPublicRoute(safePath)) {
|
|
48
52
|
authLocals.recordId = null;
|
|
49
|
-
return addSecurityHeaders(await next());
|
|
53
|
+
return addSecurityHeaders(await next(), nonce);
|
|
50
54
|
}
|
|
51
55
|
// Protected route - validate session
|
|
52
56
|
const internalApiKey = authLocals.runtime?.env?.INTERNAL_API_KEY || import.meta.env.INTERNAL_API_KEY;
|
|
@@ -68,5 +72,5 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|
|
68
72
|
return new Response('Forbidden: Invalid user ID in URL', { status: 403 });
|
|
69
73
|
}
|
|
70
74
|
authLocals.recordId = session.recordId;
|
|
71
|
-
return addSecurityHeaders(await next());
|
|
75
|
+
return addSecurityHeaders(await next(), nonce);
|
|
72
76
|
});
|
package/dist/security.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
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;
|
|
1
7
|
/** Sanitize endpoint path (prevents ../ traversal and encoded variants) */
|
|
2
8
|
export declare function sanitizeEndpoint(endpoint: string): string | null;
|
|
3
9
|
/** 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":"AAIA;;;;GAIG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAItC;AAgBD,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,5 +1,15 @@
|
|
|
1
|
-
// Security utilities - path traversal prevention
|
|
1
|
+
// Security utilities - path traversal prevention, nonce generation
|
|
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
|
+
}
|
|
3
13
|
/** Decode and check for traversal attacks */
|
|
4
14
|
function decodeAndValidate(str) {
|
|
5
15
|
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":"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"}
|
|
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,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,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"}
|