fix: Store internal JWK as JWKS to be backwards compatible

This commit is contained in:
Joachim Van Herwegen 2023-02-08 14:16:24 +01:00
parent 9a64095205
commit 7fd0b50383
2 changed files with 12 additions and 9 deletions

View File

@ -1,7 +1,7 @@
import { createPublicKey } from 'crypto'; import { createPublicKey } from 'crypto';
import type { KeyObject } from 'crypto'; import type { KeyObject } from 'crypto';
import { exportJWK, generateKeyPair, importJWK } from 'jose'; import { exportJWK, generateKeyPair, importJWK } from 'jose';
import type { AsymmetricSigningAlgorithm } from 'oidc-provider'; import type { JWKS, AsymmetricSigningAlgorithm } from 'oidc-provider';
import type { KeyValueStorage } from '../../storage/keyvalue/KeyValueStorage'; import type { KeyValueStorage } from '../../storage/keyvalue/KeyValueStorage';
import type { AlgJwk, JwkGenerator } from './JwkGenerator'; import type { AlgJwk, JwkGenerator } from './JwkGenerator';
@ -17,12 +17,12 @@ export class CachedJwkGenerator implements JwkGenerator {
public readonly alg: AsymmetricSigningAlgorithm; public readonly alg: AsymmetricSigningAlgorithm;
private readonly key: string; private readonly key: string;
private readonly storage: KeyValueStorage<string, AlgJwk>; private readonly storage: KeyValueStorage<string, JWKS>;
private privateJwk?: AlgJwk; private privateJwk?: AlgJwk;
private publicJwk?: AlgJwk; private publicJwk?: AlgJwk;
public constructor(alg: AsymmetricSigningAlgorithm, storageKey: string, storage: KeyValueStorage<string, AlgJwk>) { public constructor(alg: AsymmetricSigningAlgorithm, storageKey: string, storage: KeyValueStorage<string, JWKS>) {
this.alg = alg; this.alg = alg;
this.key = storageKey; this.key = storageKey;
this.storage = storage; this.storage = storage;
@ -33,10 +33,12 @@ export class CachedJwkGenerator implements JwkGenerator {
return this.privateJwk; return this.privateJwk;
} }
const jwk = await this.storage.get(this.key); // We store in JWKS format for backwards compatibility reasons.
if (jwk) { // If we want to just store the key instead we will need some way to do the migration.
this.privateJwk = jwk; const jwks = await this.storage.get(this.key);
return jwk; if (jwks) {
this.privateJwk = jwks.keys[0] as AlgJwk;
return this.privateJwk;
} }
const { privateKey } = await generateKeyPair(this.alg); const { privateKey } = await generateKeyPair(this.alg);
@ -45,7 +47,7 @@ export class CachedJwkGenerator implements JwkGenerator {
const privateJwk = { ...await exportJWK(privateKey) } as AlgJwk; const privateJwk = { ...await exportJWK(privateKey) } as AlgJwk;
privateJwk.alg = this.alg; privateJwk.alg = this.alg;
await this.storage.set(this.key, privateJwk); await this.storage.set(this.key, { keys: [ privateJwk ]});
this.privateJwk = privateJwk; this.privateJwk = privateJwk;
return privateJwk; return privateJwk;
} }

View File

@ -1,5 +1,6 @@
import { generateKeyPair, importJWK, jwtVerify, SignJWT } from 'jose'; import { generateKeyPair, importJWK, jwtVerify, SignJWT } from 'jose';
import * as jose from 'jose'; import * as jose from 'jose';
import type { JWKS } from 'oidc-provider';
import { CachedJwkGenerator } from '../../../../src/identity/configuration/CachedJwkGenerator'; import { CachedJwkGenerator } from '../../../../src/identity/configuration/CachedJwkGenerator';
import type { AlgJwk } from '../../../../src/identity/configuration/JwkGenerator'; import type { AlgJwk } from '../../../../src/identity/configuration/JwkGenerator';
import type { KeyValueStorage } from '../../../../src/storage/keyvalue/KeyValueStorage'; import type { KeyValueStorage } from '../../../../src/storage/keyvalue/KeyValueStorage';
@ -8,7 +9,7 @@ describe('A CachedJwkGenerator', (): void => {
const alg = 'ES256'; const alg = 'ES256';
const storageKey = 'jwks'; const storageKey = 'jwks';
let storageMap: Map<string, AlgJwk>; let storageMap: Map<string, AlgJwk>;
let storage: jest.Mocked<KeyValueStorage<string, AlgJwk>>; let storage: jest.Mocked<KeyValueStorage<string, JWKS>>;
let generator: CachedJwkGenerator; let generator: CachedJwkGenerator;
beforeEach(async(): Promise<void> => { beforeEach(async(): Promise<void> => {