Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions indexer/.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 22 additions & 11 deletions indexer/src/kadena-server/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
];

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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');
},
});

Expand Down Expand Up @@ -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`));
Expand All @@ -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, {
Expand Down