Allow cross origin requests only for message bus

I was able to make it work using the second method (Custom middleware to enable cors only for Message Bus requests). The issue was on the access-control-allow-headers that were not set the right way. The fix was to populate the response access-control-allow-headers with the Access-Control-Request-Headers request headers.

Here is the final implementation:

class MessageBusCorsMiddleware
  HTTP_ORIGIN = 'HTTP_ORIGIN'
  HTTP_X_ORIGIN = 'HTTP_X_ORIGIN'

  HTTP_ACCESS_CONTROL_REQUEST_METHOD = 'HTTP_ACCESS_CONTROL_REQUEST_METHOD'
  HTTP_ACCESS_CONTROL_REQUEST_HEADERS = 'HTTP_ACCESS_CONTROL_REQUEST_HEADERS'
  OPTIONS = 'OPTIONS'
  REQUEST_METHOD = 'REQUEST_METHOD'
  PATH_INFO      = 'PATH_INFO'

  def initialize(app)
    @app = app
  end

  def call(env)
    # If it's message bus and an OPTIONS request, return CORS headers
    if env[PATH_INFO].start_with?('/message-bus') && env[REQUEST_METHOD] == OPTIONS && env[HTTP_ACCESS_CONTROL_REQUEST_METHOD]
      origin = env['HTTP_ORIGIN']
      # Apply CORS headers for /message-bus requests
      headers = {
        "access-control-allow-origin" => "*",
        "access-control-allow-methods" => "GET, POST, PUT, PATCH, DELETE, OPTIONS",
        "access-control-expose-headers" => "",
        "access-control-max-age" => "7200"
      }

      headers.merge!('access-control-allow-headers' => env[HTTP_ACCESS_CONTROL_REQUEST_HEADERS]) if env[HTTP_ACCESS_CONTROL_REQUEST_HEADERS]
      [200, headers, []]
    else
      @app.call(env)
    end
  end
end

I was having issues understanding the role of the the HTTP header “Access-Control-Request-Headers” so I asked ChatGPT:

The HTTP header “Access-Control-Request-Headers” is used in the context of Cross-Origin Resource Sharing (CORS) requests. CORS is a mechanism that allows web applications to make requests to a different domain than the one the application originated from.

When a web application makes a cross-origin request, it typically sends an initial “preflight” request to the server to determine if the actual request is allowed. The preflight request includes the “Access-Control-Request-Headers” header, which lists the additional headers that the application wants to include in the actual request.

For example, if a web application wants to include custom headers like “X-Auth-Token” or “Authorization” in its cross-origin request, it would specify those headers in the “Access-Control-Request-Headers” header of the preflight request.

The server receiving the preflight request can then inspect the “Access-Control-Request-Headers” header to determine whether the requested headers are allowed for the actual request. If the server approves the requested headers, it responds with the appropriate Access-Control-Allow-Headers header in the preflight response, allowing the web application to proceed with the actual request.

In summary, “Access-Control-Request-Headers” is an HTTP header used in CORS preflight requests to specify the additional headers that a web application wants to include in its cross-origin request.

I am sharing this in case someone else is trying to achieve the same thing. I am also open to feedback especially regarding security issues that this implementation can open.