get your claude code tokens here
1<!doctype html> 2<html> 3 <head> 4 <meta charset="utf-8" /> 5 <meta name="viewport" content="width=device-width, initial-scale=1" /> 6 <title>Anthropic Auth</title> 7 <style> 8 body { 9 font-family: 10 system-ui, 11 -apple-system, 12 Segoe UI, 13 Roboto, 14 Ubuntu, 15 Cantarell, 16 Noto Sans, 17 sans-serif; 18 background: #0f0f10; 19 color: #fff; 20 margin: 0; 21 display: flex; 22 min-height: 100vh; 23 align-items: center; 24 justify-content: center; 25 } 26 .card { 27 background: #1a1a1b; 28 border: 1px solid #2b2b2c; 29 border-radius: 14px; 30 padding: 28px; 31 max-width: 560px; 32 width: 100%; 33 } 34 h1 { 35 margin: 0 0 8px; 36 } 37 p { 38 color: #9aa0a6; 39 } 40 button, 41 a.button { 42 background: linear-gradient(135deg, #ff6b35, #ff8e53); 43 color: #fff; 44 border: none; 45 border-radius: 10px; 46 padding: 12px 16px; 47 font-weight: 600; 48 cursor: pointer; 49 text-decoration: none; 50 display: inline-block; 51 } 52 textarea { 53 width: 100%; 54 min-height: 120px; 55 background: #111; 56 border: 1px solid #2b2b2c; 57 border-radius: 10px; 58 color: #fff; 59 padding: 10px; 60 } 61 .row { 62 margin: 16px 0; 63 } 64 .muted { 65 color: #9aa0a6; 66 } 67 .status { 68 margin-top: 8px; 69 font-size: 14px; 70 } 71 </style> 72 </head> 73 <body> 74 <div class="card"> 75 <h1>Anthropic Authentication</h1> 76 <p class="muted"> 77 Start the OAuth flow, authorize in the new tab, then paste the 78 returned token here. 79 </p> 80 81 <div class="row"> 82 <a 83 id="authlink" 84 class="button" 85 href="#" 86 target="_blank" 87 style="display: none" 88 >Open Anthropic Authorization</a 89 > 90 </div> 91 92 <div class="row"> 93 <label for="code">Authorization code</label> 94 <textarea 95 id="code" 96 placeholder="Paste the exact code shown by Anthropic (not a URL). If it includes a #, keep the part after it too." 97 ></textarea> 98 </div> 99 100 <div class="row"> 101 <button id="complete">Complete Authentication</button> 102 </div> 103 104 <div id="status" class="status"></div> 105 </div> 106 107 <script> 108 let verifier = ""; 109 const statusEl = document.getElementById("status"); 110 111 function setStatus(msg, ok) { 112 statusEl.textContent = msg; 113 statusEl.style.color = ok ? "#34a853" : "#ea4335"; 114 } 115 116 (async () => { 117 setStatus("Preparing authorization...", true); 118 const res = await fetch("/api/auth/start", { method: "POST" }); 119 if (!res.ok) { 120 setStatus("Failed to prepare auth", false); 121 return; 122 } 123 const data = await res.json(); 124 verifier = data.verifier; 125 const a = document.getElementById("authlink"); 126 a.href = data.authUrl; 127 a.style.display = "inline-block"; 128 setStatus( 129 'Ready. Click "Open Authorization" to continue.', 130 true, 131 ); 132 })(); 133 134 const completeBtn = document.getElementById("complete"); 135 document 136 .getElementById("complete") 137 .addEventListener("click", async () => { 138 if (completeBtn.disabled) return; 139 completeBtn.disabled = true; 140 const code = document.getElementById("code").value.trim(); 141 if (!code || !verifier) { 142 setStatus( 143 "Missing code or verifier. Click Start first.", 144 false, 145 ); 146 completeBtn.disabled = false; 147 return; 148 } 149 const res = await fetch("/api/auth/complete", { 150 method: "POST", 151 headers: { "content-type": "application/json" }, 152 body: JSON.stringify({ code, verifier }), 153 }); 154 if (!res.ok) { 155 setStatus("Code exchange failed", false); 156 completeBtn.disabled = false; 157 return; 158 } 159 setStatus("Authenticated! Fetching token...", true); 160 const t = await fetch("/api/token"); 161 if (!t.ok) { 162 setStatus("Could not fetch token", false); 163 completeBtn.disabled = false; 164 return; 165 } 166 const tok = await t.json(); 167 setStatus( 168 "Access token acquired (expires " + 169 new Date(tok.expiresAt * 1000).toLocaleString() + 170 ")", 171 true, 172 ); 173 setTimeout(() => { 174 try { 175 window.close(); 176 } catch {} 177 }, 500); 178 }); 179 </script> 180 </body> 181</html>