In my last TIL I talked about how to set additional security headers for Gitlab. But I also had to do this for other applications I was supporting, where it was more straight-forward to do it (meaning: with code).

I needed to set the access-control-allow-origin header in the other applications. This header tells the browser from which origins the website is allowed to download resources.

This is relevant in web apps that run on webapp-frontend.example.com and want to use data from webapp-backend.example.com. To allow the browser to access webapp-backend.example.com, the frontend application needs to allow it in its access-control-allow-origin header, like this:

access-control-allow-origin: https://webapp-backend.example.com

So I set this in the frontend-application and wanted to test it from the command line.

Here’s how I did it:

curl -v --request OPTIONS 'https://webapp-frontend.example.com' -H 'Origin: https://webapp-backend.example.com' -H 'Access-Control-Request-Method: POST'

Of course I used curl for testing. To check if access-control-allow-origin works, you send a OPTIONS-request to check what methods are allowed by the application. The header 'Access-Control-Request-Method: POST' informs the application that I want to do a POST-request (I guess that’s not strictly necessary to test the allow-origin header).

Now to finally test it, I deactivated the access-control-allow-origin header, to see what will happen. Here’s the result:

> curl -v --request OPTIONS 'https://webapp-frontend.example.com' -H 'Origin: https://webapp-backend.example.com' -H 'Access-Control-Request-Method: POST'
*   Trying 127.0.0.1:8000...
* Connected to 127.0.0.1 (127.0.0.1) port 8000
> OPTIONS /healthz HTTP/1.1
> Host: 127.0.0.1:8000
> User-Agent: curl/8.7.1
> Accept: */*
> Origin: https://webapp-backend.example.com
> Access-Control-Request-Method: POST
> 
* Request completely sent off
< HTTP/1.1 400 Bad Request
< date: Fri, 06 Sep 2024 11:44:27 GMT
< server: uvicorn
< vary: Origin
< access-control-allow-methods: GET, POST
< access-control-max-age: 600
< access-control-allow-headers: Accept, Accept-Language, Content-Language, Content-Type
< content-length: 22
< content-type: text/plain; charset=utf-8
< content-security-policy: base-uri 'self'; connect-src 'self'; script-src; script-src-attr; frame-src; object-src 'none'; img-src; style-src; font-src; manifest-src; media-src; default-src
< referrer-policy: no-referrer
< x-frame-options: DENY
< x-content-type-options: nosniff
< cross-origin-embedder-policy: require-corp
< cross-origin-opener-policy: same-origin
< cross-origin-resource-policy: same-origin
< 
* Connection #0 to host 127.0.0.1 left intact
Disallowed CORS origin

The last line tells you that my request was denied. You can also see that there are three access-control headers in the response (access-control-allow-methods, access-control-max-age, access-control-allow-headers), but no access-control-allow-origin.

Now I activate the header in the application and re-run the curl command:

> curl -v --request OPTIONS 'https://webapp-frontend.example.com' -H 'Origin: https://webapp-backend.example.com' -H 'Access-Control-Request-Method: POST'
*   Trying 127.0.0.1:8000...
* Connected to 127.0.0.1 (127.0.0.1) port 8000
> OPTIONS /healthz HTTP/1.1
> Host: 127.0.0.1:8000
> User-Agent: curl/8.7.1
> Accept: */
> Origin: https://webapp-backend.example.com
> Access-Control-Request-Method: POST
> 
* Request completely sent off
< HTTP/1.1 200 OK
< date: Fri, 06 Sep 2024 11:44:07 GMT
< server: uvicorn
< vary: Origin
< access-control-allow-methods: GET, POST
< access-control-max-age: 600
< access-control-allow-headers: Accept, Accept-Language, Content-Language, Content-Type
< access-control-allow-origin: https://webapp-backend.example.com
< content-length: 2
< content-type: text/plain; charset=utf-8
< content-security-policy: base-uri 'self'; connect-src 'self'; script-src; script-src-attr; frame-src; object-src 'none'; img-src; style-src; font-src; manifest-src; media-src; default-src
< referrer-policy: no-referrer
< x-frame-options: DENY
< x-content-type-options: nosniff
< cross-origin-embedder-policy: require-corp
< cross-origin-opener-policy: same-origin
< cross-origin-resource-policy: same-origin
< 
* Connection #0 to host 127.0.0.1 left intact
OK

Now two things have changed:

  • I get back a OK-response indicating that my request ist allowed.
  • There’s now a header in the response: access-control-allow-origin: https://webapp-backend.example.com

And that’s it. With this simple method you can test on the command-line if your access-control-allow-origin works.



Related posts: