postgresdk 0.14.5 → 0.15.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/README.md +6 -6
- package/dist/cli.js +31 -19
- package/dist/index.js +31 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -165,7 +165,7 @@ export default {
|
|
|
165
165
|
// OR
|
|
166
166
|
jwt: { // JWT with multi-service support
|
|
167
167
|
services: [
|
|
168
|
-
{ issuer: "my-app", secret:
|
|
168
|
+
{ issuer: "my-app", secret: "env:JWT_SECRET" } // Use "env:" prefix!
|
|
169
169
|
]
|
|
170
170
|
}
|
|
171
171
|
},
|
|
@@ -296,7 +296,7 @@ export default {
|
|
|
296
296
|
strategy: "jwt-hs256",
|
|
297
297
|
jwt: {
|
|
298
298
|
services: [
|
|
299
|
-
{ issuer: "my-app", secret:
|
|
299
|
+
{ issuer: "my-app", secret: "env:JWT_SECRET" } // Use "env:" prefix!
|
|
300
300
|
],
|
|
301
301
|
audience: "my-api" // Optional
|
|
302
302
|
}
|
|
@@ -310,8 +310,8 @@ export default {
|
|
|
310
310
|
strategy: "jwt-hs256",
|
|
311
311
|
jwt: {
|
|
312
312
|
services: [
|
|
313
|
-
{ issuer: "web-app", secret:
|
|
314
|
-
{ issuer: "mobile-app", secret:
|
|
313
|
+
{ issuer: "web-app", secret: "env:WEB_APP_SECRET" },
|
|
314
|
+
{ issuer: "mobile-app", secret: "env:MOBILE_SECRET" },
|
|
315
315
|
],
|
|
316
316
|
audience: "my-api"
|
|
317
317
|
}
|
|
@@ -352,8 +352,8 @@ export default {
|
|
|
352
352
|
strategy: "jwt-hs256",
|
|
353
353
|
jwt: {
|
|
354
354
|
services: [
|
|
355
|
-
{ issuer: "web-app", secret:
|
|
356
|
-
{ issuer: "analytics-service", secret:
|
|
355
|
+
{ issuer: "web-app", secret: "env:WEB_SECRET" },
|
|
356
|
+
{ issuer: "analytics-service", secret: "env:ANALYTICS_SECRET" }
|
|
357
357
|
],
|
|
358
358
|
audience: "my-api"
|
|
359
359
|
}
|
package/dist/cli.js
CHANGED
|
@@ -3941,10 +3941,37 @@ function emitAuth(cfgAuth) {
|
|
|
3941
3941
|
const apiKeys = cfgAuth?.apiKeys ?? [];
|
|
3942
3942
|
const jwtServices = cfgAuth?.jwt?.services ?? [];
|
|
3943
3943
|
const jwtAudience = cfgAuth?.jwt?.audience ?? undefined;
|
|
3944
|
+
if (strategy === "jwt-hs256" && jwtServices.length > 0) {
|
|
3945
|
+
for (const svc of jwtServices) {
|
|
3946
|
+
if (!svc.secret) {
|
|
3947
|
+
throw new Error(`JWT service "${svc.issuer}" is missing required secret.
|
|
3948
|
+
|
|
3949
|
+
` + `Use the "env:VAR_NAME" pattern in your config:
|
|
3950
|
+
` + ` { issuer: "${svc.issuer}", secret: "env:${svc.issuer.toUpperCase().replace(/-/g, "_")}_SECRET" }`);
|
|
3951
|
+
}
|
|
3952
|
+
if (!svc.secret.startsWith("env:")) {
|
|
3953
|
+
throw new Error(`SECURITY ERROR: JWT secret for "${svc.issuer}" must use "env:VAR_NAME" pattern.
|
|
3954
|
+
|
|
3955
|
+
` + `Found: secret: ${typeof svc.secret === "string" && svc.secret.length > 20 ? '"***REDACTED***"' : JSON.stringify(svc.secret)}
|
|
3956
|
+
|
|
3957
|
+
` + `Hardcoding secrets in config files is a security risk!
|
|
3958
|
+
` + `Instead, use:
|
|
3959
|
+
` + ` { issuer: "${svc.issuer}", secret: "env:${svc.issuer.toUpperCase().replace(/-/g, "_")}_SECRET" }
|
|
3960
|
+
|
|
3961
|
+
` + `Then set the environment variable at runtime.`);
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3944
3965
|
const STRATEGY = JSON.stringify(strategy);
|
|
3945
3966
|
const API_KEY_HEADER = JSON.stringify(apiKeyHeader);
|
|
3946
3967
|
const RAW_API_KEYS = JSON.stringify(apiKeys);
|
|
3947
|
-
const
|
|
3968
|
+
const jwtServicesCode = jwtServices.length === 0 ? "[]" : `[
|
|
3969
|
+
${jwtServices.map((svc) => {
|
|
3970
|
+
const varName = svc.secret.slice(4);
|
|
3971
|
+
return ` { issuer: ${JSON.stringify(svc.issuer)}, secret: process.env.${varName} ?? "" }`;
|
|
3972
|
+
}).join(`,
|
|
3973
|
+
`)}
|
|
3974
|
+
]`;
|
|
3948
3975
|
const JWT_AUDIENCE = jwtAudience === undefined ? "undefined" : JSON.stringify(jwtAudience);
|
|
3949
3976
|
return `/**
|
|
3950
3977
|
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
@@ -3962,7 +3989,7 @@ const STRATEGY = ${STRATEGY} as "none" | "api-key" | "jwt-hs256";
|
|
|
3962
3989
|
const API_KEY_HEADER = ${API_KEY_HEADER} as string;
|
|
3963
3990
|
const RAW_API_KEYS = ${RAW_API_KEYS} as readonly string[];
|
|
3964
3991
|
|
|
3965
|
-
const JWT_SERVICES = ${
|
|
3992
|
+
const JWT_SERVICES = ${jwtServicesCode} as ReadonlyArray<{ issuer: string; secret: string }>;
|
|
3966
3993
|
const JWT_AUDIENCE = ${JWT_AUDIENCE} as string | undefined;
|
|
3967
3994
|
// -------------------------------------
|
|
3968
3995
|
|
|
@@ -3978,15 +4005,6 @@ function expandEnvList(v: string): string[] {
|
|
|
3978
4005
|
return v.split(",").map(s => s.trim()).filter(Boolean);
|
|
3979
4006
|
}
|
|
3980
4007
|
|
|
3981
|
-
function resolveValue(v: string | undefined): string {
|
|
3982
|
-
if (!v) return "";
|
|
3983
|
-
if (v.startsWith("env:")) {
|
|
3984
|
-
const name = v.slice(4);
|
|
3985
|
-
return process.env[name] ?? "";
|
|
3986
|
-
}
|
|
3987
|
-
return v;
|
|
3988
|
-
}
|
|
3989
|
-
|
|
3990
4008
|
function resolveKeys(keys: readonly string[]): string[] {
|
|
3991
4009
|
const out: string[] = [];
|
|
3992
4010
|
for (const k of keys) {
|
|
@@ -4004,12 +4022,6 @@ function resolveKeys(keys: readonly string[]): string[] {
|
|
|
4004
4022
|
|
|
4005
4023
|
const API_KEYS = resolveKeys(RAW_API_KEYS);
|
|
4006
4024
|
|
|
4007
|
-
// Resolve JWT service secrets from env vars if needed
|
|
4008
|
-
const RESOLVED_JWT_SERVICES = JWT_SERVICES.map(svc => ({
|
|
4009
|
-
issuer: svc.issuer,
|
|
4010
|
-
secret: resolveValue(svc.secret)
|
|
4011
|
-
}));
|
|
4012
|
-
|
|
4013
4025
|
// Augment Hono context for DX
|
|
4014
4026
|
declare module "hono" {
|
|
4015
4027
|
interface ContextVariableMap {
|
|
@@ -4052,7 +4064,7 @@ export async function authMiddleware(c: Context, next: Next) {
|
|
|
4052
4064
|
}
|
|
4053
4065
|
const token = m[1];
|
|
4054
4066
|
|
|
4055
|
-
if (!
|
|
4067
|
+
if (!JWT_SERVICES.length) {
|
|
4056
4068
|
log.error("JWT strategy configured but no services defined");
|
|
4057
4069
|
return c.json({ error: "Unauthorized" }, 401);
|
|
4058
4070
|
}
|
|
@@ -4071,7 +4083,7 @@ export async function authMiddleware(c: Context, next: Next) {
|
|
|
4071
4083
|
}
|
|
4072
4084
|
|
|
4073
4085
|
// Find matching service by issuer
|
|
4074
|
-
const service =
|
|
4086
|
+
const service = JWT_SERVICES.find(s => s.issuer === issuer);
|
|
4075
4087
|
if (!service) {
|
|
4076
4088
|
log.error("Unknown JWT issuer:", issuer);
|
|
4077
4089
|
return c.json({ error: "Unauthorized" }, 401);
|
package/dist/index.js
CHANGED
|
@@ -3115,10 +3115,37 @@ function emitAuth(cfgAuth) {
|
|
|
3115
3115
|
const apiKeys = cfgAuth?.apiKeys ?? [];
|
|
3116
3116
|
const jwtServices = cfgAuth?.jwt?.services ?? [];
|
|
3117
3117
|
const jwtAudience = cfgAuth?.jwt?.audience ?? undefined;
|
|
3118
|
+
if (strategy === "jwt-hs256" && jwtServices.length > 0) {
|
|
3119
|
+
for (const svc of jwtServices) {
|
|
3120
|
+
if (!svc.secret) {
|
|
3121
|
+
throw new Error(`JWT service "${svc.issuer}" is missing required secret.
|
|
3122
|
+
|
|
3123
|
+
` + `Use the "env:VAR_NAME" pattern in your config:
|
|
3124
|
+
` + ` { issuer: "${svc.issuer}", secret: "env:${svc.issuer.toUpperCase().replace(/-/g, "_")}_SECRET" }`);
|
|
3125
|
+
}
|
|
3126
|
+
if (!svc.secret.startsWith("env:")) {
|
|
3127
|
+
throw new Error(`SECURITY ERROR: JWT secret for "${svc.issuer}" must use "env:VAR_NAME" pattern.
|
|
3128
|
+
|
|
3129
|
+
` + `Found: secret: ${typeof svc.secret === "string" && svc.secret.length > 20 ? '"***REDACTED***"' : JSON.stringify(svc.secret)}
|
|
3130
|
+
|
|
3131
|
+
` + `Hardcoding secrets in config files is a security risk!
|
|
3132
|
+
` + `Instead, use:
|
|
3133
|
+
` + ` { issuer: "${svc.issuer}", secret: "env:${svc.issuer.toUpperCase().replace(/-/g, "_")}_SECRET" }
|
|
3134
|
+
|
|
3135
|
+
` + `Then set the environment variable at runtime.`);
|
|
3136
|
+
}
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3118
3139
|
const STRATEGY = JSON.stringify(strategy);
|
|
3119
3140
|
const API_KEY_HEADER = JSON.stringify(apiKeyHeader);
|
|
3120
3141
|
const RAW_API_KEYS = JSON.stringify(apiKeys);
|
|
3121
|
-
const
|
|
3142
|
+
const jwtServicesCode = jwtServices.length === 0 ? "[]" : `[
|
|
3143
|
+
${jwtServices.map((svc) => {
|
|
3144
|
+
const varName = svc.secret.slice(4);
|
|
3145
|
+
return ` { issuer: ${JSON.stringify(svc.issuer)}, secret: process.env.${varName} ?? "" }`;
|
|
3146
|
+
}).join(`,
|
|
3147
|
+
`)}
|
|
3148
|
+
]`;
|
|
3122
3149
|
const JWT_AUDIENCE = jwtAudience === undefined ? "undefined" : JSON.stringify(jwtAudience);
|
|
3123
3150
|
return `/**
|
|
3124
3151
|
* AUTO-GENERATED FILE - DO NOT EDIT
|
|
@@ -3136,7 +3163,7 @@ const STRATEGY = ${STRATEGY} as "none" | "api-key" | "jwt-hs256";
|
|
|
3136
3163
|
const API_KEY_HEADER = ${API_KEY_HEADER} as string;
|
|
3137
3164
|
const RAW_API_KEYS = ${RAW_API_KEYS} as readonly string[];
|
|
3138
3165
|
|
|
3139
|
-
const JWT_SERVICES = ${
|
|
3166
|
+
const JWT_SERVICES = ${jwtServicesCode} as ReadonlyArray<{ issuer: string; secret: string }>;
|
|
3140
3167
|
const JWT_AUDIENCE = ${JWT_AUDIENCE} as string | undefined;
|
|
3141
3168
|
// -------------------------------------
|
|
3142
3169
|
|
|
@@ -3152,15 +3179,6 @@ function expandEnvList(v: string): string[] {
|
|
|
3152
3179
|
return v.split(",").map(s => s.trim()).filter(Boolean);
|
|
3153
3180
|
}
|
|
3154
3181
|
|
|
3155
|
-
function resolveValue(v: string | undefined): string {
|
|
3156
|
-
if (!v) return "";
|
|
3157
|
-
if (v.startsWith("env:")) {
|
|
3158
|
-
const name = v.slice(4);
|
|
3159
|
-
return process.env[name] ?? "";
|
|
3160
|
-
}
|
|
3161
|
-
return v;
|
|
3162
|
-
}
|
|
3163
|
-
|
|
3164
3182
|
function resolveKeys(keys: readonly string[]): string[] {
|
|
3165
3183
|
const out: string[] = [];
|
|
3166
3184
|
for (const k of keys) {
|
|
@@ -3178,12 +3196,6 @@ function resolveKeys(keys: readonly string[]): string[] {
|
|
|
3178
3196
|
|
|
3179
3197
|
const API_KEYS = resolveKeys(RAW_API_KEYS);
|
|
3180
3198
|
|
|
3181
|
-
// Resolve JWT service secrets from env vars if needed
|
|
3182
|
-
const RESOLVED_JWT_SERVICES = JWT_SERVICES.map(svc => ({
|
|
3183
|
-
issuer: svc.issuer,
|
|
3184
|
-
secret: resolveValue(svc.secret)
|
|
3185
|
-
}));
|
|
3186
|
-
|
|
3187
3199
|
// Augment Hono context for DX
|
|
3188
3200
|
declare module "hono" {
|
|
3189
3201
|
interface ContextVariableMap {
|
|
@@ -3226,7 +3238,7 @@ export async function authMiddleware(c: Context, next: Next) {
|
|
|
3226
3238
|
}
|
|
3227
3239
|
const token = m[1];
|
|
3228
3240
|
|
|
3229
|
-
if (!
|
|
3241
|
+
if (!JWT_SERVICES.length) {
|
|
3230
3242
|
log.error("JWT strategy configured but no services defined");
|
|
3231
3243
|
return c.json({ error: "Unauthorized" }, 401);
|
|
3232
3244
|
}
|
|
@@ -3245,7 +3257,7 @@ export async function authMiddleware(c: Context, next: Next) {
|
|
|
3245
3257
|
}
|
|
3246
3258
|
|
|
3247
3259
|
// Find matching service by issuer
|
|
3248
|
-
const service =
|
|
3260
|
+
const service = JWT_SERVICES.find(s => s.issuer === issuer);
|
|
3249
3261
|
if (!service) {
|
|
3250
3262
|
log.error("Unknown JWT issuer:", issuer);
|
|
3251
3263
|
return c.json({ error: "Unauthorized" }, 401);
|