sso
sso copied to clipboard
Add configurable CORS support to SSO Proxy
Is your feature request related to a problem? Please describe.
We have a frontend service, behind SSO, running on frontend.sso.example.com
that makes XHR calls to a backend service at backend.sso.example.com
.
While accessing frontend.sso.example.com
as an authorised user from Chrome, the session cookie from frontend.sso.example.com
isn't being forwarded to backend.sso.example.com
because the XHR responses from the SSO proxy have the wildcard (*) Access-Control-Allow-Origin header, which is blocked according to CORS - since the two services are on different origins.
CORs requires the Access-Control-Allow-Origin header on the XHR response to match the origin domain to forward cookies across different origins.
Describe the solution you'd like An option to configure CORS for the proxy through environment variables on the Proxy would be great. Or alternatively, a way to configure CORS individually on services through the upstream config file.
Describe alternatives you've considered I attempted to play around with some of the configuration options currently available, both through the proxy configuration file and through the upstream configuration file, but wasn't able to bypass the issue we faced. In the end, I cloned the project and manually added a CORS library, which we then hosted on our private container registry to use with our services.
Additional context My issues have been on Chrome and I haven't tested on other browsers
I believe I'm also running into this, @adityarkj would it be possible to host that image publicly?
@spencergilbert That would be possible, yes. However, I'd need to touch up the code a little bit before hosting it somewhere, which I might not get time to do for a few weeks at least.
I think I have the same issue. Earlier I tried to do path-based routing and when that didn't work, I went in this direction. How do others solve this problem of having an authentication-protected frontend sending requests to an authentication-protected backend at a different origin? Seems like it would be a common scenario.
I tried to set SESSION_COOKIE_DOMAIN
in sso-auth
and COOKIE_DOMAIN
in the sso-proxy
to a domain that would cover both services, but I couldn't get cookies to be submitted to the backend.
Yeah, I'm trying to get this to work for Grafana and Prometheus, with similar issues.
I came across this issue too because of the exact same scenario. But for the record...
because the XHR responses from the SSO proxy have the wildcard (*) Access-Control-Allow-Origin header
The SSO proxy does not actually set the CORS headers. It is your upstream application that is setting it, and you need to ensure that there is a specific Access-Control-Allow-Origin
defined (e.g. the host for the frontend). Access-Control-Allow-Credentials
must also be set for this backend-frontend scenario to work.
Finally, set the SKIP_AUTH_PREFLIGHT
environment variable to true
for the SSO proxy deployment. Otherwise, OPTIONS
requests to the API will be "redirected" to the SSO proxy, and the preflight will fail because redirects are not allowed. If you do enable this, ensure that the upstream hosts do not expose anything sensitive when provided with an OPTIONS
request.
With the aforementioned in mind, it is very much possible to have both a backend, and frontend proxied through SSO with the frontend being able to talk to the backend.
That said, it would be nice to be able to intercept preflight requests / handle CORS at the proxy level. But, perhaps it may bloat the SSO proxy with features that should probably be handled by more complex API gateways like Kong.
This was a mess for me to figure out;
What I ended up doing which works for us because we control both sides of this is:
- Defined out upstreams as such (using the helm chart)
upstreams:
- service: frontend
default:
from: 'frontend.redacted.tld'
to: 'http://frontend.prod.svc.cluster.local'
- service: backend
default:
from: 'backend.redacted.tld'
to: 'http://backend.prod.svc.cluster.local'
options:
header_overrides:
Access-Control-Allow-Origin: 'https://frontend.redacted.tld'
Access-Control-Allow-Credentials: 'true'
proxy:
extraEnv:
- name: STATSD_HOST
value: localhost
- name: STATSD_PORT
value: '11111'
- name: COOKIE_SECURE
value: 'false' # TODO: This feels like it shouldn't be required. https://github.com/minddocdev/buzzfeed-sso/issues/1
- name: PROVIDER_URL_INTERNAL
value: 'http://buzzfeed-sso-auth.prod.svc.cluster.local'
- name: SKIP_AUTH_PREFLIGHT
value: 'true' # https://github.com/buzzfeed/sso/issues/251
- name: COOKIE_DOMAIN
value: 'redacted.tld'
auth:
domain: 'sso-auth.redacted.tld'
extraEnv:
- name: STATSD_HOST
value: localhost
- name: STATSD_PORT
value: '11111'
- name: COOKIE_SECURE
value: 'false'
- name: SESSION_COOKIE_DOMAIN
value: 'redacted.tld'
-
Removed ALL CORS stuff from our backend (realistically was just a couple lines).
-
Changed our frontend (TypeScript based with Axios to) to set the "withCredentials" attribute:
return axios
.request({
method: "GET",
url: URL,
withCredentials: true,
})
.then(response => {
console.log(`< ${response.status} GET ${URL}`);
// ...
});
This is the only thing that I could get working smoothly and consistently. Biggest problem I ran into on the buzzfeed-sso side was the sso-auth.redacted.tld getting blocked because of CORS... I think if I could set the response headers from that to include Access-Control-Allow-Origin: https://frontend.redacted.tld
I would not have had to edit the frontend.