Skip to content

Commit fda1e49

Browse files
committed
Fixes #243: when the header specifies kid and the payload iss, attempt
to retrieve public key from .well-known path.
1 parent c280e82 commit fda1e49

File tree

2 files changed

+84
-10
lines changed

2 files changed

+84
-10
lines changed

js/app.js

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,60 @@ FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw==\n\
348348

349349
}
350350

351+
function downloadPublicKeyIfPossible(token, callback) {
352+
var decoded = window.decodeJWT(token);
353+
if(decoded.error) {
354+
console.error(decoded.error);
355+
callback();
356+
return;
357+
}
358+
359+
if(decoded.result.header.alg.indexOf('RS') !== 0 ||
360+
!decoded.result.header.kid ||
361+
!decoded.result.payload.iss) {
362+
callback();
363+
return;
364+
}
365+
366+
var url = decoded.result.payload.iss + '.well-known/jwks.json';
367+
$.get(url, function(data) {
368+
try {
369+
if(!data.keys || !(data.keys instanceof Array)) {
370+
callback();
371+
return;
372+
}
373+
374+
for(var i = 0; i < data.keys.length; ++i) {
375+
if(data.keys[i].kid === decoded.result.header.kid) {
376+
var x5c = data.keys[i].x5c;
377+
if(!(x5c instanceof Array)) {
378+
x5c = [ x5c ];
379+
}
380+
381+
var certChain = '';
382+
x5c.forEach(function(cert) {
383+
certChain += '-----BEGIN CERTIFICATE-----\n';
384+
certChain += cert + '\n';
385+
certChain += '-----END CERTIFICATE-----\n';
386+
});
387+
388+
var publicKeyElement = $('textarea[name="public-key"]');
389+
publicKeyElement.val(certChain);
390+
391+
var privateKeyElement = $('textarea[name="private-key"]');
392+
privateKeyElement.val('');
393+
394+
break;
395+
}
396+
}
397+
398+
callback();
399+
} catch(e) {
400+
console.error(e);
401+
callback();
402+
}
403+
});
404+
}
351405

352406
function tokenEditorOnChangeListener(instance) {
353407
var value = getTrimmedValue(instance);
@@ -367,21 +421,25 @@ FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw==\n\
367421

368422
try {
369423
selectDetectedAlgorithm(JSON.parse(decodedHeader.result).alg);
370-
}catch (e){
424+
} catch (e){
371425
console.error('Invalid header decoded');
372426
}
373427

374-
var selector = $('.jwt-header');
375-
setJSONEditorContent(headerEditor, decodedHeader, selector);
376-
var decodedPayload = window.decode(parts[1]);
377-
selector = $('.jwt-payload');
378-
setJSONEditorContent(payloadEditor, decodedPayload, selector);
428+
downloadPublicKeyIfPossible(value, function() {
379429

380-
fireEvent(secretElement);
430+
var selector = $('.jwt-header');
431+
setJSONEditorContent(headerEditor, decodedHeader, selector);
432+
var decodedPayload = window.decode(parts[1]);
433+
selector = $('.jwt-payload');
434+
setJSONEditorContent(payloadEditor, decodedPayload, selector);
381435

382-
if (window.matchMedia('(min-width: 768px)').matches) {
383-
autoHeightInput();
384-
}
436+
fireEvent(secretElement);
437+
438+
if (window.matchMedia('(min-width: 768px)').matches) {
439+
autoHeightInput();
440+
}
441+
442+
});
385443
}
386444

387445
function selectDetectedAlgorithm(alg){

js/jwt.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,22 @@ window.decode = function (base64json) {
4343
return {result: json, error: error};
4444
};
4545

46+
window.decodeJWT = function(encoded) {
47+
var result = {
48+
header: {},
49+
payload: {}
50+
};
51+
52+
try {
53+
var split = encoded.split('.');
54+
result.header = JSON.parse(window.decode(split[0]).result);
55+
result.payload = JSON.parse(window.decode(split[1]).result);
56+
return { result: result, error: null };
57+
} catch(e) {
58+
return { result: result, error: e };
59+
}
60+
}
61+
4662
window.sign = function (algorithm, header, payload, key, isSecretBase64Encoded) {
4763
var value = '', error = null, headerAsJSON, payloadAsJSON;
4864

0 commit comments

Comments
 (0)