@mindfulauth/core 1.3.0 → 2.0.0-beta.10

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.
Files changed (54) hide show
  1. package/README.md +2 -14
  2. package/dist/astro/ForgotPasswordScript.astro +64 -0
  3. package/dist/astro/LoginScript.astro +209 -0
  4. package/dist/astro/MagicLoginScript.astro +62 -0
  5. package/dist/astro/MagicRegisterScript.astro +73 -0
  6. package/dist/astro/MainScript.astro +236 -0
  7. package/dist/astro/RegisterPasswordScript.astro +118 -0
  8. package/dist/astro/ResendVerificationScript.astro +51 -0
  9. package/dist/astro/ResetPasswordScript.astro +155 -0
  10. package/dist/astro/SecurityScript.astro +449 -0
  11. package/dist/astro/TurnstileInit.astro +112 -0
  12. package/dist/astro/VerifyEmailScript.astro +72 -0
  13. package/dist/astro/VerifyMagicLinkScript.astro +195 -0
  14. package/dist/astro/index.d.ts +13 -0
  15. package/dist/astro/index.d.ts.map +1 -0
  16. package/dist/astro/index.js +15 -0
  17. package/dist/core/auth-handler.d.ts.map +1 -0
  18. package/dist/{auth-handler.js → core/auth-handler.js} +7 -4
  19. package/dist/{auth.d.ts → core/auth.d.ts} +1 -1
  20. package/dist/core/auth.d.ts.map +1 -0
  21. package/dist/{auth.js → core/auth.js} +1 -1
  22. package/dist/core/config.d.ts +47 -0
  23. package/dist/core/config.d.ts.map +1 -0
  24. package/dist/core/config.js +95 -0
  25. package/dist/core/csp.d.ts +19 -0
  26. package/dist/core/csp.d.ts.map +1 -0
  27. package/dist/core/csp.js +36 -0
  28. package/dist/core/index.d.ts +6 -0
  29. package/dist/core/index.d.ts.map +1 -0
  30. package/dist/core/index.js +17 -0
  31. package/dist/core/middleware.d.ts.map +1 -0
  32. package/dist/core/middleware.js +108 -0
  33. package/dist/core/security.d.ts +5 -0
  34. package/dist/core/security.d.ts.map +1 -0
  35. package/dist/{security.js → core/security.js} +1 -11
  36. package/dist/{types.d.ts → core/types.d.ts} +0 -6
  37. package/dist/core/types.d.ts.map +1 -0
  38. package/package.json +25 -15
  39. package/dist/auth-handler.d.ts.map +0 -1
  40. package/dist/auth.d.ts.map +0 -1
  41. package/dist/config.d.ts +0 -88
  42. package/dist/config.d.ts.map +0 -1
  43. package/dist/config.js +0 -230
  44. package/dist/index.d.ts +0 -7
  45. package/dist/index.d.ts.map +0 -1
  46. package/dist/index.js +0 -13
  47. package/dist/middleware.d.ts.map +0 -1
  48. package/dist/middleware.js +0 -81
  49. package/dist/security.d.ts +0 -11
  50. package/dist/security.d.ts.map +0 -1
  51. package/dist/types.d.ts.map +0 -1
  52. /package/dist/{auth-handler.d.ts → core/auth-handler.d.ts} +0 -0
  53. /package/dist/{middleware.d.ts → core/middleware.d.ts} +0 -0
  54. /package/dist/{types.js → core/types.js} +0 -0
@@ -1,15 +1,5 @@
1
- // Security utilities - path traversal prevention, nonce generation
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)
@@ -1,12 +1,6 @@
1
1
  import type { MiddlewareHandler } from 'astro';
2
2
  export interface MindfulAuthLocals {
3
3
  recordId: string | null;
4
- cspNonce?: string;
5
- runtime?: {
6
- env?: {
7
- INTERNAL_API_KEY?: string;
8
- };
9
- };
10
4
  }
