|
| 1 | +import { httpGet } from './utils.js'; |
| 2 | + |
| 3 | +function getKeyFromX5c(x5c) { |
| 4 | + if(!x5c) { |
| 5 | + throw new Error('x5c claim not present?'); |
| 6 | + } |
| 7 | + |
| 8 | + if(!(x5c instanceof Array)) { |
| 9 | + x5c = [ x5c ]; |
| 10 | + } |
| 11 | + |
| 12 | + let certChain = ''; |
| 13 | + x5c.forEach(cert => { |
| 14 | + certChain += '-----BEGIN CERTIFICATE-----\n'; |
| 15 | + certChain += cert + '\n'; |
| 16 | + certChain += '-----END CERTIFICATE-----\n'; |
| 17 | + }); |
| 18 | + |
| 19 | + return certChain; |
| 20 | +} |
| 21 | + |
| 22 | +function getKeyFromX5Claims(claims) { |
| 23 | + return new Promise((resolve, reject) => { |
| 24 | + if(claims.x5c) { |
| 25 | + resolve(getKeyFromX5c(claims.x5c)); |
| 26 | + } else if(claims.x5u) { |
| 27 | + resolve(httpGet(claims.x5u).then(getKeyFromX5c)); |
| 28 | + } else { |
| 29 | + reject('x5c or x5u claims not available'); |
| 30 | + } |
| 31 | + }); |
| 32 | +} |
| 33 | + |
| 34 | +function getKeyFromJwkKeySetUrl(kid, url) { |
| 35 | + return httpGet(url).then(data => { |
| 36 | + data = JSON.parse(data); |
| 37 | + |
| 38 | + if(!data || !data.keys || !(data.keys instanceof Array)) { |
| 39 | + throw new Error(`Could not get JWK key set from URL: ${url}`); |
| 40 | + } |
| 41 | + |
| 42 | + for(let i = 0; i < data.keys.length; ++i) { |
| 43 | + const jwk = data.keys[i]; |
| 44 | + if(jwk.kid === kid) { |
| 45 | + return getKeyFromX5Claims(jwk); |
| 46 | + } |
| 47 | + } |
| 48 | + |
| 49 | + throw new Error(`Could not find key with kid ${kid} in URL: ${url}`); |
| 50 | + }); |
| 51 | +} |
| 52 | + |
| 53 | +export function downloadPublicKeyIfPossible(decodedToken) { |
| 54 | + return new Promise((resolve, reject) => { |
| 55 | + const header = decodedToken.header; |
| 56 | + const payload = decodedToken.payload; |
| 57 | + |
| 58 | + if(!header.alg || header.alg.indexOf('HS') === 0) { |
| 59 | + reject(`Unsupported alg: ${header.alg}`); |
| 60 | + return; |
| 61 | + } |
| 62 | + |
| 63 | + if(header.x5c || header.x5u) { |
| 64 | + resolve(getKeyFromX5Claims(header)); |
| 65 | + } else if(header.jku) { |
| 66 | + resolve(getKeyFromJwkKeySetUrl(header.kid, header.jku)); |
| 67 | + } else if(header.jwk) { |
| 68 | + resolve(getKeyFromX5Claims(header.jwk)); |
| 69 | + } else if(header.kid && payload.iss) { |
| 70 | + //Auth0-specific scheme |
| 71 | + const url = payload.iss + '.well-known/jwks.json'; |
| 72 | + resolve(getKeyFromJwkKeySetUrl(header.kid, url)); |
| 73 | + } else { |
| 74 | + reject('No details about key'); |
| 75 | + } |
| 76 | + }); |
| 77 | +} |
0 commit comments