@innvoid/getmarket-sdk 0.1.5 → 0.1.6

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/index.d.cts CHANGED
@@ -1,8 +1,36 @@
1
1
  export { CacheProvider, TwoLevelCache, TwoLevelCacheOptions, closeCache, getOrSet, getTwoLevelCache } from './cache/index.cjs';
2
2
  export { AnyHeaders, ClientErrorCode, HttpClientOpts, InternalHttp, UpstreamError, createHttpClient, mapAxiosToUpstreamError, withRequestId, withRequestIdConfig } from './core/index.cjs';
3
- export { HEADER_AUTHORIZATION, HEADER_BRANCH_UID, HEADER_COMPANY_UID, HEADER_EMPLOYEE_UID, HEADER_INTERNAL_API_KEY, HEADER_REQUEST_ID, RequestContext, getRequestContextFromHeaders } from './headers/index.cjs';
4
- export { REQUEST_ID_HEADER, REQUEST_ID_HEADER_ALT, RESPONSE_REQUEST_ID_HEADER, createAuthMiddleware, readRs256PublicKey, sendError, sendOk, verifyBackendJwtRS256 } from './middlewares/index.cjs';
5
- export { A as AuthContext, a as AuthMiddlewareOptions, b as AuthSession, c as AuthSubject, H as HydrateInput, d as HydrateResult, e as Hydrator, T as TokenType } from './types-CRECQuHp.cjs';
3
+ export { HEADER_AUTHORIZATION, HEADER_BRANCH_UID, HEADER_COMPANY_UID, HEADER_EMPLOYEE_UID, HEADER_INTERNAL_API_KEY, HEADER_REQUEST_ID } from './headers/index.cjs';
4
+ export { R as RequestContext, g as getRequestContextFromHeaders } from './parse-C4vk-fmH.cjs';
5
+ export { internalAuth, parseHeaders, requestId, requireAnyPermission, requireAuthContext, requirePermissions, requireRoles, requireRolesOrAnyPermission, sendError, sendOk } from './middlewares/index.cjs';
6
+ import { A as AuthContext, a as AuthMiddlewareOptions } from './types-CRECQuHp.cjs';
7
+ export { b as AuthSession, c as AuthSubject, H as HydrateInput, d as HydrateResult, e as Hydrator, T as TokenType } from './types-CRECQuHp.cjs';
8
+ import { Response, NextFunction } from 'express';
9
+ import { JwtPayload } from 'jsonwebtoken';
6
10
  import 'axios';
7
- import 'express';
8
- import 'jsonwebtoken';
11
+
12
+ declare global {
13
+ namespace Express {
14
+ interface Request {
15
+ auth?: AuthContext;
16
+ }
17
+ }
18
+ }
19
+ /**
20
+ * ✅ Middleware estándar:
21
+ * - Solo Authorization: Bearer
22
+ * - Solo RS256
23
+ * - Cero legacy
24
+ * - Hidrata vía hook (OBLIGATORIO)
25
+ */
26
+ declare function createAuthMiddleware(opts: AuthMiddlewareOptions): (req: any, res: Response, next: NextFunction) => Promise<void | Response<any, Record<string, any>>>;
27
+
28
+ /**
29
+ * ✅ Keys viven en getmarket-stack:
30
+ * - JWT_PUBLIC_KEY_PATH=/run/secrets/jwtRS256.key.pub (recomendado)
31
+ * - fallback env AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY
32
+ */
33
+ declare function readRs256PublicKey(): string;
34
+ declare function verifyBackendJwtRS256(raw: string): JwtPayload;
35
+
36
+ export { AuthContext, AuthMiddlewareOptions, createAuthMiddleware, readRs256PublicKey, verifyBackendJwtRS256 };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,36 @@
1
1
  export { CacheProvider, TwoLevelCache, TwoLevelCacheOptions, closeCache, getOrSet, getTwoLevelCache } from './cache/index.js';
2
2
  export { AnyHeaders, ClientErrorCode, HttpClientOpts, InternalHttp, UpstreamError, createHttpClient, mapAxiosToUpstreamError, withRequestId, withRequestIdConfig } from './core/index.js';
