diff --git a/src/index.ts b/src/index.ts index a57c18c4c..41c0bd644 100644 --- a/src/index.ts +++ b/src/index.ts @@ -374,6 +374,7 @@ export * from './server/description/StorageLocationStrategy'; export * from './server/middleware/AcpHeaderHandler'; export * from './server/middleware/CorsHandler'; export * from './server/middleware/HeaderHandler'; +export * from './server/middleware/JwksHandler'; export * from './server/middleware/StaticAssetHandler'; export * from './server/middleware/WebSocketAdvertiser'; diff --git a/src/server/middleware/JwksHandler.ts b/src/server/middleware/JwksHandler.ts new file mode 100644 index 000000000..ea5c4353a --- /dev/null +++ b/src/server/middleware/JwksHandler.ts @@ -0,0 +1,42 @@ +import { HttpHandler, type HttpHandlerInput } from '../HttpHandler'; +import type { JwkGenerator } from '../../identity/configuration/JwkGenerator'; +import { MethodNotAllowedHttpError } from '../../util/errors/MethodNotAllowedHttpError'; +import { NotImplementedHttpError } from '../../util/errors/NotImplementedHttpError'; + +export class JwksHandler extends HttpHandler { + public constructor( + private readonly path: string, + private readonly generator: JwkGenerator, + ) { + super(); + } + + public async canHandle({ request }: HttpHandlerInput): Promise { + const { method, url } = request; + + if (![ 'GET', 'HEAD' ].includes(method ?? '')) { + throw new MethodNotAllowedHttpError( + method ? [ method ] : undefined, + `Only GET or HEAD requests can target the storage description.`, + ); + } + + if (url !== this.path) { + throw new NotImplementedHttpError(`This handler is not configured for ${url}`); + } + } + + public async handle({ request, response }: HttpHandlerInput): Promise { + const key = await this.generator.getPublicKey(); + + // eslint-disable-next-line ts/naming-convention -- HTTP header + response.writeHead(200, { 'content-type': 'application/json' }); + + if (request.method === 'HEAD') { + response.end(); + return; + } + + response.end(JSON.stringify({ keys: [ Object.assign(key, { kid: 'TODO' }) ]})); + } +}