handy online tools for AT Protocol boat.kelinci.net
atproto bluesky atcute typescript solidjs
at trunk 69 lines 1.5 kB view raw
1/** 2 * Decodes a JWT token 3 * @param token The token string 4 * @returns JSON object from the token 5 */ 6export const decodeJwt = (token: string): unknown => { 7 const pos = 1; 8 const part = token.split('.')[1]; 9 10 let decoded: string; 11 12 if (typeof part !== 'string') { 13 throw new Error('invalid token: missing part ' + (pos + 1)); 14 } 15 16 try { 17 decoded = base64UrlDecode(part); 18 } catch (e) { 19 throw new Error('invalid token: invalid b64 for part ' + (pos + 1) + ' (' + (e as Error).message + ')'); 20 } 21 22 try { 23 return JSON.parse(decoded); 24 } catch (e) { 25 throw new Error('invalid token: invalid json for part ' + (pos + 1) + ' (' + (e as Error).message + ')'); 26 } 27}; 28 29/** 30 * Decodes a URL-safe Base64 string 31 * @param str URL-safe Base64 that needed to be decoded 32 * @returns The actual string 33 */ 34const base64UrlDecode = (str: string): string => { 35 let output = str.replace(/-/g, '+').replace(/_/g, '/'); 36 37 switch (output.length % 4) { 38 case 0: 39 break; 40 case 2: 41 output += '=='; 42 break; 43 case 3: 44 output += '='; 45 break; 46 default: 47 throw new Error('base64 string is not of the correct length'); 48 } 49 50 try { 51 return b64DecodeUnicode(output); 52 } catch { 53 return atob(output); 54 } 55}; 56 57const b64DecodeUnicode = (str: string): string => { 58 return decodeURIComponent( 59 atob(str).replace(/(.)/g, (_m, p) => { 60 let code = p.charCodeAt(0).toString(16).toUpperCase(); 61 62 if (code.length < 2) { 63 code = '0' + code; 64 } 65 66 return '%' + code; 67 }), 68 ); 69};