File size: 1,422 Bytes
c0dd699
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import * as jose from 'jose';
import { JwksError } from './errors';

function resolveAlg(jwk: { alg?: string; kty: string; crv?: string }) {
	if (jwk.alg) {
		return jwk.alg;
	}

	if (jwk.kty === 'RSA') {
		return 'RS256';
	}

	if (jwk.kty === 'EC') {
		switch (jwk.crv) {
			case 'P-256':
				return 'ES256';
			case 'secp256k1':
				return 'ES256K';
			case 'P-384':
				return 'ES384';
			case 'P-521':
				return 'ES512';
		}
	}

	if (jwk.kty === 'OKP') {
		switch (jwk.crv) {
			case 'Ed25519':
			case 'Ed448':
				return 'EdDSA';
		}
	}

	throw new JwksError('Unsupported JWK');
}

export async function retrieveSigningKeys(jwks: any[]) {
	const results = [];

	jwks = jwks.filter(({ use }) => use === 'sig' || use === undefined).filter(({ kty }) => kty === 'RSA' || kty === 'EC' || kty === 'OKP');

	for (const jwk of jwks) {
		try {
			const key = await jose.importJWK({ ...jwk, ext: true }, resolveAlg(jwk));
			if ((key as jose.KeyLike).type !== 'public') {
				continue;
			}
			results.push({
				get publicKey() {
					return key;
				},
				get rsaPublicKey() {
					return key;
				},
				getPublicKey() {
					return key;
				},
				...(typeof jwk.kid === 'string' && jwk.kid ? { kid: jwk.kid } : undefined),
				...(typeof jwk.alg === 'string' && jwk.alg ? { alg: jwk.alg } : undefined),
			});
		} catch (err: any) {
			console.error('Error importing JWK:', err);
			continue;
		}
	}
	return results;
}