ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto
at master 3.3 kB view raw
1import { Handler, HandlerEvent, HandlerResponse } from "@netlify/functions"; 2import { CONFIG } from "./core/config/constants"; 3 4export const handler: Handler = async ( 5 event: HandlerEvent, 6): Promise<HandlerResponse> => { 7 try { 8 // Get the host that's requesting the metadata 9 // This will be different for production vs preview deploys vs dev --live 10 const requestHost = process.env.DEPLOY_URL 11 ? new URL(process.env.DEPLOY_URL).host 12 : event.headers["x-forwarded-host"] || event.headers.host; 13 14 if (!requestHost) { 15 return { 16 statusCode: 400, 17 headers: { "Content-Type": "application/json" }, 18 body: JSON.stringify({ error: "Missing host header" }), 19 }; 20 } 21 22 // Check if this is a loopback/development request 23 const isLoopback = 24 requestHost.startsWith("127.0.0.1") || 25 requestHost.startsWith("[::1]") || 26 requestHost === "localhost"; 27 28 if (isLoopback) { 29 // For loopback clients, return minimal metadata 30 // NOTE: In practice, the OAuth server won't fetch this because 31 // loopback clients use hardcoded metadata on the server side 32 const appUrl = `http://${requestHost}`; 33 const redirectUri = `${appUrl}/.netlify/functions/oauth-callback`; 34 35 return { 36 statusCode: 200, 37 headers: { 38 "Content-Type": "application/json", 39 "Access-Control-Allow-Origin": "*", 40 }, 41 body: JSON.stringify({ 42 client_id: appUrl, // Just the origin for loopback 43 client_name: "ATlast (Local Dev)", 44 client_uri: appUrl, 45 redirect_uris: [redirectUri], 46 scope: CONFIG.OAUTH_SCOPES, 47 grant_types: ["authorization_code", "refresh_token"], 48 response_types: ["code"], 49 application_type: "web", 50 token_endpoint_auth_method: "none", // No auth for loopback 51 dpop_bound_access_tokens: true, 52 }), 53 }; 54 } 55 56 // Production: Confidential client metadata 57 const redirectUri = `https://${requestHost}/.netlify/functions/oauth-callback`; 58 const appUrl = `https://${requestHost}`; 59 const jwksUri = `https://${requestHost}/.netlify/functions/jwks`; 60 const clientId = `https://${requestHost}/oauth-client-metadata.json`; 61 const logoUri = `https://${requestHost}/favicon.svg`; 62 63 const metadata = { 64 client_id: clientId, 65 client_name: "ATlast", 66 client_uri: appUrl, 67 redirect_uris: [redirectUri], 68 logo_uri: logoUri, 69 scope: CONFIG.OAUTH_SCOPES, 70 grant_types: ["authorization_code", "refresh_token"], 71 response_types: ["code"], 72 application_type: "web", 73 token_endpoint_auth_method: "private_key_jwt", 74 token_endpoint_auth_signing_alg: "ES256", 75 dpop_bound_access_tokens: true, 76 jwks_uri: jwksUri, 77 }; 78 79 return { 80 statusCode: 200, 81 headers: { 82 "Content-Type": "application/json", 83 "Access-Control-Allow-Origin": "*", 84 "Cache-Control": "no-store", 85 }, 86 body: JSON.stringify(metadata), 87 }; 88 } catch (error) { 89 console.error("Client metadata error:", error); 90 return { 91 statusCode: 500, 92 headers: { "Content-Type": "application/json" }, 93 body: JSON.stringify({ error: "Internal server error" }), 94 }; 95 } 96};