11
5
  declare global {
12
6
  namespace App {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/core/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;CACzB;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/package.json CHANGED
@@ -1,26 +1,34 @@
1
1
  {
2
2
  "name": "@mindfulauth/core",
3
- "version": "1.3.0",
4
- "description": "Mindful Auth core authentication library for Astro",
3
+ "version": "2.0.0-beta.10",
4
+ "description": "Mindful Auth core authentication library for Astro 6",
5
5
  "type": "module",
6
- "main": "./dist/index.js",
7
- "types": "./dist/index.d.ts",
6
+ "sideEffects": false,
8
7
  "exports": {
9
8
  ".": {
10
- "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js"
9
+ "types": "./dist/core/index.d.ts",
10
+ "import": "./dist/core/index.js"
12
11
  },
12
+ "./astro": {
13
+ "types": "./dist/astro/index.d.ts",
14
+ "import": "./dist/astro/index.js"
15
+ },
16
+ "./astro/*.astro": "./dist/astro/*.astro",
13
17
  "./middleware": {
14
- "types": "./dist/middleware.d.ts",
15
- "import": "./dist/middleware.js"
18
+ "types": "./dist/core/middleware.d.ts",
19
+ "import": "./dist/core/middleware.js"
16
20
  },
17
21
  "./auth-handler": {
18
- "types": "./dist/auth-handler.d.ts",
19
- "import": "./dist/auth-handler.js"
22
+ "types": "./dist/core/auth-handler.d.ts",
23
+ "import": "./dist/core/auth-handler.js"
20
24
  },
21
25
  "./config": {
22
- "types": "./dist/config.d.ts",
23
- "import": "./dist/config.js"
26
+ "types": "./dist/core/config.d.ts",
27
+ "import": "./dist/core/config.js"
28
+ },
29
+ "./csp": {
30
+ "types": "./dist/core/csp.d.ts",
31
+ "import": "./dist/core/csp.js"
24
32
  }
25
33
  },
26
34
  "files": [
@@ -28,7 +36,7 @@
28
36
  "README.md"
29
37
  ],
30
38
  "scripts": {
31
- "build": "tsc",
39
+ "build": "tsc && cp src/astro/*.astro dist/astro/",
32
40
  "dev": "tsc --watch",
33
41
  "prepublishOnly": "npm run build"
34
42
  },
@@ -42,10 +50,12 @@
42
50
  "author": "Mindful Auth",
43
51
  "license": "MIT",
44
52
  "peerDependencies": {
45
- "astro": "^5.0.0"
53
+ "astro": "^6.0.0-beta.20"
46
54
  },
47
55
  "devDependencies": {
48
- "astro": "^5.17.3",
56
+ "@cloudflare/workers-types": "^4.20260307.1",
57
+ "@types/node": "^25.3.5",
58
+ "astro": "^6.0.0-beta.20",
49
59
  "typescript": "^5.9.3"
50
60
  }
51
61
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth-handler.d.ts","sourceRoot":"","sources":["../src/auth-handler.ts"],"names":[],"mappings":"AAmEA,2EAA2E;AAC3E,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CA4BpH;AAED,gEAAgE;AAChE,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwDrH"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAEvD,yDAAyD;AACzD,wBAAsB,eAAe,CACjC,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACvB,OAAO,CAAC,uBAAuB,CAAC,CAsClC;AAED,oGAAoG;AACpG,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAAE,CAerI"}
package/dist/config.d.ts DELETED
@@ -1,88 +0,0 @@
1
- export declare const CENTRAL_AUTH_ORIGIN = "https://api.mindfulauth.com";
2
- export declare const CDN_ORIGIN = "https://cdn.mindfulauth.com";
3
- export declare const ALLOWED_AUTH_METHODS: string[];
4
- export declare const MAX_BODY_SIZE_BYTES = 1048576;
5
- export declare const AUTH_PROXY_TIMEOUT_MS = 15000;
6
- export declare const SESSION_VALIDATION_TIMEOUT_MS = 10000;
7
- /**
8
- * Returns the combined list of assets to skip session validation for.
9
- * Merges defaults with any custom assets configured via mauthSecurityConfig().
10
- */
11
- export declare function GET_SKIP_ASSETS(): string[];
12
- export declare const PUBLIC_ROUTES: string[];
13
- export declare const PUBLIC_PREFIXES: string[];
14
- /**
15
- * Configure Mindful Auth security settings including CSP sources and static
16
- * assets to skip. Returns the options to be passed to getMauthViteDefines().
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:
23
- *
24
- * @example
25
- * // astro.config.mjs
26
- * 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
- * }
42
- * });
43
- *
44
- * export default defineConfig({
45
- * vite: { define: getMauthViteDefines(mauthCfg) }
46
- * });
47
- */
48
- export declare function mauthSecurityConfig(options?: {
49
- 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
- }): typeof options;
65
- /**
66
- * Converts the result of mauthSecurityConfig() into Vite define entries.
67
- * Pass the output to vite.define in astro.config.mjs so custom values are
68
- * baked into the SSR bundle at build time.
69
- */
70
- export declare function getMauthViteDefines(options?: {
71
- 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
- }): Record<string, string>;
87
- export declare function GET_SECURITY_HEADERS(nonce?: string): Record<string, string>;
88
- //# sourceMappingURL=config.d.ts.map
@@ -1 +0,0 @@
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 DELETED
@@ -1,230 +0,0 @@
1
- // ============================================================================
2
- // Configuration for the Astro Portal
3
- // ============================================================================
4
- // API Endpoints
5
- export const CENTRAL_AUTH_ORIGIN = 'https://api.mindfulauth.com';
6
- export const CDN_ORIGIN = 'https://cdn.mindfulauth.com';
7
- // Request & Timeout Configuration
8
- export const ALLOWED_AUTH_METHODS = ['GET', 'POST'];
9
- export const MAX_BODY_SIZE_BYTES = 1048576; // 1MB limit
10
- export const AUTH_PROXY_TIMEOUT_MS = 15000;
11
- export const SESSION_VALIDATION_TIMEOUT_MS = 10000;
12
- // ============================================================================
13
- // Static Assets & Route Configuration
14
- // ============================================================================
15
- // Static assets to skip session validation (favicon, robots.txt, etc.)
16
- // SECURITY CRITICAL: Only add actual static file requests here.
17
- // Examples of safe entries: /favicon.ico, /robots.txt, /sitemap.xml
18
- // NEVER add application routes like /dashboard, /profile, /secure/* - this COMPLETELY bypasses authentication. If you add a route here, unauthenticated users can access it without logging in.
19
- const DEFAULT_SKIP_ASSETS = ['/favicon.ico', '/robots.txt', '/.well-known/security.txt'];
20
- /**
21
- * Returns the combined list of assets to skip session validation for.
22
- * Merges defaults with any custom assets configured via mauthSecurityConfig().
23
- */
24
- export function GET_SKIP_ASSETS() {
25
- return [...DEFAULT_SKIP_ASSETS, ...__MAUTH_SKIP_ASSETS__];
26
- }
27
- // Public routes that do not require authentication
28
- // ⚠️ DO NOT EDIT - These are critical for the authentication system to work correctly
29
- export const PUBLIC_ROUTES = [
30
- '/',
31
- '/login',
32
- '/register',
33
- '/magic-login',
34
- '/magic-register',
35
- '/forgot-password',
36
- '/resend-verification',
37
- ];
38
- // Dynamic public routes (prefix matching)
39
- // ⚠️ DO NOT EDIT - These are critical for the authentication system to work correctly
40
- export const PUBLIC_PREFIXES = [
41
- '/auth/',
42
- '/email-verified/',
43
- '/reset-password/',
44
- '/verify-email/',
45
- '/verify-magic-link/',
46
- '/api/public/',
47
- ];
48
- // ============================================================================
49
- // Security Headers & CSP Configuration
50
- // ============================================================================
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
- /**
111
- * Configure Mindful Auth security settings including CSP sources and static
112
- * assets to skip. Returns the options to be passed to getMauthViteDefines().
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
- *
118
- * Call in astro.config.mjs and pass the result to vite.define:
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
- * });
143
- */
144
- export function mauthSecurityConfig(options) {
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__])];
192
- return {
193
- 'X-Content-Type-Options': 'nosniff',
194
- 'X-Frame-Options': 'SAMEORIGIN',
195
- 'Referrer-Policy': 'strict-origin-when-cross-origin',
196
- 'Strict-Transport-Security': 'max-age=31536000; includeSubDomains',
197
- '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
- };
230
- }
package/dist/index.d.ts DELETED
@@ -1,7 +0,0 @@
1
- export * from './types';
2
- export * from './config';
3
- export * from './auth';
4
- export * from './auth-handler';
5
- export * from './security';
6
- export { onRequest } from './middleware';
7
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,SAAS,CAAC;AAGxB,cAAc,UAAU,CAAC;AAGzB,cAAc,QAAQ,CAAC;AAGvB,cAAc,gBAAgB,CAAC;AAG/B,cAAc,YAAY,CAAC;AAG3B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC"}
package/dist/index.js DELETED
@@ -1,13 +0,0 @@
1
- // Mindful Auth Core - Main exports
2
- // Types
3
- export * from './types';
4
- // Configuration
5
- export * from './config';
6
- // Authentication
7
- export * from './auth';
8
- // Auth handler for API routes
9
- export * from './auth-handler';
10
- // Security utilities
11
- export * from './security';
12
- // Middleware (also available via '@mindful-auth/core/middleware')
13
- export { onRequest } from './middleware';
@@ -1 +0,0 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAuBA,eAAO,MAAM,SAAS,mCAyEpB,CAAC"}
@@ -1,81 +0,0 @@
1
- // Global middleware for session validation
2
- // Runs before all route handlers to enforce authentication
3
- import { defineMiddleware } from 'astro:middleware';
4
- import { PUBLIC_ROUTES, PUBLIC_PREFIXES, GET_SECURITY_HEADERS, GET_SKIP_ASSETS } from './config';
5
- import { sanitizePath, generateNonce } from './security';
6
- import { validateSession, validateMemberIdInUrl } from './auth';
7
- /** Check if a path is a public route (no auth required) */
8
- function isPublicRoute(pathname) {
9
- return PUBLIC_ROUTES.includes(pathname) ||
10
- PUBLIC_PREFIXES.some(prefix => pathname.startsWith(prefix));
11
- }
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
- response.headers.set(key, value);
16
- });
17
- return response;
18
- }
19
- // Main middleware function
20
- export const onRequest = defineMiddleware(async (context, next) => {
21
- const { request, url, redirect, locals } = context;
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
- }
28
- // Type assertion for locals (users should extend App.Locals in their project)
29
- const authLocals = locals;
30
- // Generate a per-request nonce for CSP. Exposed as locals.cspNonce so
31
- // layouts can add nonce={Astro.locals.cspNonce} to inline <script> tags.
32
- const nonce = generateNonce();
33
- authLocals.cspNonce = nonce;
34
- // Skip middleware for static assets FIRST (before dev mode)
35
- if (GET_SKIP_ASSETS().includes(pathname)) {
36
- return next();
37
- }
38
- // DEV MODE: Skip auth on localhost
39
- if (import.meta.env.DEV && (url.hostname === 'localhost' || url.hostname === '127.0.0.1')) {
40
- if (isPublicRoute(pathname)) {
41
- authLocals.recordId = null;
42
- return next();
43
- }
44
- // For protected routes, extract or create mock recordId
45
- // Match memberid with trailing slash
46
- const match = pathname.match(/^\/([a-zA-Z0-9-]+)(?:\/|$)/);
47
- authLocals.recordId = match ? match[1] : 'dev-user-123';
48
- return next();
49
- }
50
- // Sanitize path
51
- const safePath = sanitizePath(pathname);
52
- if (!safePath) {
53
- return new Response('Bad Request', { status: 400 });
54
- }
55
- // Public routes - no auth needed
56
- if (isPublicRoute(safePath)) {
57
- authLocals.recordId = null;
58
- return addSecurityHeaders(await next(), nonce);
59
- }
60
- // Protected route - validate session
61
- const internalApiKey = authLocals.runtime?.env?.INTERNAL_API_KEY || import.meta.env.INTERNAL_API_KEY;
62
- if (!internalApiKey) {
63
- console.error('[middleware] CRITICAL: INTERNAL_API_KEY not configured');
64
- return new Response('Internal Server Error', { status: 500 });
65
- }
66
- // URL must have memberid
67
- if (!validateMemberIdInUrl(safePath, null).valid) {
68
- return new Response('Forbidden: URL must include memberid', { status: 403 });
69
- }
70
- // Validate session
71
- const session = await validateSession(request, url.hostname, safePath, internalApiKey);
72
- if (!session.valid) {
73
- return redirect('/login');
74
- }
75
- // Validate memberid matches session
76
- if (!validateMemberIdInUrl(safePath, session.recordId).valid) {
77
- return new Response('Forbidden: Invalid user ID in URL', { status: 403 });
78
- }
79
- authLocals.recordId = session.recordId;
80
- return addSecurityHeaders(await next(), nonce);
81
- });
@@ -1,11 +0,0 @@
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
- /** Sanitize endpoint path (prevents ../ traversal and encoded variants) */
8
- export declare function sanitizeEndpoint(endpoint: string): string | null;
9
- /** Sanitize URL path (prevents ../ traversal and encoded variants) */
10
- export declare function sanitizePath(pathname: string): string | null;
11
- //# sourceMappingURL=security.d.ts.map
@@ -1 +0,0 @@
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"}
@@ -1 +0,0 @@
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"}
File without changes
File without changes