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>