an app to share curated trails sidetrail.app
1

Configure Feed

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

at main 2.6 kB View raw
1import { NextRequest, NextResponse } from "next/server"; 2import { getOAuthClient, getSession } from "@/auth"; 3 4function getBaseUrl(request: NextRequest): string { 5 const host = 6 request.headers.get("x-forwarded-host") || 7 request.headers.get("host") || 8 new URL(request.url).host; 9 const proto = request.headers.get("x-forwarded-proto") || "https"; 10 11 return `${proto}://${host}`; 12} 13 14function isSameOrigin(url: string, baseUrl: string): boolean { 15 try { 16 return new URL(url, baseUrl).origin === new URL(baseUrl).origin; 17 } catch { 18 return false; 19 } 20} 21 22async function handleCallback(request: NextRequest) { 23 const baseUrl = getBaseUrl(request); 24 const params = new URLSearchParams(request.nextUrl.search); 25 26 // Check for OAuth error 27 const error = params.get("error"); 28 if (error) { 29 const description = params.get("error_description") || error; 30 return NextResponse.redirect( 31 new URL(`/login?error=${encodeURIComponent(description)}`, baseUrl), 32 ); 33 } 34 35 try { 36 const client = await getOAuthClient(); 37 38 // Complete the OAuth flow 39 const { session: oauthSession, state } = await client.callback(params); 40 41 // Parse returnUrl from state 42 let returnUrl = "/"; 43 if (state) { 44 try { 45 const parsed = JSON.parse(state); 46 if ( 47 parsed.returnUrl && 48 typeof parsed.returnUrl === "string" && 49 isSameOrigin(parsed.returnUrl, baseUrl) 50 ) { 51 returnUrl = parsed.returnUrl; 52 } 53 } catch { 54 // Ignore parse errors 55 } 56 } 57 58 // Store the DID in our session cookie 59 const session = await getSession(); 60 61 // If already signed in with different account, sign out old one 62 if (session.did && session.did !== oauthSession.did) { 63 try { 64 const oldSession = await client.restore(session.did); 65 if (oldSession) await oldSession.signOut(); 66 } catch { 67 // Ignore errors signing out old session 68 } 69 } 70 71 session.did = oauthSession.did; 72 await session.save(); 73 74 // Redirect to returnUrl: We have ensured the return URL is relative above: 75 const redirectUrl = new URL(returnUrl, baseUrl); 76 return NextResponse.redirect(redirectUrl); 77 } catch (err) { 78 console.error("OAuth callback error:", err); 79 const message = err instanceof Error ? err.message : "Authentication failed"; 80 return NextResponse.redirect(new URL(`/login?error=${encodeURIComponent(message)}`, baseUrl)); 81 } 82} 83 84export async function GET(request: NextRequest) { 85 return handleCallback(request); 86}