Description
Problem
- External requests to a Coder app will always fail.
- Workspace apps cannot make requests to each other if they are owned by different users.
Explanation of why
As coder stands today (v2.15.3), we allow cross domain requests between workspace apps of the same user. Meaning you could host a backend webserver on workspace A, and host the frontend on workspace B. As long as the workspaces are owned by the same user, all web requests will function correctly (assuming credentials: "include"
).
This is all handled magically here
Lines 47 to 75 in eb1602b
This allows basic intuitive functionality. By handling this for the user's, we can address some of the nuanced CORS behaviors within Coder. For example, the most common answer on solving CORS is Access-Control-Allow-Origin: *
. This will not work for an application in Coder. All Coder apps require Coder authentication via a cookie, and credentials are not supported if CORS is set to *
.
From | Alice | Bob | ||||
---|---|---|---|---|---|---|
Workspace 1 | Workspace 2 | Workspace 3 | ||||
To | App A | App B | App C | App D | ||
Alice | Workspace 1 | App A | ✅ | ✅* | ✅* | ❌ |
App B | ✅* | ✅ | ✅* | ❌ | ||
Workspace 2 | App C | ✅* | ✅* | ✅ | ❌ | |
Bob | Workspace 3 | App D | ❌ | ❌ | ❌ | ✅ |
🚫 What is the status quo?
The status quo is that Coder manages CORS requests between apps. This approach has generally lead to less customer support tickets on how to handle CORS.
We currently do not allow requests between different users. This does not appear to be because of huge security risk. Subdomain apps are given very limited session tokens that only allow workspace app connections. There is a risk that someone could steal this token and go to other apps by the user, but they cannot interact with other Coder resources.
Solution #1 Solve it in Coder (INCOMPLETE SOLUTION)
We can adjust the table above to include cross user requests. This would expand the security surface by default, which although attacks are limited in escalation, providing this by default seems insecure.
It also does not handle requests external to Coder. External requests must be supported by public shared apps to handle the use cases requested.
🚫 Solution #2 Suggest workarounds (Not always possible)
Instead of allowing cross site requests, the user could deploy a local webserver to proxy requests to the second user's app.
Many frontend servers have this as a feature:
If the web app in question has a backend server, then the backend server can proxy traffic to avoid CORS issues.
❓ Solution #3 Disable CORS handling by Coder
The best option is to disable our custom CORS handling and defer to the workspace app. There is a few ways we could maybe do this:
Disable at the deployment level.
- Adds another server flag 👎
- Breaks the QOL behavior for likely 1 use case 👎
- Easy to switch behavior without any state (db) lookups 👍
Disable at the app level
- Could configure in terraform per app 👍
- Have to do a db lookup on requests or maintain a cache 👎
Disable based on response headers.
Given CORS requests are preflight requests, can we do this? Can we pass the preflight to the workspace app, get the headers. If CORS headers are present, return as is. If they are not, add them to the response? Then we just defer to the app if they configure it themselves. No Coder config necessary.
Final thoughts
When workspace sharing becomes a feature, this use case might show up more.
Implementation notes
The implementation cannot be configured at the workspace, template, or user level. To be configured there, an in memory cache would be required.
The requirements to a solution cannot require a database lookup on each request. That would cause too many database calls for web apps with hundreds of static resources.
The only input information on each request you get from making a request from app A to app B.
- The origin,
https://8002--<agent>--<workspace>--<user_A>--apps.coder.com/
- The request to B,
https://8002--<agent>--<workspace>--<user_B>--apps.coder.com/
with cookies for the app B
Related Links: