web-security

Darrell 2025-01-16T16:44:33.109959Z

Would someone kindly point out what I’m doing wrong? I’ve tried ring.middleware.cors and jumblerg.middleware.cors but I still get this error in the browser console:

Access to fetch at '' from origin '' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Here is my code (using jumblerg.middleware.cors):
(def app
  (-> app-routes
      wrap-params
      wrap-multipart-params))

(defn -main
  [& _args]
  (wrap-cors app #".*")
  (wrap-cors app identity)
  (println "Starting server on port 3000...")
  (run-jetty app {:port 3000 :join? false}))
Here it is using ring.middleware.cors:
(def app
  (-> app-routes
      (wrap-cors :access-control-allow-origin [#""]
                 :access-control-allow-methods [:get :put :post :delete])
      wrap-params
      wrap-multipart-params))

(defn -main
  [& _args]
  (println "Starting server on port 3000...")
  (run-jetty app {:port 3000 :join? false}))

mloughlin 2025-01-23T12:23:09.914299Z

Are you able to inspect the ring response before and after you use wrap-cors? I have a middleware that only sends the response to tap> that I use for this type of thing

mloughlin 2025-01-22T13:04:56.638149Z

I'm a little late to the party, did you get it working?

mloughlin 2025-01-22T13:06:48.832259Z

I would recommend directly adding your own "Access-Control-Allow-Origin" header with a custom middleware for debugging purposes

Darrell 2025-01-22T15:03:42.499169Z

I actually may have just traced it down last night. It appears to be a problem in the route handler not returning any data. If I hard code it to return data, I don’t get a CORS error, oddly enough.

seancorfield 2025-01-16T17:46:08.749299Z

In that first case, you are throwing away the result of calling wrap-cors, so I assume that was intended for debugging? In the second case, you have wrap-cors in the middle of the middleware -- it needs to be on the very outside of the wrapping.

Darrell 2025-01-16T18:00:49.760849Z

So, for the second case, do you mean this? (apologies for the beginner question, I can move it to #beginners if need be)

(def app
  (-> app-routes
      wrap-params
      wrap-multipart-params
      (wrap-cors :access-control-allow-origin [#""]
                 :access-control-allow-methods [:get :put :post :delete])))

seancorfield 2025-01-16T19:24:06.193439Z

I believe that should work, yes.

seancorfield 2025-01-16T19:26:28.573219Z

Our wrap-cors call at work looks like this:

(let [h (ring-cors/wrap-cors handler
                               :access-control-allow-headers #{"accept"
                                                               "accept-encoding"
                                                               "accept-language"
                                                               "authorization"
                                                               "content-type"
                                                               "origin"}
                               :access-control-allow-methods [:delete :get
                                                              :patch :post :put]
                               ;; 24 hours (in seconds) -- note that only Firefox
                               ;; will honor this; other browsers cap lower!
                               :access-control-max-age "86400"
                               :access-control-allow-origin #".*")]

Darrell 2025-01-16T19:35:29.210129Z

Weird. For some reason it’s still not wrapping the CORS. I tried this:

(def app
  (-> app-routes
      wrap-params
      wrap-multipart-params
      (wrap-cors :access-control-allow-origin [#""]
                 :access-control-allow-methods [:get :put :post :delete])))
And this:
(def app
  (-> app-routes
      wrap-params
      wrap-multipart-params
      (wrap-cors :access-control-allow-headers #{"accept"
                                                 "accept-encoding"
                                                 "accept-language"
                                                 "authorization"
                                                 "content-type"
                                                 "origin"}
                 :access-control-allow-methods [:delete :get :patch :post :put]
                 ;; 24 hours (in seconds) -- note that only Firefox
                 ;; will honor this; other browsers cap lower!
                 :access-control-max-age "86400"
                 :access-control-allow-origin #".*")))

seancorfield 2025-01-16T20:13:58.288199Z

And you get the exact same message with that last setup? Is there any more detail in the JS dev console in the browser?

seancorfield 2025-01-16T20:14:54.398089Z

This is the body of our CORS middleware (the body of that let above) which may help you debug things:

(fn [req]
      (when (= :options (:request-method req))
        ;; ensure all options requests get a fixed name (to prevent leakage
        ;; of the raw URI into New Relic), then ignore the whole transaction
        ;; (options requests are fast because the middleware immediately
        ;; returns a response -- and we'll fully track the actual request)
        (newrelic/set-transaction req "CORS" "/options")
        (omit-transaction))
      (if-let [resp (h req)]
        resp
        (do
          ;; debugging -- I don't believe we should ever fail a preflight check
          ;; but if we do, I want to see the request to figure out _why_!
          (logger/error "CORS FAILED" req)
          (-> (resp/response "preflight failed")
              (resp/status 403)
              (resp/content-type "text/html")))))))

Darrell 2025-01-16T21:16:56.893559Z

Yeah, same message no matter what. This is the full set of errors in the browser console:

Access to fetch at '' from origin '' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
app.js:23 
        
        
       POST  net::ERR_FAILED 500 (Server Error)
(anonymous) @ app.js:23
app.js:49 Error: TypeError: Failed to fetch
    at HTMLFormElement. (app.js:23:32)