11const jose = require ( 'jose' ) ;
2- const crypto = require ( 'crypto' ) ;
2+ const JwksError = require ( './errors/JwksError' ) ;
3+
4+ function resolveAlg ( jwk ) {
5+ if ( jwk . alg ) {
6+ return jwk . alg ;
7+ }
8+
9+ if ( jwk . kty === 'RSA' ) {
10+ return 'RS256' ;
11+ }
12+
13+ if ( jwk . kty === 'EC' ) {
14+ switch ( jwk . crv ) {
15+ case 'P-256' :
16+ return 'ES256' ;
17+ case 'secp256k1' :
18+ return 'ES256K' ;
19+ case 'P-384' :
20+ return 'ES384' ;
21+ case 'P-521' :
22+ return 'ES512' ;
23+ }
24+ }
25+
26+ if ( jwk . kty === 'OKP' ) {
27+ switch ( jwk . crv ) {
28+ case 'Ed25519' :
29+ case 'Ed448' :
30+ return 'EdDSA' ;
31+ }
32+ }
33+
34+ throw new JwksError ( 'Unsupported JWK' ) ;
35+ }
336
437async function retrieveSigningKeys ( jwks ) {
538 const results = [ ] ;
@@ -10,14 +43,23 @@ async function retrieveSigningKeys(jwks) {
1043
1144 for ( const jwk of jwks ) {
1245 try {
13- // The algorithm is actually not used in the Node.js KeyObject-based runtime
14- // passing an arbitrary value here and checking that KeyObject was returned
15- // later
16- const keyObject = await jose . importJWK ( jwk , 'RS256' ) ;
17- if ( ! ( keyObject instanceof crypto . KeyObject ) || keyObject . type !== 'public' ) {
46+ const key = await jose . importJWK ( jwk , resolveAlg ( jwk ) ) ;
47+ if ( key . type !== 'public' ) {
1848 continue ;
1949 }
20- const getSpki = ( ) => keyObject . export ( { format : 'pem' , type : 'spki' } ) ;
50+ let getSpki ;
51+ switch ( key [ Symbol . toStringTag ] ) {
52+ case 'CryptoKey' : {
53+ const spki = await jose . exportSPKI ( key ) ;
54+ getSpki = ( ) => spki ;
55+ break ;
56+ }
57+ case 'KeyObject' :
58+ // Assume legacy Node.js version without the Symbol.toStringTag backported
59+ // Fall through
60+ default :
61+ getSpki = ( ) => key . export ( { format : 'pem' , type : 'spki' } ) ;
62+ }
2163 results . push ( {
2264 get publicKey ( ) { return getSpki ( ) ; } ,
2365 get rsaPublicKey ( ) { return getSpki ( ) ; } ,
0 commit comments