|
20 | 20 | }
|
21 | 21 | }
|
22 | 22 |
|
| 23 | + var DEFAULT_HS_TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ'; |
| 24 | + |
| 25 | + var DEFAULT_RS_TOKEN = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.EkN-DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8jO19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuhtF39yxJPAjUESwxk2J5k_4zM3O-vtd1Ghyo4IbqKKSy6J9mTniYJPenn5-HIirE'; |
| 26 | + |
| 27 | + var DEFAULT_PUBLIC_RSA = "\ |
| 28 | +-----BEGIN PUBLIC KEY-----\n\ |
| 29 | +MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGHFHYLugd\ |
| 30 | +UWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQs\ |
| 31 | +HUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5D\ |
| 32 | +o2kQ+X5xK9cipRgEKwIDAQAB\n\ |
| 33 | +-----END PUBLIC KEY-----\ |
| 34 | + "; |
| 35 | + |
| 36 | + var DEFAULT_PRIVATE_RSA = "\ |
| 37 | +-----BEGIN RSA PRIVATE KEY-----\n\ |
| 38 | +MIICWwIBAAKBgQDdlatRjRjogo3WojgGHFHYLugdUWAY9iR3fy4arWNA1KoS8kVw\ |
| 39 | +33cJibXr8bvwUAUparCwlvdbH6dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW\ |
| 40 | ++jK+xQU9a03GUnKHkkle+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB\ |
| 41 | +AoGAD+onAtVye4ic7VR7V50DF9bOnwRwNXrARcDhq9LWNRrRGElESYYTQ6EbatXS\ |
| 42 | +3MCyjjX2eMhu/aF5YhXBwkppwxg+EOmXeh+MzL7Zh284OuPbkglAaGhV9bb6/5Cp\ |
| 43 | +uGb1esyPbYW+Ty2PC0GSZfIXkXs76jXAu9TOBvD0ybc2YlkCQQDywg2R/7t3Q2OE\ |
| 44 | +2+yo382CLJdrlSLVROWKwb4tb2PjhY4XAwV8d1vy0RenxTB+K5Mu57uVSTHtrMK0\ |
| 45 | +GAtFr833AkEA6avx20OHo61Yela/4k5kQDtjEf1N0LfI+BcWZtxsS3jDM3i1Hp0K\ |
| 46 | +Su5rsCPb8acJo5RO26gGVrfAsDcIXKC+bQJAZZ2XIpsitLyPpuiMOvBbzPavd4gY\ |
| 47 | +6Z8KWrfYzJoI/Q9FuBo6rKwl4BFoToD7WIUS+hpkagwWiz+6zLoX1dbOZwJACmH5\ |
| 48 | +fSSjAkLRi54PKJ8TFUeOP15h9sQzydI8zJU+upvDEKZsZc/UhT/SySDOxQ4G/523\ |
| 49 | +Y0sz/OZtSWcol/UMgQJALesy++GdvoIDLfJX5GBQpuFgFenRiRDabxrE9MNUZ2aP\ |
| 50 | +FaFp+DyAe+b4nDwuJaW2LURbr8AEZga7oQj0uYxcYw==\n\ |
| 51 | + -----END RSA PRIVATE KEY-----\ |
| 52 | + "; |
| 53 | + |
23 | 54 | var codeMirror = CodeMirror;
|
24 | 55 |
|
25 | 56 | function tabHack(instance) {
|
|
48 | 79 | lint: true
|
49 | 80 | });
|
50 | 81 |
|
| 82 | + var algorithmRadios = $('input[name="algorithm"]'), |
| 83 | + lastRestoredToken; |
| 84 | + |
51 | 85 | function setJSONEditorContent(jsonEditor, decodedJSON, selector) {
|
52 | 86 | jsonEditor.off('change', refreshTokenEditor);
|
53 | 87 | if (decodedJSON.result !== null && decodedJSON.result !== undefined) {
|
|
79 | 113 | }
|
80 | 114 |
|
81 | 115 | var decodedHeader = window.decode(parts[0]);
|
| 116 | + |
| 117 | + try { |
| 118 | + selectDetectedAlgorithm(JSON.parse(decodedHeader.result).alg); |
| 119 | + }catch (e){ |
| 120 | + console.log('Invalid header decoded'); |
| 121 | + } |
| 122 | + |
82 | 123 | var selector = $('.jwt-header');
|
83 | 124 | setJSONEditorContent(headerEditor, decodedHeader, selector);
|
84 | 125 | var decodedPayload = window.decode(parts[1]);
|
|
88 | 129 | fireEvent(secretElement);
|
89 | 130 | }
|
90 | 131 |
|
| 132 | + function selectDetectedAlgorithm(alg){ |
| 133 | + |
| 134 | + var $algRadio = $('.algorithm input[value="'+alg+'"]'); |
| 135 | + $algRadio.prop('checked', true); |
| 136 | + |
| 137 | + fireEvent($algRadio.get(0)); |
| 138 | + |
| 139 | + } |
| 140 | + |
91 | 141 | function saveToStorage(jwt) {
|
92 | 142 | // Save last valid jwt value for refresh
|
93 | 143 | localStorage.jwtValue = jwt;
|
|
99 | 149 | }
|
100 | 150 |
|
101 | 151 | function refreshTokenEditor(instance) {
|
| 152 | + |
102 | 153 | tokenEditor.off('change', tokenEditorOnChangeListener);
|
| 154 | + |
| 155 | + var algorithm = getAlgorithm(); |
103 | 156 | var secretElement = document.getElementsByName('secret')[0];
|
104 | 157 | var isBase64EncodedElement = document.getElementsByName('is-base64-encoded')[0];
|
105 |
| - var signResult = window.sign(headerEditor.getValue(), payloadEditor.getValue(), secretElement.value, |
106 |
| - isBase64EncodedElement.checked); |
| 158 | + |
| 159 | + var signResult = window.sign( |
| 160 | + algorithm, |
| 161 | + headerEditor.getValue(), |
| 162 | + payloadEditor.getValue(), |
| 163 | + getKey(algorithm, 'sign'), |
| 164 | + isBase64EncodedElement.checked); |
| 165 | + |
107 | 166 |
|
108 | 167 | if (signResult.error) {
|
109 | 168 | tokenEditor.setValue('');
|
|
158 | 217 | var isBase64EncodedElement = document.getElementsByName('is-base64-encoded')[0];
|
159 | 218 |
|
160 | 219 | function updateSignature () {
|
| 220 | + |
| 221 | + var algorithm = getAlgorithm(); |
161 | 222 | var signatureElement = getFirstElementByClassName('js-signature');
|
162 | 223 | var signatureContainerElement = getFirstElementByClassName('jwt-signature');
|
163 | 224 |
|
|
172 | 233 | } else {
|
173 | 234 | $(signatureContainerElement).removeClass('error');
|
174 | 235 | }
|
175 |
| - var result = window.verify(value, secretElement.value, isBase64); |
| 236 | + |
| 237 | + var result = window.verify( |
| 238 | + algorithm, |
| 239 | + value, |
| 240 | + getKey(algorithm, 'verify'), |
| 241 | + isBase64); |
| 242 | + |
| 243 | + |
176 | 244 | var error = result.error;
|
177 | 245 | result = result.result;
|
178 | 246 | if (!error && result) {
|
|
185 | 253 | signatureElement.innerHTML = '<i class="fa fa-times-circle-o"></i> invalid signature';
|
186 | 254 | }
|
187 | 255 | }
|
| 256 | + |
| 257 | + function getKey(algorithm, action){ |
| 258 | + |
| 259 | + var secretElement = $('input[name="secret"]'), |
| 260 | + privateKeyElement = $('textarea[name="private-key"]'), |
| 261 | + publicKeyElement = $('textarea[name="public-key"]'); |
| 262 | + |
| 263 | + if(algorithm === 'HS256'){ |
| 264 | + return secretElement.val(); |
| 265 | + }else{ |
| 266 | + return action === 'sign' ? privateKeyElement.val() : publicKeyElement.val(); |
| 267 | + } |
| 268 | + |
| 269 | + } |
| 270 | + |
| 271 | + function getAlgorithm(){ |
| 272 | + |
| 273 | + return algorithmRadios.filter(':checked').val(); |
| 274 | + } |
| 275 | + |
| 276 | + function updateAlgorithm () { |
| 277 | + |
| 278 | + var algorithm = algorithmRadios.filter(':checked').val(); |
| 279 | + |
| 280 | + $('.jwt-signature pre') |
| 281 | + .hide() |
| 282 | + .filter('.' + algorithm) |
| 283 | + .show(); |
| 284 | + |
| 285 | + if(getTrimmedValue(tokenEditor) === DEFAULT_HS_TOKEN && |
| 286 | + algorithm === 'RS256'){ |
| 287 | + setDefaultsForRSA(); |
| 288 | + }else if(getTrimmedValue(tokenEditor) === DEFAULT_RS_TOKEN && |
| 289 | + algorithm === 'HS256'){ |
| 290 | + setDefaultsForHMAC(); |
| 291 | + } |
| 292 | + |
| 293 | + } |
| 294 | + |
| 295 | + function setDefaultsForRSA(){ |
| 296 | + |
| 297 | + tokenEditor.setValue(DEFAULT_RS_TOKEN); |
| 298 | + |
| 299 | + $('.jwt-signature textarea[name=public-key]').val(DEFAULT_PUBLIC_RSA); |
| 300 | + $('.jwt-signature textarea[name=private-key]').val(DEFAULT_PRIVATE_RSA); |
| 301 | + } |
| 302 | + |
| 303 | + function setDefaultsForHMAC(){ |
| 304 | + |
| 305 | + tokenEditor.setValue(DEFAULT_HS_TOKEN); |
| 306 | + } |
| 307 | + |
| 308 | + updateAlgorithm(); |
| 309 | + |
| 310 | + algorithmRadios.on('change', function(){ |
| 311 | + updateAlgorithm(); |
| 312 | + updateSignature(); |
| 313 | + }); |
| 314 | + |
| 315 | + $('.jwt-signature textarea').on('change', updateSignature, false); |
| 316 | + $('.jwt-signature textarea').on('keyup', updateSignature, false); |
| 317 | + $('.jwt-signature textarea').on('keyup', validateKey, false); |
| 318 | + |
188 | 319 | secretElement.addEventListener('change', updateSignature, false);
|
189 | 320 | secretElement.addEventListener('keyup', updateSignature, false);
|
190 | 321 | isBase64EncodedElement.addEventListener('change', updateSignature, false);
|
191 | 322 |
|
| 323 | + function validateKey(){ |
| 324 | + |
| 325 | + $textarea = $(this); |
| 326 | + var valid; |
| 327 | + |
| 328 | + if($textarea.prop('name') === 'public-key'){ |
| 329 | + valid = /-----BEGIN (PUBLIC KEY|CERTIFICATE)-----(.|\n)*-----END (PUBLIC KEY|CERTIFICATE)-----/.test($textarea.val()); |
| 330 | + }else{ |
| 331 | + valid = /-----BEGIN RSA PRIVATE KEY-----(.|\n)*-----END RSA PRIVATE KEY-----/.test($textarea.val()); |
| 332 | + } |
| 333 | + |
| 334 | + if (valid) { |
| 335 | + $textarea.removeClass('error'); |
| 336 | + }else{ |
| 337 | + $textarea.addClass('error'); |
| 338 | + } |
| 339 | + |
| 340 | + } |
| 341 | + |
192 | 342 | if (document.location.search) {
|
193 | 343 | var qs = document.location.search.slice(1);
|
194 | 344 | var d = {};
|
|
212 | 362 | }
|
213 | 363 |
|
214 | 364 | loadFromStorage(function (jwt) {
|
| 365 | + |
| 366 | + lastRestoredToken = jwt || DEFAULT_HS_TOKEN; |
| 367 | + |
215 | 368 | tokenEditor.setValue(
|
216 |
| - jwt || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ' |
| 369 | + lastRestoredToken |
217 | 370 | );
|
218 | 371 | });
|
219 | 372 |
|
|
230 | 383 | }, 1000);
|
231 | 384 | }).call(this);
|
232 | 385 |
|
| 386 | + |
| 387 | +//Inizialize bootstrap widgets |
| 388 | +$('[data-toggle="tooltip"]').tooltip(); |
| 389 | + |
| 390 | +// Fetch stargazers count for each repo from GitHub's API |
| 391 | +$('.stars').each(function(idx, element){ |
| 392 | + |
| 393 | + var $el = $(element); |
| 394 | + var repo = $el.attr('data-repo'); |
| 395 | + |
| 396 | + if (repo){ |
| 397 | + $.getJSON('http://api.github.com/repos/' + repo, function(repoData){ |
| 398 | + |
| 399 | + var $count = $('<span>'); |
| 400 | + $count.text(repoData.stargazers_count); |
| 401 | + |
| 402 | + $el.find('i').after($count); |
| 403 | + |
| 404 | + $el.show(); |
| 405 | + }); |
| 406 | + } |
| 407 | +}); |
| 408 | + |
233 | 409 | //CANVAS
|
234 | 410 | // $(function(){
|
235 | 411 | // var canvas = document.querySelector('canvas'),
|
|
0 commit comments