Skip to content

Commit 99c93cb

Browse files
committed
feat: kadena subdomains allowed
1 parent c159c2a commit 99c93cb

File tree

2 files changed

+23
-11
lines changed

2 files changed

+23
-11
lines changed

indexer/.env.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ KADENA_GRAPHQL_API_URL=localhost
88
KADENA_GRAPHQL_API_PORT=3001
99

1010
API_GATEWAY_URL=https://api.mainnet.kadindexer.io
11+
API_KADENA_URL=https://kadena.io
1112

1213
DB_USERNAME=postgres
1314
DB_PASSWORD=password

indexer/src/kadena-server/server.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const KADENA_GRAPHQL_API_PORT = getRequiredEnvString('KADENA_GRAPHQL_API_PORT');
4343

4444
const ALLOWED_ORIGINS = [
4545
getRequiredEnvString('API_GATEWAY_URL'),
46+
getRequiredEnvString('API_KADENA_URL'),
4647
`http://localhost:${KADENA_GRAPHQL_API_PORT}`,
4748
];
4849

@@ -123,6 +124,23 @@ const ipFilterMiddleware = (req: Request, res: Response, next: NextFunction) =>
123124
}
124125
};
125126

127+
const isAllowedOrigin = (origin: string): boolean => {
128+
try {
129+
const originUrl = new URL(origin);
130+
return ALLOWED_ORIGINS.some(allowed => {
131+
const allowedUrl = new URL(allowed);
132+
// Check if it's an exact match
133+
if (originUrl.origin === allowedUrl.origin) return true;
134+
// Check if it's a subdomain (only for kadena.io)
135+
if (allowedUrl.hostname === 'kadena.io' && originUrl.hostname.endsWith('.kadena.io'))
136+
return true;
137+
return false;
138+
});
139+
} catch {
140+
return false;
141+
}
142+
};
143+
126144
export async function useKadenaGraphqlServer() {
127145
const app = express();
128146
const httpServer = http.createServer(app);
@@ -219,15 +237,10 @@ export async function useKadenaGraphqlServer() {
219237
if (!origin || origin === 'null') {
220238
return callback(false, 400, 'No origin');
221239
}
222-
try {
223-
const url = new URL(origin);
224-
if (ALLOWED_ORIGINS.includes(url.origin)) {
225-
return callback(true);
226-
}
227-
return callback(false, 403, 'Forbidden');
228-
} catch {
229-
return callback(false, 400, 'Invalid origin');
240+
if (isAllowedOrigin(origin)) {
241+
return callback(true);
230242
}
243+
return callback(false, 403, 'Forbidden');
231244
},
232245
});
233246

@@ -260,8 +273,7 @@ export async function useKadenaGraphqlServer() {
260273
}
261274

262275
try {
263-
const url = new URL(origin);
264-
if (ALLOWED_ORIGINS.includes(url.origin)) {
276+
if (isAllowedOrigin(origin)) {
265277
return callback(null, true);
266278
}
267279
return callback(new Error(`Origin ${origin} not allowed by CORS`));
@@ -271,7 +283,6 @@ export async function useKadenaGraphqlServer() {
271283
},
272284
methods: ['POST', 'OPTIONS'],
273285
allowedHeaders: ['Content-Type', 'Authorization'],
274-
// When using credentials: true, you cannot use * for Access-Control-Allow-Origin. You must specify exact origins.
275286
credentials: true,
276287
}),
277288
expressMiddleware(server, {

0 commit comments

Comments
 (0)