-
Notifications
You must be signed in to change notification settings - Fork 125
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CORS Configuration for Public API #11512
Conversation
front/config/cors.ts
Outdated
return ALLOWED_ORIGINS.includes(origin as AllowedOriginType); | ||
} | ||
|
||
export const DEV_ORIGIN = "http://localhost:3010" as const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the front plugin url in dev ? In development it may be nice to accept any origin starting with http://localhost (any port)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, happy to change for a startsWith
then.
front/middleware.ts
Outdated
if (isDevelopment() && origin === DEV_ORIGIN) { | ||
response.headers.set("Access-Control-Allow-Origin", DEV_ORIGIN); | ||
response.headers.set("Access-Control-Allow-Credentials", "true"); | ||
} else if (origin && isAllowedOrigin(origin)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
both branches are similar, we can use a single test ( second one with the requested origin )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Merged.
"Access-Control-Allow-Headers", | ||
"Authorization, Content-Type, X-Request-Origin, x-Commit-Hash, X-Dust-Extension-Version" | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
at some point the middleware should return a 403 if the origin is not allowed or if it request a non allowed header in Access-Control-Request-Headers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 ah yeah indeed, when I tried I got a 403, because I was not_authenticated
but let me add a proper error handler for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated. Let me know if this is what you had in mind.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just missing the origin.startsWith(DEV_ORIGIN)
instead of === , but looks good 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's a few comments. Nitpicky but this is high security risk.
I remember we had cors stuff in next config or our infra? Did you clean them up?
Surprised that there isn't a lib for that? When it comes to security a lib from trusted providers is always better than custom code, did you check?
front/middleware.ts
Outdated
response: NextResponse, | ||
request: NextRequest | ||
): NextResponse { | ||
const corsResponse = setCorsHeaders(response, request); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's call it corsErrorResponse
?.toLowerCase(); | ||
|
||
// If this is a preflight request checking headers. | ||
if (request.method === "OPTIONS" && requestHeaders) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If OPTIONS and no header we should 403 as well instead of blanket 200?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding was that an OPTIONS
request without CORS-specific headers is likely a regular HTTP OPTIONS request (checking which HTTP methods are supported). These are valid HTTP requests that should receive a 200 OK with appropriate Allow headers
|
||
response.headers.set( | ||
"Access-Control-Allow-Methods", | ||
"GET, POST, PUT, DELETE, OPTIONS" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we put OPTIONS here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See comment from above.
"content-type", | ||
"x-request-origin", | ||
"x-commit-hash", | ||
"x-dust-extension-version", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also allow a header for hacker one researchers (see our vdp documentation)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, added.
front/middleware.ts
Outdated
// Cannot use helper functions like isDevelopment() in Edge Runtime middleware since they are not | ||
// bundled. Must check NODE_ENV directly. | ||
const isDevOrigin = | ||
process.env.NODE_ENV === "development" && origin === DEV_ORIGIN; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can get rid of DEV_ORIGIN no? Less code is better for security we just allow all in dev
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
I did check for existing libraries, all of them are for expressJS, I found only one for NextJs that did not convince me. Most resources out there will tell you to use the middleware approach for NextJs (example). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This PR implements proper CORS handling for our public API endpoints (
/v1/*
) while maintaining existing development environment CORS support.Context
CORS (Cross-Origin Resource Sharing) is a security feature implemented by browsers that prevents web pages from making requests to a different domain than the one that served the web page. Until now, our public API (
/v1/*
) has been primarily used by:However, as we're building a new Front extension to have Dust directly in the web application, we've discovered that our API wasn't properly handling CORS. This prevented the extension from making requests directly from browser-based JavaScript code.
Problem
When a web page from
front-ext.dust.tt
tries to make a request todust.tt/v1/...
, browsers block the request unless the server explicitly allows it through CORS headers. This is a security measure to prevent malicious websites from making unauthorized requests to our API on behalf of authenticated users.Without proper CORS headers:
Solution
This PR implements proper CORS handling by:
Changes
CORS Configuration
config/cors.ts
file to centralize CORS configurationfront-ext.dust.tt
for productionlocalhost:3010
Middleware Updates
/v1
routessetCorsHeaders()
for public API endpoints with origin validationsetDevCorsHeaders()
for development environmentTechnical Details
The CORS implementation follows security best practices:
*
) origins allowedTests
Risk
Deploy Plan