@mostajs/auth 2.3.1 → 2.3.3

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.
@@ -24,6 +24,16 @@ export interface CheckRequestParams {
24
24
  }>;
25
25
  /** Allow request through without apikey (legacy / public-mode). */
26
26
  openMode?: boolean;
27
+ /**
28
+ * When no apikey is provided, fall back to a labeled apikey stored in
29
+ * the api_keys table (typically `public-default`). The fallback's
30
+ * permissions still apply — so a public-default key with read-only
31
+ * scope keeps writes blocked even when no key is sent.
32
+ *
33
+ * Use case : MCP endpoint that wants to preserve compat with existing
34
+ * mcp.so / Claude Desktop users who haven't published the apikey yet.
35
+ */
36
+ fallbackPublicLabel?: string;
27
37
  }
28
38
  export interface CheckRequestResult {
29
39
  ok: boolean;
@@ -36,7 +36,7 @@ function pickQuery(q, name) {
36
36
  * (e.g. `if (!result.ok) reply.code(result.status).send(result.body)`).
37
37
  */
38
38
  export async function checkRequest(params) {
39
- const { dialect, headers, query, ip, transport, checks = [], openMode = false } = params;
39
+ const { dialect, headers, query, ip, transport, checks = [], openMode = false, fallbackPublicLabel } = params;
40
40
  // Extract auth identifiers from the request
41
41
  const apiKey = pickHeader(headers, 'x-api-key') ??
42
42
  (pickHeader(headers, 'authorization')?.replace(/^Bearer\s+/i, '').trim() || undefined) ??
@@ -53,8 +53,53 @@ export async function checkRequest(params) {
53
53
  projectName,
54
54
  meta: { ip: resolvedIp },
55
55
  };
56
- // No apikey → either openMode passes through, or 401
56
+ // No apikey → either fallback to a public labeled key, or openMode pass-through, or 401
57
57
  if (!apiKey) {
58
+ // Fallback to a labeled public apikey (e.g. 'public-default') if configured.
59
+ // Looks up the row by label, applies its scope checks. Useful for MCP /
60
+ // demo endpoints that want to preserve compat with users who haven't yet
61
+ // published the public apikey in their config.
62
+ if (fallbackPublicLabel && dialect) {
63
+ try {
64
+ const { getApiKeyRepo, isScopeAuthorized } = await import('@mostajs/api-keys/server');
65
+ const repo = getApiKeyRepo(dialect);
66
+ const fallbackKey = await repo.findOne({ label: fallbackPublicLabel, enabled: true });
67
+ if (fallbackKey) {
68
+ // Normalize legacy permission shape (move projects/operations/transports into scopes)
69
+ const perms = fallbackKey.permissions || {};
70
+ const scopes = { ...(perms.scopes ?? {}) };
71
+ for (const k of ['projects', 'operations', 'transports']) {
72
+ if (perms[k] !== undefined && scopes[k] === undefined)
73
+ scopes[k] = perms[k];
74
+ }
75
+ const normPerms = { ...perms, scopes };
76
+ // Run the same scope checks against the public key's perms
77
+ for (const c of checks) {
78
+ if (!isScopeAuthorized(normPerms, c.scope, c.value)) {
79
+ return {
80
+ ok: false, status: 403,
81
+ body: { status: 'error', error: { code: 'FORBIDDEN',
82
+ message: `Public access not authorized for ${c.scope}="${c.value}"`, } },
83
+ };
84
+ }
85
+ }
86
+ return {
87
+ ok: true, status: 200,
88
+ apikey: fallbackKey,
89
+ ctx: {
90
+ ...baseCtx,
91
+ subscription: fallbackKey.label || fallbackKey.id,
92
+ permissions: normPerms.scopes ?? {},
93
+ accountId: fallbackKey.account || fallbackKey.accountId,
94
+ apikeyId: fallbackKey.id,
95
+ },
96
+ };
97
+ }
98
+ }
99
+ catch {
100
+ // Fallback failed — fall through to standard 401 / openMode
101
+ }
102
+ }
58
103
  if (openMode)
59
104
  return { ok: true, status: 200, ctx: baseCtx };
60
105
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mostajs/auth",
3
- "version": "2.3.1",
3
+ "version": "2.3.3",
4
4
  "description": "Authentication — NextAuth, password hashing, session management",
5
5
  "author": "Dr Hamid MADANI <drmdh@msn.com>",
6
6
  "license": "AGPL-3.0-or-later",
@@ -83,6 +83,11 @@
83
83
  "import": "./dist/lib/apikey-provider.js",
84
84
  "default": "./dist/lib/apikey-provider.js"
85
85
  },
86
+ "./lib/check-request": {
87
+ "types": "./dist/lib/check-request.d.ts",
88
+ "import": "./dist/lib/check-request.js",
89
+ "default": "./dist/lib/check-request.js"
90
+ },
86
91
  "./lib/session-enrichment": {
87
92
  "types": "./dist/lib/session-enrichment.d.ts",
88
93
  "import": "./dist/lib/session-enrichment.js",