3
- export { HEADER_AUTHORIZATION, HEADER_BRANCH_UID, HEADER_COMPANY_UID, HEADER_EMPLOYEE_UID, HEADER_INTERNAL_API_KEY, HEADER_REQUEST_ID, RequestContext, getRequestContextFromHeaders } from './headers/index.js';
4
- export { REQUEST_ID_HEADER, REQUEST_ID_HEADER_ALT, RESPONSE_REQUEST_ID_HEADER, createAuthMiddleware, readRs256PublicKey, sendError, sendOk, verifyBackendJwtRS256 } from './middlewares/index.js';
5
- export { A as AuthContext, a as AuthMiddlewareOptions, b as AuthSession, c as AuthSubject, H as HydrateInput, d as HydrateResult, e as Hydrator, T as TokenType } from './types-CRECQuHp.js';
3
+ export { HEADER_AUTHORIZATION, HEADER_BRANCH_UID, HEADER_COMPANY_UID, HEADER_EMPLOYEE_UID, HEADER_INTERNAL_API_KEY, HEADER_REQUEST_ID } from './headers/index.js';
4
+ export { R as RequestContext, g as getRequestContextFromHeaders } from './parse-C4vk-fmH.js';
5
+ export { internalAuth, parseHeaders, requestId, requireAnyPermission, requireAuthContext, requirePermissions, requireRoles, requireRolesOrAnyPermission, sendError, sendOk } from './middlewares/index.js';
6
+ import { A as AuthContext, a as AuthMiddlewareOptions } from './types-CRECQuHp.js';
7
+ export { b as AuthSession, c as AuthSubject, H as HydrateInput, d as HydrateResult, e as Hydrator, T as TokenType } from './types-CRECQuHp.js';
8
+ import { Response, NextFunction } from 'express';
9
+ import { JwtPayload } from 'jsonwebtoken';
6
10
  import 'axios';
