https://kotlinlang.org logo
#ktor
Title
# ktor
m

mp

07/06/2018, 1:08 PM
What’s your CORS config?
📝 1
1
v

vincent.brule

07/06/2018, 1:09 PM
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

mp

07/06/2018, 1:11 PM
Ah. You need to use the actual hostname, `*`(
anyHost()
) wn’t work. I’ll pull up the spec to explain why, hang on
v

vincent.brule

07/06/2018, 1:12 PM
I need to replace anyHost() by host(“*”) ?
m

mp

07/06/2018, 1:13 PM
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

vincent.brule

07/06/2018, 1:15 PM
Is there a method to totally disable CORS because I have many issue with this ?
m

mp

07/06/2018, 1:15 PM
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

vincent.brule

07/06/2018, 1:16 PM
Yes I understand
I have the impression CORS just are a problem for back end developer...
m

mp

07/06/2018, 1:17 PM
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

vincent.brule

07/06/2018, 1:18 PM
Thanks !
I don’t understand the goal of CORS …? Is it to secure the back ?
m

mp

07/06/2018, 1:19 PM
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

vincent.brule

07/06/2018, 1:20 PM
But if I try without localhost but with an external server I will not have these problems ?
m

mp

07/06/2018, 1:20 PM
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

vincent.brule

07/06/2018, 1:20 PM
Just for your code… What is corsAllowOrigin() ?
m

mp

07/06/2018, 1:20 PM
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

vincent.brule

07/06/2018, 1:21 PM
So the problem is the same origin : localhost ?
I have the same error with your code 😞
m

mp

07/06/2018, 1:23 PM
can you paste the preflight request (from your browser’s dev tools)
v

vincent.brule

07/06/2018, 1:23 PM
Request URL: http://localhost:8080/employee/update/informations Request Method: OPTIONS
this one ?
m

mp

07/06/2018, 1:24 PM
right, but with all the headers
and paste the current CORS config you’re using
v

vincent.brule

07/06/2018, 1:24 PM
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

mp

07/06/2018, 1:25 PM
Remove
anyHost
v

vincent.brule

07/06/2018, 1:25 PM
Yes sorry It was not the good CORS config I edit it
m

mp

07/06/2018, 1:26 PM
also, get / post are already allowed methods by default
v

vincent.brule

07/06/2018, 1:26 PM
I remove it thanks
m

mp

07/06/2018, 1:26 PM
what are the request headers for the preflight?
v

vincent.brule

07/06/2018, 1:27 PM
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

mp

07/06/2018, 1:27 PM
(also probably not an issue here but I see that you’re on ktor 0.9.2; 0.9.3 is current)
v

vincent.brule

07/06/2018, 1:28 PM
Thanks, I update it
m

mp

07/06/2018, 1:28 PM
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

vincent.brule

07/06/2018, 1:30 PM
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

mp

07/06/2018, 1:32 PM
NP, and now you know how to debug CORS 🙂
v

vincent.brule

07/06/2018, 1:33 PM
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

Deactivated User

07/06/2018, 1:34 PM
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

vincent.brule

07/06/2018, 1:36 PM
The problem is not the documentation but my lack of knowledge with CORS 😉
m

mp

07/06/2018, 1:36 PM
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

Deactivated User

07/06/2018, 1:44 PM
🙂 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

mp

07/06/2018, 1:47 PM
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

Deactivated User

07/06/2018, 1:54 PM
@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

mp

07/06/2018, 1:56 PM
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

Deactivated User

07/06/2018, 2:00 PM
I see, thanks for the insights! Maybe an issue to implement custom logic for origin accepting would be nice, yes
m

mp

07/06/2018, 2:00 PM
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
99 Views