|
8 | 8 | createRemoteJWKSet, |
9 | 9 | exportJWK, |
10 | 10 | type FlattenedJWSInput, |
| 11 | + generateKeyPair, |
11 | 12 | importPKCS8, |
12 | 13 | type JSONWebKeySet, |
13 | 14 | type JWK, |
@@ -71,16 +72,21 @@ export class JwtProvider { |
71 | 72 | * registered so this process can verify its own tokens (refresh tokens, |
72 | 73 | * authorization codes, id_tokens). Public keys are published via `getJwks`. |
73 | 74 | * |
74 | | - * `privateKey` is a PKCS#8 PEM (from env). Additive: realms without a |
75 | | - * signing key keep the HS256 path untouched. |
| 75 | + * `privateKey` is a PKCS#8 PEM (from env). When it is empty/undefined an |
| 76 | + * **ephemeral per-process keypair** is generated so dev/test work with no env |
| 77 | + * key configured — the published JWKS still resolves; tokens just don't |
| 78 | + * survive a restart. Additive: realms without a signing key keep the HS256 |
| 79 | + * path untouched. |
76 | 80 | */ |
77 | 81 | public async setSigningKey( |
78 | 82 | name: string, |
79 | 83 | signing: SigningConfig, |
80 | 84 | ): Promise<void> { |
81 | | - const key = await importPKCS8(signing.privateKey, signing.alg, { |
82 | | - extractable: true, |
83 | | - }); |
| 85 | + const key = signing.privateKey |
| 86 | + ? await importPKCS8(signing.privateKey, signing.alg, { |
| 87 | + extractable: true, |
| 88 | + }) |
| 89 | + : (await generateKeyPair(signing.alg, { extractable: true })).privateKey; |
84 | 90 | const exported = await exportJWK(key); |
85 | 91 | // Strip every private member so the published JWK is public-only. |
86 | 92 | const { d, p, q, dp, dq, qi, ...pub } = exported as Record<string, unknown>; |
@@ -259,7 +265,11 @@ export interface SignerHolder { |
259 | 265 | */ |
260 | 266 | export interface SigningConfig { |
261 | 267 | alg: "EdDSA" | "RS256"; |
262 | | - privateKey: string; |
| 268 | + /** |
| 269 | + * PKCS#8 PEM private key. Empty/undefined → an ephemeral per-process keypair |
| 270 | + * is generated (dev/test convenience; tokens don't survive a restart). |
| 271 | + */ |
| 272 | + privateKey?: string; |
263 | 273 | kid: string; |
264 | 274 | } |
265 | 275 |
|
|
0 commit comments