7
- import 'express';
8
- import 'jsonwebtoken';
11
+
12
+ declare global {
13
+ namespace Express {
14
+ interface Request {
15
+ auth?: AuthContext;
16
+ }
17
+ }
18
+ }
19
+ /**
20
+ * ✅ Middleware estándar:
21
+ * - Solo Authorization: Bearer
22
+ * - Solo RS256
23
+ * - Cero legacy
24
+ * - Hidrata vía hook (OBLIGATORIO)
25
+ */
26
+ declare function createAuthMiddleware(opts: AuthMiddlewareOptions): (req: any, res: Response, next: NextFunction) => Promise<void | Response<any, Record<string, any>>>;
27
+
28
+ /**
29
+ * ✅ Keys viven en getmarket-stack:
30
+ * - JWT_PUBLIC_KEY_PATH=/run/secrets/jwtRS256.key.pub (recomendado)
31
+ * - fallback env AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY
32
+ */
33
+ declare function readRs256PublicKey(): string;
34
+ declare function verifyBackendJwtRS256(raw: string): JwtPayload;
35
+
36
+ export { AuthContext, AuthMiddlewareOptions, createAuthMiddleware, readRs256PublicKey, verifyBackendJwtRS256 };
package/dist/index.js CHANGED
@@ -11,19 +11,21 @@ import {
11
11
  mapAxiosToUpstreamError,
12
12
  withRequestId,
13
13
  withRequestIdConfig
14
- } from "./chunk-RA5PN2F4.js";
14
+ } from "./chunk-OSYBK5AN.js";
15
15
  import {
16
- createAuthMiddleware,
17
- readRs256PublicKey,
16
+ internalAuth,
17
+ parseHeaders,
18
+ requireAnyPermission,
19
+ requireAuthContext,
20
+ requirePermissions,
21
+ requireRoles,
22
+ requireRolesOrAnyPermission,
18
23
  sendError,
19
- sendOk,
20
- verifyBackendJwtRS256
21
- } from "./chunk-A2E3FXYI.js";
24
+ sendOk
25
+ } from "./chunk-JXOLNJ7J.js";
22
26
  import {
23
- REQUEST_ID_HEADER,
24
- REQUEST_ID_HEADER_ALT,
25
- RESPONSE_REQUEST_ID_HEADER
26
- } from "./chunk-OJUNVATQ.js";
27
+ requestId
28
+ } from "./chunk-KJ64O2EG.js";
27
29
  import {
28
30
  HEADER_AUTHORIZATION,
29
31
  HEADER_BRANCH_UID,
@@ -32,7 +34,144 @@ import {
32
34
  HEADER_INTERNAL_API_KEY,
33
35
  HEADER_REQUEST_ID,
34
36
  getRequestContextFromHeaders
35
- } from "./chunk-65HACONF.js";
37
+ } from "./chunk-P2U3MT2E.js";
38
+
39
+ // src/auth/jwt.ts
40
+ import fs from "fs";
41
+ import jwt from "jsonwebtoken";
42
+ function readFileIfExists(path) {
43
+ if (!path) return null;
44
+ try {
45
+ const v = fs.readFileSync(path, "utf8").trim();
46
+ return v.length ? v : null;
47
+ } catch {
48
+ return null;
49
+ }
50
+ }
51
+ function readRs256PublicKey() {
52
+ const fromFile = readFileIfExists(process.env.JWT_PUBLIC_KEY_PATH);
53
+ if (fromFile) return fromFile;
54
+ const fromEnv = String(process.env.AUTH_JWT_PUBLIC_KEY || process.env.AUTH_RSA_PUBLIC_KEY || "").replace(/\\n/g, "\n").trim();
55
+ if (fromEnv) return fromEnv;
56
+ throw new Error("Missing RS256 public key (JWT_PUBLIC_KEY_PATH / AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY)");
57
+ }
58
+ function verifyBackendJwtRS256(raw) {
59
+ const publicKey = readRs256PublicKey();
60
+ const audience = process.env.JWT_AUDIENCE || process.env.AUTH_JWT_AUDIENCE || "getmarket.api";
61
+ const issuer = process.env.JWT_ISSUER || process.env.AUTH_JWT_ISSUER || "getmarket-auth";
62
+ return jwt.verify(raw, publicKey, {
63
+ algorithms: ["RS256"],
64
+ audience,
65
+ issuer
66
+ });
67
+ }
68
+
69
+ // src/auth/middleware.ts
70
+ function getBearerToken(req) {
71
+ const auth = String(req.headers?.authorization || "");
72
+ if (!auth.startsWith("Bearer ")) return null;
73
+ const token = auth.slice(7).trim();
74
+ return token.length ? token : null;
75
+ }
76
+ function normalizeUid(v) {
77
+ const s = String(v ?? "").trim();
78
+ return s.length ? s : null;
79
+ }
80
+ function createAuthMiddleware(opts) {
81
+ const {
82
+ subject,
83
+ allowFirebaseIdToken = false,
84
+ requireSubject = true,
85
+ hydrate
86
+ } = opts;
87
+ return async (req, res, next) => {
88
+ const token = getBearerToken(req);
89
+ if (!token) {
90
+ return res.status(401).json({
91
+ ok: false,
92
+ code: "AUTH_MISSING_TOKEN",
93
+ message: "Missing Authorization Bearer token"
94
+ });
95
+ }
96
+ const headerCtx = req.context || {};
97
+ const company_uid = normalizeUid(headerCtx.company_uid);
98
+ const branch_uid = normalizeUid(headerCtx.branch_uid);
99
+ try {
100
+ const decoded = verifyBackendJwtRS256(token);
101
+ const baseCtx = {
102
+ tokenType: "backend",
103
+ subject,
104
+ company_uid: company_uid ?? void 0,
105
+ branch_uid: branch_uid ?? void 0,
106
+ roles: Array.isArray(decoded?.roles) ? decoded.roles : [],
107
+ permissions: Array.isArray(decoded?.permissions) ? decoded.permissions : [],
108
+ denied_permissions: Array.isArray(decoded?.denied_permissions) ? decoded.denied_permissions : [],
109
+ session: {
110
+ jti: decoded?.jti,
111
+ device_id: decoded?.device_id,
112
+ expires_at: decoded?.exp
113
+ }
114
+ };
115
+ const hydrated = await hydrate({ decoded, req, subject, company_uid, branch_uid });
116
+ Object.assign(baseCtx, hydrated);
117
+ if (requireSubject) {
118
+ if (subject === "employee" && !baseCtx.employee) {
119
+ return res.status(401).json({
120
+ ok: false,
121
+ code: "AUTH_EMPLOYEE_NOT_FOUND",
122
+ message: "Employee not resolved by hydrator"
123
+ });
124
+ }
125
+ if (subject === "customer" && !baseCtx.customer) {
126
+ return res.status(401).json({
127
+ ok: false,
128
+ code: "AUTH_CUSTOMER_NOT_FOUND",
129
+ message: "Customer not resolved by hydrator"
130
+ });
131
+ }
132
+ }
133
+ req.auth = baseCtx;
134
+ return next();
135
+ } catch {
136
+ if (!allowFirebaseIdToken) {
137
+ return res.status(401).json({
138
+ ok: false,
139
+ code: "AUTH_INVALID_TOKEN",
140
+ message: "Invalid or expired token"
141
+ });
142
+ }
143
+ try {
144
+ const { default: admin } = await import("firebase-admin");
145
+ const firebaseDecoded = await admin.auth().verifyIdToken(token);
146
+ if (firebaseDecoded.email && firebaseDecoded.email_verified === false) {
147
+ return res.status(401).json({
148
+ ok: false,
149
+ code: "AUTH_EMAIL_NOT_VERIFIED",
150
+ message: "Email not verified"
151
+ });
152
+ }
153
+ req.auth = {
154
+ tokenType: "backend",
155
+ subject,
156
+ firebase: firebaseDecoded,
157
+ company_uid: company_uid ?? void 0,
158
+ branch_uid: branch_uid ?? void 0,
159
+ companies: [],
160
+ roles: [],
161
+ permissions: [],
162
+ denied_permissions: []
163
+ };
164
+ return next();
165
+ } catch {
166
+ return res.status(401).json({
167
+ ok: false,
168
+ code: "AUTH_INVALID_TOKEN",
169
+ message: "Invalid or expired token"
170
+ });
171
+ }
172
+ }
173
+ };
174
+ }
36
175
  export {
37
176
  HEADER_AUTHORIZATION,
38
177
  HEADER_BRANCH_UID,
@@ -41,9 +180,6 @@ export {
41
180
  HEADER_INTERNAL_API_KEY,
42
181
  HEADER_REQUEST_ID,
43
182
  InternalHttp,
44
- REQUEST_ID_HEADER,
45
- REQUEST_ID_HEADER_ALT,
46
- RESPONSE_REQUEST_ID_HEADER,
47
183
  TwoLevelCache,
48
184
  UpstreamError,
49
185
  closeCache,
@@ -52,8 +188,16 @@ export {
52
188
  getOrSet,
53
189
  getRequestContextFromHeaders,
54
190
  getTwoLevelCache,
191
+ internalAuth,
55
192
  mapAxiosToUpstreamError,
193
+ parseHeaders,
56
194
  readRs256PublicKey,
195
+ requestId,
196
+ requireAnyPermission,
197
+ requireAuthContext,
198
+ requirePermissions,
199
+ requireRoles,
200
+ requireRolesOrAnyPermission,
57
201
  sendError,
58
202
  sendOk,
59
203
  verifyBackendJwtRS256,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
1
+ {"version":3,"sources":["../src/auth/jwt.ts","../src/auth/middleware.ts"],"sourcesContent":["import fs from \"fs\";\nimport jwt, {JwtPayload} from \"jsonwebtoken\";\n\nfunction readFileIfExists(path?: string): string | null {\n if (!path) return null;\n try {\n const v = fs.readFileSync(path, \"utf8\").trim();\n return v.length ? v : null;\n } catch {\n return null;\n }\n}\n\n/**\n * ✅ Keys viven en getmarket-stack:\n * - JWT_PUBLIC_KEY_PATH=/run/secrets/jwtRS256.key.pub (recomendado)\n * - fallback env AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY\n */\nexport function readRs256PublicKey(): string {\n const fromFile = readFileIfExists(process.env.JWT_PUBLIC_KEY_PATH);\n if (fromFile) return fromFile;\n\n const fromEnv = String(process.env.AUTH_JWT_PUBLIC_KEY || process.env.AUTH_RSA_PUBLIC_KEY || \"\")\n .replace(/\\\\n/g, \"\\n\")\n .trim();\n\n if (fromEnv) return fromEnv;\n\n throw new Error(\"Missing RS256 public key (JWT_PUBLIC_KEY_PATH / AUTH_JWT_PUBLIC_KEY / AUTH_RSA_PUBLIC_KEY)\");\n}\n\nexport function verifyBackendJwtRS256(raw: string): JwtPayload {\n const publicKey = readRs256PublicKey();\n\n const audience = process.env.JWT_AUDIENCE || process.env.AUTH_JWT_AUDIENCE || \"getmarket.api\";\n const issuer = process.env.JWT_ISSUER || process.env.AUTH_JWT_ISSUER || \"getmarket-auth\";\n\n // ✅ SOLO RS256\n return jwt.verify(raw, publicKey, {\n algorithms: [\"RS256\"],\n audience,\n issuer,\n }) as JwtPayload;\n}\n","import type {NextFunction, Response} from \"express\";\nimport {verifyBackendJwtRS256} from \"./jwt\";\nimport type {AuthContext, AuthMiddlewareOptions} from \"./types\";\n\ndeclare global {\n namespace Express {\n interface Request {\n auth?: AuthContext;\n }\n }\n}\n\nfunction getBearerToken(req: any): string | null {\n const auth = String(req.headers?.authorization || \"\");\n if (!auth.startsWith(\"Bearer \")) return null;\n const token = auth.slice(7).trim();\n return token.length ? token : null;\n}\n\nfunction normalizeUid(v: any): string | null {\n const s = String(v ?? \"\").trim();\n return s.length ? s : null;\n}\n\n/**\n * ✅ Middleware estándar:\n * - Solo Authorization: Bearer\n * - Solo RS256\n * - Cero legacy\n * - Hidrata vía hook (OBLIGATORIO)\n */\nexport function createAuthMiddleware(opts: AuthMiddlewareOptions) {\n const {\n subject,\n allowFirebaseIdToken = false,\n requireSubject = true,\n hydrate,\n } = opts;\n\n return async (req: any, res: Response, next: NextFunction) => {\n const token = getBearerToken(req);\n if (!token) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_MISSING_TOKEN\",\n message: \"Missing Authorization Bearer token\",\n });\n }\n\n // Contexto desde parseHeaders (SDK) -> req.context\n const headerCtx = (req as any).context || {};\n const company_uid = normalizeUid(headerCtx.company_uid);\n const branch_uid = normalizeUid(headerCtx.branch_uid);\n\n // 1) RS256 backend JWT\n try {\n const decoded: any = verifyBackendJwtRS256(token);\n\n const baseCtx: AuthContext = {\n tokenType: \"backend\",\n subject,\n company_uid: company_uid ?? undefined,\n branch_uid: branch_uid ?? undefined,\n roles: Array.isArray(decoded?.roles) ? decoded.roles : [],\n permissions: Array.isArray(decoded?.permissions) ? decoded.permissions : [],\n denied_permissions: Array.isArray(decoded?.denied_permissions) ? decoded.denied_permissions : [],\n session: {\n jti: decoded?.jti,\n device_id: decoded?.device_id,\n expires_at: decoded?.exp,\n },\n };\n\n // ✅ hydrate obligatorio (cero legacy)\n const hydrated = await hydrate({decoded, req, subject, company_uid, branch_uid});\n Object.assign(baseCtx, hydrated);\n\n if (requireSubject) {\n if (subject === \"employee\" && !baseCtx.employee) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_EMPLOYEE_NOT_FOUND\",\n message: \"Employee not resolved by hydrator\",\n });\n }\n if (subject === \"customer\" && !baseCtx.customer) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_CUSTOMER_NOT_FOUND\",\n message: \"Customer not resolved by hydrator\",\n });\n }\n }\n\n req.auth = baseCtx;\n return next();\n } catch {\n // 2) Firebase opcional (si está habilitado explícitamente)\n if (!allowFirebaseIdToken) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_INVALID_TOKEN\",\n message: \"Invalid or expired token\",\n });\n }\n\n try {\n const {default: admin} = await import(\"firebase-admin\");\n const firebaseDecoded = await admin.auth().verifyIdToken(token);\n\n if (firebaseDecoded.email && firebaseDecoded.email_verified === false) {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_EMAIL_NOT_VERIFIED\",\n message: \"Email not verified\",\n });\n }\n\n req.auth = {\n tokenType: \"backend\",\n subject,\n firebase: firebaseDecoded,\n company_uid: company_uid ?? undefined,\n branch_uid: branch_uid ?? undefined,\n companies: [],\n roles: [],\n permissions: [],\n denied_permissions: [],\n };\n\n return next();\n } catch {\n return res.status(401).json({\n ok: false,\n code: \"AUTH_INVALID_TOKEN\",\n message: \"Invalid or expired token\",\n });\n }\n }\n };\n}\n"],"mappings":"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","names":[]}