Enabling CORS requests


I’m trying to reach the REST API using a webapp.

I’m encountering CORS errors. I set http_enable_cors to true but it did not change anything.
I’m using Graylog 4.0.9 ova.

My requests using XmlHttpRequest are blocked:

Access to XMLHttpRequest at '' from origin 'http://xxx:' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.

This is how my request looks like:

        let xhttp = new XMLHttpRequest();
        xhttp.open("GET", "", false);
        xhttp.setRequestHeader('Access-Control-Allow-Origin', '*')
        xhttp.setRequestHeader("X-Requested-by", "XMLHttpRequest");
        xhttp.setRequestHeader("Accept", "application/json");
        xhttp.setRequestHeader("Authority", "Basic "+btoa("admin:PX9tLvLL"));



I tried to modify the nginx conf by adding :

   add_header 'Access-Control-Allow-Origin' '*';
   add_header 'Access-Control-Allow-Credentials' 'true';
   add_header 'Access-Control-Allow-Headers' '*';
   add_header 'Access-Control-Allow-Methods' '*';

Then I obtain a 401 Unauthorized error.

I don’t understand this behavior because the request works when I’m using postman. I guess the problem comes either from my xmlHttpRequest / the cors config or both.

Update 2 :

I reset the server.conf and now I only get 401 errors with exact same request which is working on postman.

I guess the problem is all coming from the CORS and navigator’s security and its pre fetch requests OPTION. I saw they were mandatory for any “complex” request like unusual header like X-Request-by" (which is also mandatory for Graylog calls).

I’ll try to make a home made python api I’ll use like a proxy for requesting directly the graylog API.

Update 3

When I check the request made by graylog when we use the search UI, I see the endpoint api/views/search is used. I would like to reproduce it for obvious reasons but how is generated those id which are use in argument.

Moreover it only create the search and it does make easy retrieving infomration…

Example (cmd curl equivalent taken from chrome console):

curl "" ^
  -H "Connection: keep-alive" ^
  -H "Pragma: no-cache" ^
  -H "Cache-Control: no-cache" ^
  -H "Authorization: Basic MzkzOWQxZDQtOGE5Y....YmUzOnNlc3Npb24=" ^
  -H "Accept: application/json" ^
  -H "X-Requested-With: XMLHttpRequest" ^
  -H "X-Requested-By: XMLHttpRequest" ^
  -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36" ^
  -H "Content-Type: application/json" ^
  -H "Origin:" ^
  -H "Referer:^%^3A0&rangetype=relative&relative=172800" ^
  -H "Accept-Language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7" ^
  --data-raw "^{^\^"id^\^":^\^"623bac8d60de91ab7aee28b7^\^",^\^"queries^\^":^[^{^\^"id^\^":^\^"dfc02d96-5437-4e85-bec0-38f7e98d5fa6^\^",^\^"query^\^":^{^\^"type^\^":^\^"elasticsearch^\^",^\^"query_string^\^":^\^"EventID:1^\^"^},^\^"timerange^\^":^{^\^"type^\^":^\^"relative^\^",^\^"range^\^":172800^},^\^"filter^\^":null,^\^"search_types^\^":^[^{^\^"timerange^\^":null,^\^"query^\^":null,^\^"streams^\^":^[^],^\^"id^\^":^\^"75ef0c91-b139-42ee-b5d1-13009380644d^\^",^\^"name^\^":^\^"chart^\^",^\^"series^\^":^[^{^\^"type^\^":^\^"count^\^",^\^"id^\^":^\^"count()^\^",^\^"field^\^":null^}^],^\^"sort^\^":^[^],^\^"rollup^\^":true,^\^"type^\^":^\^"pivot^\^",^\^"row_groups^\^":^[^{^\^"type^\^":^\^"time^\^",^\^"field^\^":^\^"timestamp^\^",^\^"interval^\^":^{^\^"type^\^":^\^"auto^\^",^\^"scaling^\^":1^}^}^],^\^"column_groups^\^":^[^],^\^"filter^\^":null^},^{^\^"timerange^\^":null,^\^"query^\^":null,^\^"streams^\^":^[^],^\^"id^\^":^\^"a9ec4c8f-fe01-43a9-8e22-bc949ebdc157^\^",^\^"name^\^":null,^\^"limit^\^":150,^\^"offset^\^":0,^\^"sort^\^":^[^{^\^"field^\^":^\^"timestamp^\^",^\^"order^\^":^\^"DESC^\^"^}^],^\^"decorators^\^":^[^],^\^"type^\^":^\^"messages^\^",^\^"filter^\^":null^}^]^}^],^\^"parameters^\^":^[^]^}" ^
  --compressed ^

I see your allowing ALL That was the first thing I was going to suggest.

What does postman config have that your webapp doesn’t? I see the 401 basically lacks valid authentication credentials for the target.

Have you tried to adjust these settings?

EDIT: Couple more ideas.
One of the most common reasons you might experience a 401 error is that your browser’s cache and cookies are out of date, preventing the authorization from successfully going through.
If your browser isn’t using the valid authentication credentials (or any at all), the server will reject the request. It’s also possible that the source of the problem can be attributed to a minor mistake.
Common culprits in this category include an incorrectly-typed URL .
Hope that helps


In fact those 401 errors precede a pre fetch query which is mandatory on web browsers because the XmlHttpRequest cors request is considered as special (Idk all the criterias but I know specific headers like X-Requested-By are part of them).

In my case this pre fecth query results a 204 http code which means no content returned. Then the original request is launched with all same argument as my tests with postman. But in the XmlHttpREquest context, it returns the 401 error.

I know it does not make any sense because the exact same request works with postman. This is why I presume the problem comes from the pre fetching system.

Concerning the url whitelisting, I think it only affect output from graylog and not incoming queries but I can give a try.

I understand now,

Came across this, not sure if it will help.

OK big news.

The whole problem was coming from a misconfiguration of the Authorization header. (syntax error)

When it comes to using sessionId, the Authorization header format is "sessionId:session". When you want to directly use clear credentials the syntax is "user:password" and not "session:sessionId"

For the one having close issues to mine, don’t forget to verify you did not also forget any mandatory header like "X-Requested-By".

My bad

Thanks again for your support @gsmith !

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.