Unable to use API due to cross origin block

Forum for questions and support relating to the 1.34.x releases only.
Post Reply
xiki
Posts: 3
Joined: Mon Apr 12, 2021 8:23 pm

Unable to use API due to cross origin block

Post by xiki »

I've been trying to fix this for a while now. I have a local host, where I'm building an interface and would like to make API requests to zoneminder server, which is on another machine. Both endpoints are behind a valid SSL configuration.

I'm sending a JS fetch to https://<domain>/zm/api/host/login.json, with the appropriate user and password. This same request works fine on Insomnia ( similar to Postman ) but on my local host where I'm building the interface, the browser spits out:

Access to fetch at 'https://cams.domain1.com/zm/api/host/login.json' from origin 'https://loc.domain1.com' has been blocked by CORS policy: Request header field access-control-allow-expose-headers is not allowed by Access-Control-Allow-Headers in preflight response.

What am I missing?
hine.site
Posts: 2
Joined: Thu Sep 02, 2021 3:52 am

Re: Unable to use API due to cross origin block

Post by hine.site »

I couldn't find anyway official way to add the headers, but what you can do is edit the api application controller and add your own headers.
On my system, the application controller can be found here:

Code: Select all

/usr/share/zoneminder/www/api/app/Controller/AppController.php
Then add your headers to the bottom of the 'beforeFilter' function.

I would recomend using the cors function on the response. For example:

Code: Select all

$this->response->cors($this->request, '*');
You can even pass in an array of domains to allow if you would rather not allow everything.
/**
* Setup access for origin and methods on cross origin requests
*
* This method allow multiple ways to setup the domains, see the examples
*
* ### Full URI
* e.g `cors($request, 'https://www.cakephp.org');`
*
* ### URI with wildcard
* e.g `cors($request, 'http://*.cakephp.org');`
*
* ### Ignoring the requested protocol
* e.g `cors($request, 'www.cakephp.org');`
*
* ### Any URI
* e.g `cors($request, '*');`
*
* ### Whitelist of URIs
* e.g `cors($request, array('https://www.cakephp.org', '*.google.com', 'https://myproject.github.io'));`
*
* @param CakeRequest $request Request object
* @param string|array $allowedDomains List of allowed domains, see method description for more details
* @param string|array $allowedMethods List of HTTP verbs allowed
* @param string|array $allowedHeaders List of HTTP headers allowed
* @return void
*/
public function cors(CakeRequest $request, $allowedDomains, $allowedMethods = array(), $allowedHeaders = array()) {
For anyone interested in doing this, do note that there are security implications.
Also, since this is just a hack/work-around, you may need to reapply this change after performing a zoneminder upgrade.
A system option for this would be nice. A text box that would allow a comma separated list of urls would be perfect.
User avatar
asker
Posts: 1553
Joined: Sun Mar 01, 2015 12:12 pm

Re: Unable to use API due to cross origin block

Post by asker »

Can't one enable CORS in Apache (or whichever webserver you use) instead or is this something different?
https://enable-cors.org/server_apache.html
I no longer work on zmNinja, zmeventnotification, pyzm or mlapi. I may respond on occasion based on my available time/interest.

Please read before posting:
How to set up logging properly
How to troubleshoot and report - ES
How to troubleshoot and report - zmNinja
ES docs
zmNinja docs
hine.site
Posts: 2
Joined: Thu Sep 02, 2021 3:52 am

Re: Unable to use API due to cross origin block

Post by hine.site »

You are correct, you can instead add the response header in the server configuration.
For a simple allow all rule, this would be easier than modifying the app controller as well.
I feel rather embarrassed for not thinking about that myself...

The only downside to this approach is that it is an all or one situation.
To the best of my knowledge, you can either allow all domains (with an *), or a single sub/domain.
Using cake's cors method on the response allows you to provide a list of domains and subdomains to allow access.
I think it also allows you to further restrict access to specific endpoints.

I would also assume setting the header in the server config would be safer for upgrades, but I have had one upgrade overwrite the default zoneminder.conf.
Post Reply