Skip to content
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

Allow multiple origin domains for CORS #1973

Conversation

claesjohansson
Copy link

This PR references 1774 contributed by @danielvijge and has been rebased on top of next.

Summary

When several domains consume an API, the CORS header Access-Control-Allow-Origin is not as useful, because it only allows one domain, or all domains (with "*"). The specs do not allow for a list of domains. This change works around this by comparing the Origin header to a list of configured domain in the array 'origin_domains'. It tests if the end of the domain matches either ".{domain}" or "//{domain}". Thus, if origins_domain="example.com, example.net", a request from Origin="http://www.example.com" would be allowed, as does a request from Origin="http://example.com". But Origin="http://my-example.com" is not allowed. In this case, no Access-Control-Allow-Origin header is set.
If both origin and origin_domains are configured, origin_domains take precedence over origin.

Full changelog

  • Changes to CORS plugin schema to have extra configuration for origin_domains[]
  • Changes to CORS plugin handler to test for multiple domain and set correct header
  • Changes to test script to test if the correct header is set when the origin domain matches
  • Changes to test script to test if the header remains empty when the origin domain does not match

Issues resolved

Fix #1043

This commit references @danielvijge’s commit eurail@cc7be41 and has been rebased on top of next
@claesjohansson claesjohansson changed the base branch from master to next January 12, 2017 12:52
Copy link
Member

@Tieske Tieske left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx for your contribution. Some comments...

local function configure_origin(ngx, conf)
if conf.origin == nil then
local origin = ngx.req.get_headers()["origin"] or nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The or nil does not make sense here, can be removed

@@ -7,6 +7,7 @@ return {
methods = { type = "array", enum = { "HEAD", "GET", "POST", "PUT", "PATCH", "DELETE" } },
max_age = { type = "number" },
credentials = { type = "boolean", default = false },
preflight_continue = { type = "boolean", default = false }
preflight_continue = { type = "boolean", default = false },
origin_domains = { type = "array" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this array requires validation of its contents (and accompanying tests)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

additionally, not knowing CORS in-depth, shouldn't origin and origin-domains be mutually exclusive?

Claes Johansson added 2 commits January 12, 2017 15:29
…l-allow-origin-response-header) there should be a way to define a list of origins on the Origin request header, but with a note stating "In practice the origin-list-or-null production is more constrained. Rather than allowing a space-separated list of origins, it is either a single origin or the string "null"."
@subnetmarco subnetmarco self-requested a review January 21, 2017 06:07
@subnetmarco
Copy link
Member

I have added some comments on the original #1774

@@ -181,5 +199,27 @@ describe("Plugin: cors (access)", function()
assert.is_nil(res.headers["Access-Control-Allow-Credentials"])
assert.is_nil(res.headers["Access-Control-Max-Age"])
end)
it("sets CORS orgin based on origin host", function()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: "orgin"

local function configure_origin(ngx, conf)
local origin = ngx.req.get_headers()["origin"] or nil
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's only do this in the else branch a couple lines underneath. Also, no need for or nil.

if conf.origin == nil then
ngx.header["Access-Control-Allow-Origin"] = "*"
else
ngx.header["Access-Control-Allow-Origin"] = conf.origin
ngx.header["Vary"] = "Origin"
if origin ~= nil and host_in_domain(origin, conf) then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if origin , no need for ~= nil

@@ -7,12 +7,24 @@ CorsHandler.PRIORITY = 2000

local OPTIONS = "OPTIONS"

local function host_in_domain(domain, conf)
for i, d in ipairs(conf.origin) do
if string.match(domain, '[%.|//]'..d..'$') then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do a couple things here:

@thibaultcha
Copy link
Member

Replaced by #2203 with a new commit on top of yours which fixes the missing requirements. Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants