A community based topic aggregation platform built on atproto
1<!DOCTYPE html> 2<html> 3<head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1"> 6 <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'unsafe-inline'; style-src 'unsafe-inline'"> 7 <title>Authorization Successful - Coves</title> 8 <style> 9 body { 10 font-family: system-ui, -apple-system, sans-serif; 11 display: flex; 12 align-items: center; 13 justify-content: center; 14 min-height: 100vh; 15 margin: 0; 16 background: #f5f5f5; 17 } 18 .container { 19 text-align: center; 20 padding: 2rem; 21 background: white; 22 border-radius: 8px; 23 box-shadow: 0 2px 8px rgba(0,0,0,0.1); 24 max-width: 400px; 25 } 26 .success { color: #22c55e; font-size: 3rem; margin-bottom: 1rem; } 27 h1 { margin: 0 0 0.5rem; color: #1f2937; font-size: 1.5rem; } 28 p { color: #6b7280; margin: 0.5rem 0; } 29 a { 30 display: inline-block; 31 margin-top: 1rem; 32 padding: 0.75rem 1.5rem; 33 background: #3b82f6; 34 color: white; 35 text-decoration: none; 36 border-radius: 6px; 37 font-weight: 500; 38 } 39 a:hover { background: #2563eb; } 40 </style> 41</head> 42<body> 43 <div class="container"> 44 <div class="success"></div> 45 <h1>Authorization Successful!</h1> 46 <p id="status">Returning to Coves...</p> 47 <a href="#" id="manualLink">Open Coves</a> 48 </div> 49 <script> 50 (function() { 51 // Parse and sanitize query params - only allow expected OAuth parameters 52 const urlParams = new URLSearchParams(window.location.search); 53 const safeParams = new URLSearchParams(); 54 55 // Whitelist only expected OAuth callback parameters 56 const code = urlParams.get('code'); 57 const state = urlParams.get('state'); 58 const error = urlParams.get('error'); 59 const errorDescription = urlParams.get('error_description'); 60 const iss = urlParams.get('iss'); 61 62 if (code) safeParams.set('code', code); 63 if (state) safeParams.set('state', state); 64 if (error) safeParams.set('error', error); 65 if (errorDescription) safeParams.set('error_description', errorDescription); 66 if (iss) safeParams.set('iss', iss); 67 68 const sanitizedQuery = safeParams.toString() ? '?' + safeParams.toString() : ''; 69 70 const userAgent = navigator.userAgent || ''; 71 const isAndroid = /Android/i.test(userAgent); 72 73 // Build deep link based on platform 74 let deepLink; 75 if (isAndroid) { 76 // Android: Intent URL format 77 const pathAndQuery = '/oauth/callback' + sanitizedQuery; 78 deepLink = 'intent:/' + pathAndQuery + '#Intent;scheme=social.coves;package=social.coves;end'; 79 } else { 80 // iOS: Custom scheme 81 deepLink = 'social.coves:/oauth/callback' + sanitizedQuery; 82 } 83 84 // Update manual link 85 document.getElementById('manualLink').href = deepLink; 86 87 // Attempt automatic redirect 88 window.location.href = deepLink; 89 90 // Update status after 2 seconds if redirect didn't work 91 setTimeout(function() { 92 document.getElementById('status').textContent = 'Click the button above to continue'; 93 }, 2000); 94 })(); 95 </script> 96</body> 97</html>