diff --git a/indexer/.env.template b/indexer/.env.template index 920d7981..62be3523 100644 --- a/indexer/.env.template +++ b/indexer/.env.template @@ -8,6 +8,7 @@ KADENA_GRAPHQL_API_URL=localhost KADENA_GRAPHQL_API_PORT=3001 API_GATEWAY_URL=https://api.mainnet.kadindexer.io +API_KADENA_URL=https://kadena.io DB_USERNAME=postgres DB_PASSWORD=password diff --git a/indexer/src/kadena-server/server.ts b/indexer/src/kadena-server/server.ts index 40b135cc..11c910a1 100644 --- a/indexer/src/kadena-server/server.ts +++ b/indexer/src/kadena-server/server.ts @@ -43,6 +43,7 @@ const KADENA_GRAPHQL_API_PORT = getRequiredEnvString('KADENA_GRAPHQL_API_PORT'); const ALLOWED_ORIGINS = [ getRequiredEnvString('API_GATEWAY_URL'), + getRequiredEnvString('API_KADENA_URL'), `http://localhost:${KADENA_GRAPHQL_API_PORT}`, ]; @@ -123,6 +124,23 @@ const ipFilterMiddleware = (req: Request, res: Response, next: NextFunction) => } }; +const isAllowedOrigin = (origin: string): boolean => { + try { + const originUrl = new URL(origin); + return ALLOWED_ORIGINS.some(allowed => { + const allowedUrl = new URL(allowed); + // Check if it's an exact match + if (originUrl.origin === allowedUrl.origin) return true; + // Check if it's a subdomain (only for kadena.io) + if (allowedUrl.hostname === 'kadena.io' && originUrl.hostname.endsWith('.kadena.io')) + return true; + return false; + }); + } catch { + return false; + } +}; + export async function useKadenaGraphqlServer() { const app = express(); const httpServer = http.createServer(app); @@ -219,15 +237,10 @@ export async function useKadenaGraphqlServer() { if (!origin || origin === 'null') { return callback(false, 400, 'No origin'); } - try { - const url = new URL(origin); - if (ALLOWED_ORIGINS.includes(url.origin)) { - return callback(true); - } - return callback(false, 403, 'Forbidden'); - } catch { - return callback(false, 400, 'Invalid origin'); + if (isAllowedOrigin(origin)) { + return callback(true); } + return callback(false, 403, 'Forbidden'); }, }); @@ -260,8 +273,7 @@ export async function useKadenaGraphqlServer() { } try { - const url = new URL(origin); - if (ALLOWED_ORIGINS.includes(url.origin)) { + if (isAllowedOrigin(origin)) { return callback(null, true); } return callback(new Error(`Origin ${origin} not allowed by CORS`)); @@ -271,7 +283,6 @@ export async function useKadenaGraphqlServer() { }, methods: ['POST', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization'], - // When using credentials: true, you cannot use * for Access-Control-Allow-Origin. You must specify exact origins. credentials: true, }), expressMiddleware(server, {