What’s your CORS config?
# ktor
m
What’s your CORS config?
📝 1
1
v
I’m really not a pro with the CORS issue. I try this in ktor : install(DefaultHeaders) { //header(HttpHeaders.AccessControlAllowOrigin, “*”) header(HttpHeaders.AccessControlExposeHeaders, “ANNIA_SESSION”) } install(CORS) { anyHost() method(HttpMethod.Get) method(HttpMethod.Post) method(HttpMethod.Put) header(“ANNIA_SESSION”) }
For the get request that works but no with my put request
m
Ah. You need to use the actual hostname, `*`(
anyHost()
) wn’t work. I’ll pull up the spec to explain why, hang on
v
I need to replace anyHost() by host(“*”) ?
m
When responding to a credentialed request, the server must specify an origin in the value of the Access-Control-Allow-Origin header, instead of specifying the “*” wildcard.
No, it should be something like
<http://localhost:3000>
.
Supply the allowed origin as part of your config
BTW since you’re configuring security for browsers, you might be interested in https://bitbucket.org/marshallpierce/ktor-csrf/src/master/ (disclaimer: I’m the author)
👀 1
v
Is there a method to totally disable CORS because I have many issue with this ?
m
You’d have ot disable it from the browser side if you wanted it gone. However, you probably want to figure out the issues sooner rather than later because you don’t want to debug this in production!
v
Yes I understand
I have the impression CORS just are a problem for back end developer...
m
I’d say they make life easier by allowing us to write the backend separately from the frontend 🙂
Here’s my cors config that works great for me.
Copy code
install(CORS) {
            val originUrl = config.corsAllowOrigin()
            val host = if (originUrl.port > 0) {
                "${originUrl.host}:${originUrl.port}"
            } else {
                originUrl.host
            }
            host(host, schemes = listOf(originUrl.protocol))
            allowCredentials = true
            header("X-MI-AntiCSRF")
            method(HttpMethod.Delete)
        }
config.corsAllowOrigin()
is a
URL
which is broken apart as the CORS config API prefers.
v
Thanks !
I don’t understand the goal of CORS …? Is it to secure the back ?
m
The goal is to selectively configure the browser to lift the “same origin policy” that would normally restrict XHR requests.
If js running on
<http://foo.com|foo.com>
tried ot access
<http://bar.com|bar.com>
, browsers won’t let it do that because of security.
v
But if I try without localhost but with an external server I will not have these problems ?
m
However, if
<http://bar.com|bar.com>
is intended to be consumed by websites, it can use CORS to tell the browser “nah it’s fine”
v
Just for your code… What is corsAllowOrigin() ?
m
An external server will behave the same, except that the difference in origin will presumably because the domain is different rather than the port — on local dev, typically everything is
localhost
but with different ports for the http server that serves your JS, your backend API, databse, etc.
That method is on my config class; it returns a URL (e.g.
URL("<http://localhost:3000>")
)
v
So the problem is the same origin : localhost ?
I have the same error with your code 😞
m
can you paste the preflight request (from your browser’s dev tools)
v
Request URL: http://localhost:8080/employee/update/informations Request Method: OPTIONS
this one ?
m
right, but with all the headers
and paste the current CORS config you’re using
v
Access-Control-Expose-Headers: ANNIA_SESSION Connection: keep-alive Content-Length: 0 Date: Fri, 06 Jul 2018 132306 GMT Server: ktor-server-core/0.9.2 ktor-server-core/0.9.2
val originUrl = URL(“http://localhost:3000“) val host = if (originUrl.port > 0) { “${originUrl.host}:${originUrl.port}” } else { originUrl.host } host(host, schemes = listOf(originUrl.protocol)) method(HttpMethod.Delete) method(HttpMethod.Get) method(HttpMethod.Post) method(HttpMethod.Put) header(“ANNIA_SESSION”)
I have a react app on localhost:3000
m
Remove
anyHost
v
Yes sorry It was not the good CORS config I edit it
m
also, get / post are already allowed methods by default
v
I remove it thanks
m
what are the request headers for the preflight?
v
Accept: / Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9 Access-Control-Request-Headers: content-type,headerannia Access-Control-Request-Method: PUT
m
(also probably not an issue here but I see that you’re on ktor 0.9.2; 0.9.3 is current)
v
Thanks, I update it
m
Ah. So, the browser is asking if it’s ok to send
headerannia
but the server cors config is only whitelisting
annia_session
— try changing your cors config to use
headerannia
1
v
Oh I have a variable on my react app name headerannia but the clojure was not respected so my app put the variable name for the header, that’s the problem ! Thank you very much !
Sorry for your time, it was my mistake 😞
m
NP, and now you know how to debug CORS 🙂
v
Yes sure, I already had many problems with CORS and I just manage some trick but now I know how to do thank you !
d
Thanks for helping @mp 🙂 I had a similar issue here: https://github.com/soywiz/realworld-kotlin/blob/master/ktor-backend/src/io/realworld/ktor/Application.kt#L47 I’m going to update the documentation to give some hints on this issue 👍
👍 1
v
The problem is not the documentation but my lack of knowledge with CORS 😉
m
re that config — note that get/post are already enabled, and browsers won’t honor
anyHost()
with credentialed requests
I think struggling with CORS a bit is just one of those things that has to happen every time you start a new project
“Oh right, CORS… *cursing*”
d
🙂 well still if we can provide some hints on which things can go wrong or provide useful resources for troubleshooting, it is always a start I guess
m
Yeah. I think having a real world working setup is a great start
in practice, people are probably going to want
PUT
and
DELETE
, credentials, and a custom header or two
👍 2
d
@mp do you think this is a good snippet for a start, or do you miss something? https://github.com/ktorio/ktor-init-tools/commit/e17f8af685601da2f9a4f303e700115cc9333b3c
m
Unfortunately,
anyHost()
will be rejected by the browser for credentialed requests — see “Credentialed requests and wildcards” in https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS. Must use
host("<http://foo.com>")
form instead
👌 1
Most of the time, services know which host(s) they’re expecting to be serviced by, so this isn’t a problem to configure, but hypothetically it might be an interesting extension point to allow people to plug in their own implementations of host checking
i.e. one that always says whatever Origin is requested is allowed — this would let you allow credentialed requests from everything. An odd use case to be sure, but that’s one that currently can’t be expressed.
d
I see, thanks for the insights! Maybe an issue to implement custom logic for origin accepting would be nice, yes
m
yep if the current CORS configuration could be wrapped up in a pluggable implementation that seems ideal, if there’s a clean way to do that. That way, most users could use the CORS “engine” that’s shipped out of the box, but if you needed to get crazy, you could plug in your own logic
👍 1
(without having to rewrite the pipeline integration that would be the same for everyone)
all problems can be solved with an additional layer of indirection … 😉 Thanks, JVM, for making monomorphic virtual calls cheap!
😆 1
139 Views