Skip to content

Commit e3d8555

Browse files
committed
fix: added missing allowedHeaders in CORS for whitelist domains; removed unnecessary verifyClient in websocket
1 parent 18e674a commit e3d8555

File tree

1 file changed

+34
-16
lines changed

1 file changed

+34
-16
lines changed

indexer/src/kadena-server/server.ts

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,7 @@ const typeDefs = readFileSync(join(__dirname, './config/schema.graphql'), 'utf-8
4141

4242
const KADENA_GRAPHQL_API_PORT = getRequiredEnvString('KADENA_GRAPHQL_API_PORT');
4343

44-
const ALLOWED_ORIGINS = [
45-
getRequiredEnvString('API_GATEWAY_URL'),
46-
getRequiredEnvString('API_KADENA_URL'),
47-
`http://localhost:${KADENA_GRAPHQL_API_PORT}`,
48-
];
44+
const ALLOWED_ORIGINS = [process.env.API_GATEWAY_URL ?? '', process.env.API_KADENA_URL ?? ''];
4945

5046
const validatePaginationParamsPlugin: ApolloServerPlugin = {
5147
requestDidStart: async () => ({
@@ -127,13 +123,16 @@ const ipFilterMiddleware = (req: Request, res: Response, next: NextFunction) =>
127123
const isAllowedOrigin = (origin: string): boolean => {
128124
try {
129125
const originUrl = new URL(origin);
126+
if (originUrl.hostname === 'localhost') return true;
127+
130128
return ALLOWED_ORIGINS.some(allowed => {
131129
const allowedUrl = new URL(allowed);
132130
// Check if it's an exact match
133131
if (originUrl.origin === allowedUrl.origin) return true;
134132
// Check if it's a subdomain (only for kadena.io)
135-
if (allowedUrl.hostname === 'kadena.io' && originUrl.hostname.endsWith('.kadena.io'))
133+
if (allowedUrl.hostname === 'kadena.io' && originUrl.hostname.endsWith('.kadena.io')) {
136134
return true;
135+
}
137136
return false;
138137
});
139138
} catch {
@@ -233,15 +232,6 @@ export async function useKadenaGraphqlServer() {
233232
const wsServer = new WebSocketServer({
234233
server: httpServer,
235234
path: '/graphql',
236-
verifyClient: ({ origin }, callback) => {
237-
if (!origin || origin === 'null') {
238-
return callback(false, 400, 'No origin');
239-
}
240-
if (isAllowedOrigin(origin)) {
241-
return callback(true);
242-
}
243-
return callback(false, 403, 'Forbidden');
244-
},
245235
});
246236

247237
const serverCleanup = useServer(
@@ -282,14 +272,42 @@ export async function useKadenaGraphqlServer() {
282272
}
283273
},
284274
methods: ['POST', 'OPTIONS'],
285-
allowedHeaders: ['Content-Type', 'Authorization'],
275+
allowedHeaders: [
276+
'Content-Type',
277+
'Authorization',
278+
'Accept',
279+
'Origin',
280+
'X-Requested-With',
281+
'Cache-Control',
282+
'Pragma',
283+
],
284+
exposedHeaders: ['Access-Control-Allow-Origin'],
286285
credentials: true,
286+
maxAge: 86400, // 24 hours
287287
}),
288288
expressMiddleware(server, {
289289
context: createGraphqlContext,
290290
}),
291291
);
292292

293+
// Handle OPTIONS requests explicitly
294+
app.options('*', (req: Request, res: Response) => {
295+
const origin = req.headers.origin;
296+
if (origin && isAllowedOrigin(origin)) {
297+
res.setHeader('Access-Control-Allow-Origin', origin);
298+
res.setHeader('Access-Control-Allow-Credentials', 'true');
299+
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
300+
res.setHeader(
301+
'Access-Control-Allow-Headers',
302+
'Content-Type, Authorization, Accept, Origin, X-Requested-With, Cache-Control, Pragma',
303+
);
304+
res.setHeader('Access-Control-Max-Age', '86400');
305+
res.status(204).end();
306+
} else {
307+
res.status(403).end();
308+
}
309+
});
310+
293311
app.post('/new-block', ipFilterMiddleware, async (req, res) => {
294312
const payload = await dispatchInfoSchema.safeParseAsync(req.body);
295313
if (!payload.success) {

0 commit comments

Comments
 (0)