/** * Cloudflare Worker for Coves OAuth * Handles client metadata and OAuth callbacks with Android Intent URL support */ export default { async fetch(request) { const url = new URL(request.url); // Serve client-metadata.json if (url.pathname === '/client-metadata.json') { return new Response(JSON.stringify({ client_id: 'https://lingering-darkness-50a6.brettmay0212.workers.dev/client-metadata.json', client_name: 'Coves', client_uri: 'https://lingering-darkness-50a6.brettmay0212.workers.dev/client-metadata.json', redirect_uris: [ 'https://lingering-darkness-50a6.brettmay0212.workers.dev/oauth/callback', 'dev.workers.brettmay0212.lingering-darkness-50a6:/oauth/callback' ], scope: 'atproto transition:generic', grant_types: ['authorization_code', 'refresh_token'], response_types: ['code'], application_type: 'native', token_endpoint_auth_method: 'none', dpop_bound_access_tokens: true }), { headers: { 'Content-Type': 'application/json' } }); } // Handle OAuth callback - redirect to app if (url.pathname === '/oauth/callback') { const params = url.search; // Preserve query params (e.g., ?state=xxx&code=xxx) const userAgent = request.headers.get('User-Agent') || ''; const isAndroid = /Android/i.test(userAgent); // Build the appropriate deep link based on platform let deepLink; if (isAndroid) { // Android: Use Intent URL format (works reliably on all browsers) // Format: intent://path?query#Intent;scheme=SCHEME;package=PACKAGE;end const pathAndQuery = `/oauth/callback${params}`; deepLink = `intent:/${pathAndQuery}#Intent;scheme=dev.workers.brettmay0212.lingering-darkness-50a6;package=social.coves;end`; } else { // iOS: Use standard custom scheme deepLink = `dev.workers.brettmay0212.lingering-darkness-50a6:/oauth/callback${params}`; } return new Response(`