-
Notifications
You must be signed in to change notification settings - Fork 1
/
JWTParser.min.js
1 lines (1 loc) · 5.05 KB
/
JWTParser.min.js
1
var JWTParser=function(){"use strict";function e(e){return atob(e.replace(/-/g,"+").replace(/_/g,"/"))}function r(e){return new Uint8Array([...e].map(e=>e.charCodeAt(0)))}function t(e,r){switch(e[0]){case"H":return"oct"===r;case"R":case"P":return"RSA"===r;case"E":return"EC"===r}}function n(e,r){if("https:"!==new URL(r).protocol)throw new URIError("Keys should be fetched only over HTTPS.");return fetch(r).then(e=>e.json()).then(t=>{if(!Array.isArray(t))throw new TypeError("The specified JWKs is not an Array.");const n=t.find(r=>r.kid===e);if(!n)throw new Error(`The JWKs at ${r} did not contain the key with kid = ${e}.`);return o(n)})}function o(e){if(!e.kid)throw new Error("The key ID (kid) is missing from the JWK.");if(!e.kty)throw new Error("The key type (kty) is missing from the JWK.");if(!e.alg)throw new Error("The key algorithm (alg) is missing from the JWK.");if(!/^(?:EC|RSA|oct)$/.test(e.kty))throw new Error(`Unsupported non-standard key type: ${e.kty}.`);if(!(e.alg in s))throw new Error(`Unsupported key algorithm: ${e.alg}.`);if(!t(e.alg,e.kty))throw new Error(`The key type (${e.kty}) does not match its algorithm (${e.alg}).`);if(!/\bsig\b/.test(e.use))throw new Error("The key does not allow signing/verification.");return e}function i(e){if(!e.usages.includes("verify"))throw new Error("Cannot use this key for signature verification.");const r=e.algorithm,t=Object.values(s).find(e=>e.name===r.name&&e.hash===r.hash.name);if(!t)throw new Error("The key uses a combination of algorithm and hash that isn't listed in JWA.");if(t.namedCurve&&r.namedCurve!==t.namedCurve)throw new Error(`The key's elliptic curve is not the one specified in JWA for ${t.hash}.`);return e}function a(e,r){const t=crypto.subtle.importKey("jwk",e,s[e.alg],!1,["verify"]);return r&&(r[e.kid]=t,t.then(t=>r[e.kid]=t).catch(t=>delete r[e.kid])),t}const s={HS256:{name:"HMAC",hash:"SHA-256"},HS384:{name:"HMAC",hash:"SHA-384"},HS512:{name:"HMAC",hash:"SHA-512"},RS256:{name:"RSASSA-PKCS1-v1_5",hash:"SHA-256"},RS384:{name:"RSASSA-PKCS1-v1_5",hash:"SHA-384"},RS512:{name:"RSASSA-PKCS1-v1_5",hash:"SHA-512"},ES256:{name:"ECDSA",namedCurve:"P-256",hash:"SHA-256"},ES384:{name:"ECDSA",namedCurve:"P-384",hash:"SHA-384"},ES512:{name:"ECDSA",namedCurve:"P-521",hash:"SHA-512"},PS256:{name:"RSA-PSS",saltLength:128,hash:"SHA-256"},PS384:{name:"RSA-PSS",saltLength:384,hash:"SHA-384"},PS512:{name:"RSA-PSS",saltLength:512,hash:"SHA-512"}};class h{constructor(e={}){this.t={};for(const r of["allowInsecure","allowTokenKey","trustKeySetOrigins"])Object.defineProperty(this,r,{value:e[r]||!1,enumerable:!0,writable:!1,configurable:!1})}addKey(e,r){if(e instanceof CryptoKey){if(!r||"string"!=typeof r)throw new TypeError("How would a token reference this key without a key ID?");return this.t[r]=i(e)}return a(o(e),this.t)}async validate(t){if("string"!=typeof t)throw new TypeError("The token is not a string.");const n=t.split(".");switch(n.length){case 2:if(!this.allowInsecure)throw new Error("The token is not signed and we can't have that.");case 3:break;default:throw new Error("The token doesn't have an acceptable number of segments.")}const[o,i,a]=n;try{var h=JSON.parse(e(o))}catch(e){throw new Error("Could not decode JOSE header as base64url-encoded JSON.")}if(!h||"object"!=typeof h||h.typ&&!/^jwt$/i.test(h.typ)||!h.alg)throw new Error("Malformed JOSE header.");if(a){if(!(h.alg in s))throw new Error("Unsupported signing algorithm: "+h.alg);var w=this.o(h)}else if("none"!==h.alg)throw new Error("A signing algorithm is declared but there is no signature.");try{var f=JSON.parse(e(i))}catch(e){throw new Error("Could not decode Claims payload as base64url-encoded JSON.")}if(!f||"object"!=typeof f||f.iss&&"string"!=typeof f.iss||f.sub&&"string"!=typeof f.sub||f.aud&&"string"!=typeof f.aud||f.exp&&"number"!=typeof f.exp||f.nbf&&"number"!=typeof f.nbf||f.iat&&"number"!=typeof f.iat||f.jti&&"string"!=typeof f.jti)throw new Error("Malformed Claims payload.");var c=+h.alg.slice(-3);256===c&&(c=128);try{var u=e(a)}catch(e){throw new Error("Could not decode Signature as base64url.")}if(u.length!==c)throw new Error(`The signature for ${h.alg} should be ${c} bytes long, but it was ${u.length} bytes in the token.`);if(await crypto.subtle.verify(s[h.alg],await w,r(u),r([o,i].join("."))))return f;throw new Error("Signature verification failed.")}async o(e){var r;if(e.kid in this.t)return this.t[e.kid]instanceof Promise?await this.t[e.kid]:this.t[e.kid];if(e.jwk){if(!this.allowTokenKey)throw new Error("The token bears its own verification key, but we don't trust that.");if(r=o(e.jwk),e.kid&&e.kid!==r.kid)throw new Error("The supplied JWK has a different key ID than the JWT.")}else{if(!e.kid||!e.jku)throw new Error("The token doesn't have a JWK and doesn't say where it can be found, so we can't verify it.");if(!this.trustKeySetOrigins||!this.trustKeySetOrigins.test(new URL(e.jku).host))throw new Error(`The token points to a JWK set at ${e.jku}, but we don't trust the network to get them.`);r=await n(e.kid,e.jku)}if(r.alg!==e.alg)throw new Error("The key has a different algorithm than specified by the header.");return await a(r,this.t)}}return h}();