handy online tools for AT Protocol
boat.kelinci.net
atproto
bluesky
atcute
typescript
solidjs
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};