This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

at main 6.8 kB View raw
1import { NextRequest, NextResponse } from 'next/server'; 2 3// Configure this route as dynamic to fix static generation issues 4export const dynamic = 'force-dynamic'; 5 6const DEFAULT_AUTH_SERVER = 'https://public.api.bsky.app'; 7 8export async function POST(request: NextRequest) { 9 try { 10 // Parse request body to get PDS endpoint 11 const body = await request.json(); 12 let pdsEndpoint = body.pdsEndpoint || DEFAULT_AUTH_SERVER; 13 14 // CRITICAL FIX: Third-party PDS servers don't implement OAuth endpoints 15 // Always use public.api.bsky.app for OAuth operations 16 let authServer = pdsEndpoint; 17 if (!pdsEndpoint.includes('public.api.bsky.app')) { 18 console.log('[NONCE API] Redirecting to public.api.bsky.app for OAuth on third-party PDS'); 19 authServer = DEFAULT_AUTH_SERVER; 20 } 21 22 // Try to get a nonce from the auth server, not the PDS itself 23 const tokenEndpoint = `${authServer}/oauth/token`; 24 console.log(`[NONCE API] Attempting to get nonce from: ${tokenEndpoint}`); 25 26 // Try multiple methods to get a nonce 27 let nonce = null; 28 29 // Method 1: HEAD request (most efficient) 30 try { 31 console.log(`[NONCE API] Trying HEAD request to ${tokenEndpoint}`); 32 const headResponse = await fetch(tokenEndpoint, { 33 method: 'HEAD', 34 headers: { 35 'Accept': '*/*' 36 } 37 }); 38 39 nonce = headResponse.headers.get('DPoP-Nonce'); 40 if (nonce) { 41 console.log(`[NONCE API] Got nonce via HEAD request: ${nonce}`); 42 } 43 } catch (headError) { 44 console.warn(`[NONCE API] HEAD request failed:`, headError); 45 } 46 47 // Method 2: OPTIONS request if HEAD fails 48 if (!nonce) { 49 try { 50 console.log(`[NONCE API] Trying OPTIONS request to ${tokenEndpoint}`); 51 const optionsResponse = await fetch(tokenEndpoint, { 52 method: 'OPTIONS', 53 headers: { 54 'Accept': '*/*' 55 } 56 }); 57 58 nonce = optionsResponse.headers.get('DPoP-Nonce'); 59 if (nonce) { 60 console.log(`[NONCE API] Got nonce via OPTIONS request: ${nonce}`); 61 } 62 } catch (optionsError) { 63 console.warn(`[NONCE API] OPTIONS request failed:`, optionsError); 64 } 65 } 66 67 // Method 3: POST probe (last resort) 68 if (!nonce) { 69 try { 70 console.log(`[NONCE API] Trying POST probe to ${tokenEndpoint}`); 71 const probeResponse = await fetch(tokenEndpoint, { 72 method: 'POST', 73 headers: { 74 'Content-Type': 'application/x-www-form-urlencoded' 75 }, 76 // Empty body to trigger an error response that might contain a nonce 77 body: new URLSearchParams({}) 78 }); 79 80 nonce = probeResponse.headers.get('DPoP-Nonce'); 81 if (nonce) { 82 console.log(`[NONCE API] Got nonce via POST probe: ${nonce}`); 83 } 84 } catch (probeError) { 85 console.warn(`[NONCE API] POST probe failed:`, probeError); 86 } 87 } 88 89 // If we got a nonce through any method, return it 90 if (nonce) { 91 return NextResponse.json({ nonce }); 92 } 93 94 // If all methods failed, return an error 95 console.log(`[NONCE API] All methods failed to get a nonce from ${tokenEndpoint}`); 96 return NextResponse.json( 97 { error: 'Could not retrieve nonce', endpoint: tokenEndpoint }, 98 { status: 404 } 99 ); 100 } catch (error: any) { 101 console.error('[NONCE API] Nonce retrieval error:', error); 102 return NextResponse.json( 103 { error: 'Nonce retrieval error', message: error.message }, 104 { status: 500 } 105 ); 106 } 107} 108 109// Maintain backward compatibility 110export async function GET() { 111 try { 112 // Use the default Bluesky server 113 const tokenEndpoint = `${DEFAULT_AUTH_SERVER}/oauth/token`; 114 console.log(`[NONCE API] GET: Attempting to get nonce from: ${tokenEndpoint}`); 115 116 // Try multiple methods to get a nonce 117 let nonce = null; 118 119 // Method 1: HEAD request (most efficient) 120 try { 121 console.log(`[NONCE API] GET: Trying HEAD request to ${tokenEndpoint}`); 122 const headResponse = await fetch(tokenEndpoint, { 123 method: 'HEAD', 124 headers: { 125 'Accept': '*/*' 126 } 127 }); 128 129 nonce = headResponse.headers.get('DPoP-Nonce'); 130 if (nonce) { 131 console.log(`[NONCE API] GET: Got nonce via HEAD request: ${nonce}`); 132 } 133 } catch (headError) { 134 console.warn(`[NONCE API] GET: HEAD request failed:`, headError); 135 } 136 137 // Method 2: OPTIONS request if HEAD fails 138 if (!nonce) { 139 try { 140 console.log(`[NONCE API] GET: Trying OPTIONS request to ${tokenEndpoint}`); 141 const optionsResponse = await fetch(tokenEndpoint, { 142 method: 'OPTIONS', 143 headers: { 144 'Accept': '*/*' 145 } 146 }); 147 148 nonce = optionsResponse.headers.get('DPoP-Nonce'); 149 if (nonce) { 150 console.log(`[NONCE API] GET: Got nonce via OPTIONS request: ${nonce}`); 151 } 152 } catch (optionsError) { 153 console.warn(`[NONCE API] GET: OPTIONS request failed:`, optionsError); 154 } 155 } 156 157 // Method 3: POST probe (last resort) 158 if (!nonce) { 159 try { 160 console.log(`[NONCE API] GET: Trying POST probe to ${tokenEndpoint}`); 161 const probeResponse = await fetch(tokenEndpoint, { 162 method: 'POST', 163 headers: { 164 'Content-Type': 'application/x-www-form-urlencoded' 165 }, 166 // Empty body to trigger an error response that might contain a nonce 167 body: new URLSearchParams({}) 168 }); 169 170 nonce = probeResponse.headers.get('DPoP-Nonce'); 171 if (nonce) { 172 console.log(`[NONCE API] GET: Got nonce via POST probe: ${nonce}`); 173 } 174 } catch (probeError) { 175 console.warn(`[NONCE API] GET: POST probe failed:`, probeError); 176 } 177 } 178 179 // If we got a nonce through any method, return it 180 if (nonce) { 181 return NextResponse.json({ nonce }); 182 } 183 184 // If all methods failed, return an error 185 console.log(`[NONCE API] GET: All methods failed to get a nonce from ${tokenEndpoint}`); 186 return NextResponse.json( 187 { error: 'Could not retrieve nonce', endpoint: tokenEndpoint }, 188 { status: 404 } 189 ); 190 } catch (error: any) { 191 console.error('[NONCE API] GET: Nonce retrieval error:', error); 192 return NextResponse.json( 193 { error: 'Nonce retrieval error', message: error.message }, 194 { status: 500 } 195 ); 196 } 197} 198 199// Handle OPTIONS requests for CORS 200export async function OPTIONS() { 201 return new NextResponse(null, { 202 status: 200, 203 headers: { 204 'Access-Control-Allow-Origin': '*', 205 'Access-Control-Allow-Methods': 'GET, OPTIONS', 206 'Access-Control-Allow-Headers': 'Content-Type', 207 }, 208 }); 209}