Configure CORSPlug to work with non white listed urls upon meeting certain crietria

Hey,

We are using CORSPlug in our application, and we have been using it with a whitelist so far, but we want to allow 3rd party entities to access certain endpoints after validation(with a token), from their own website, so they can display the relevant data for them.
How can this be achieved without adding each 3rd party to the whitelist?
I imagine that the easiest would be to use the origin defining option with a function from CORSPlug but without conn it doesn’t help in this situation, since I’d need to get their token somehow and then allow it through.
Or is it possible to make

plug(CORSPlug)

the else path of the token checking mechanism?

I think i can do this by doing CORSPlug.call/2 inside my if
hah i think it just doesnt do anything now

The OPTIONS request won‘t include authentification therefore you cannot use the token to allow cors access. But you could save the origins the client uses and create the whitelist dynamically. You might need to wrap the plug to apply it though.

is it not possible to give a random token to the client, and then they can pass it with their request and check that token? and if that passes then “skip” the cors checking?

i think this would be the easiest:



so based on the given token i could make the cors pass with the url

CORS is not a simple „check“. At least not for state changing request (POST, …). The browser will sent two request, a preflight OPTIONS request to determine if the actual request is allowed and only then the real request. The preflight request won‘t include authentication. It will tell you if the second request will include authentification in a header, but that‘s it. So you cannot rely on authentification alone for allowing CORS requests.

what about if it is only for get requests?

This would suggest even GET requests are no longer simple requests if you add an authentication header to the mix. But even if it was to work I’d personally say it’s not what you want to do. CORS is meant do block access based on origins and not based on authentication. I wouldn’t want to get a CORS request rejected error because my token expired. It should result in a 401 response, because the token isn’t valid.

You might still make the list of origins somewhat dynamic. E.g. in oauth when registering an external application you could add the origin to the list of allowed origins.

so then would you say that this approach(ugly ass example inc) is very much not recommended?
I put the CORSPlug code after the pr into the project, so now it is there as a normal plug
but i can pass conn to my origin deciding function

plug(CORSPlug, origin: &XDEndpoint.Endpoint.testx/1)

  def testx(conn) do
    if "events" in conn.path_info do
      case Enum.find(conn.req_headers, fn {x, _} -> x == "business_token" end) do
        nil ->
          [
            "https://acc-web.XD.com",
            "https://staging-web.XD.com",
            "https://web.XD.com",
            "http://localhost:8080",
            "https://XD.ngrok.io"
          ]

        {_, token} ->
          # check token
          {_, host} = Enum.find(conn.req_headers, fn {x, _} -> x == "host" end)
          host
      end
    else
      [
        "https://acc-web.XD.com",
        "https://staging-web.XD.com",
        "https://web.XD.com",
        "http://localhost:8080",
        "https://XD.ngrok.io"
      ]
    end
  end

This obviously looks like garbage, so just look at it as a proof of concept.
so if we are hitting a path that is potentially can be accessed by 3rd party then we go inside the if if not then we go with the default origins.
then if they sent the required header then we would check the token and if that passes then that host should be allowed, if no header we default to the defaults.

Checking a token for access control purposes is something different than allowing an external origin to connect to your server in the first place. Personally I would keep those two things separate.

As an aside List.keyfind has imho a better api than Enum.find when looking for certain headers.

so you mean, that have a plug earlier in the stack before cors that checks the token and then maybe put something into assigns if it is ok or not?

The other way round, because you need to answer preflight requests, which don’t have the token you want to check. So your cors plug must come before any logic checking tokens.

but if i dont have the url of the incoming 3rd party in the whitelist won’t cors just give a cors error to them?

You need to get the cors origins from elsewhere, not the token. Your server needs to know which origins are allowed not the requests, preflight or not.