Complex problem with traefik api and authetication middleware

Hi all,

I have a stack docker-compose with traefik and an apache server
I have several authentication middleware (authelia, keycloak with openID, etc..)
I have also a middleware without authetication
the 2 services are availaible via url and
all middleware inclus CORS (accessControlAllowOriginList: "*")
everyting works fine except when my apache application is requesting traefik api : -->"
then I get error , for example with authelia middleware : Uncaught SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
with the other middleware I have different error.
I don't know how to manage this problem

1 Like

Gotta love complex challenges :slight_smile:

So your Apache app (php?) at /api is requesting

Where is the JSON error thrown? In your app? Can you output the non JSON?

Share your full Traefik static and dynamic config, and docker-compose.yml if used.

1 Like

The application is really simple html+js (one page). I wanted to show on a single page all http routers in traefik with the associated middleware. This information is not available on 1 page in traefik dashboard.
The idea is to have it on single page to be sure that I have associated a middleware with authentication in front of each service.
Also each host rule in traefik are converted to url hyperlink

Here is the java script

var apiUrl='';
var request=new XMLHttpRequest();'GET',apiUrl,!0);
  var data=JSON.parse(this.response);
  var table=document.createElement("table");
  var headerRow=table.insertRow(-1);
  headerRow.innerHTML = "<th>Number</th><th>URL</th><th>Router</th><th>Entrypoints</th><th>Rule</th><th>Middlewares</th><th>Service</th><th>Provider</th><th>Status</th>";
  for(var i=0;i<data.length;i++){
    var row=table.insertRow(-1);
    var cell = row.insertCell(-1); // Insert a cell in the first column for the row number
    cell.innerHTML = i; // Set the cell value to the loop counter
    var entrypoints = data[i].entryPoints.join(', '); // Join the entryPoints array into a string separated by commas
    var middlewares;
    if (Array.isArray(data[i].middlewares)) {
      middlewares = data[i].middlewares.join(', '); // Join the middlewares array into a string separated by commas
    } else {
      middlewares = data[i].middlewares;
    var url = data[i].rule.replace(/\`\)/g, '').replace(/Host\(\`/g, '').replace(/ && PathPrefix\(`/g, '');
    if (url.startsWith("HostRegexp")) {
      url = url.replace(/.+/, ""); // Replace the content with an empty string
    } else {
      url = "https://" + url; // Add the "https://" prefix
    row.innerHTML = "<td>" + i + "</td><td><a href='" + url + "'>" + url + "</a></td><td><a href='" + data[i].name + "'>" + data[i].name + "</a></td><td>" + entrypoints + "</td><td>" + data[i].rule + "</td><td><a href='" + data[i].middlewares + "'>" + data[i].middlewares + "</a></td><td><a href='" + data[i].service + "@" + data[i].provider + "'>" + data[i].service + "</a></td><td>" + data[i].provider + "</td><td>" + data[i].status + "</td>";

Here is the HTML

> <!DOCTYPE html>
> <html>
>   <head>
>       <title>Simple Traefik Dashboard v2</title>
>       <link rel="stylesheet" type="text/css" href="style.css">
>   </head>
>   <body>
>     <div id="jsonTable">
>       <h1>Simple Traefik Dashboard v2</h1>
>     </div>
>     <script src="script.js"></script>
>   </body>
> </html>

I have also create a test.html which simply contains "this is a test"

Here is the result (webpage)

Simple Traefik Dashboard v2
Number	URL	Router	Entrypoints	Rule	Middlewares	Service	Provider	Status
0	Apache2_rtr@docker	https	Host(``)	chain-no-auth@file	Apache2_svc	docker	enabled
1	adminer_rtr@docker	https	Host(``)	chain-myauth@file	adminer_svc	docker	enabled
2	authelia_rtr@docker	https	Host(``)	chain-authelia@file	authelia_svc	docker	enabled
3	keycloak_rtr@docker	https	Host(``)	undefined	keycloak_svc	docker	enabled
4	portainer_rtr@docker	https	Host(``)	chain-authelia@file	portainer_svc	docker	enabled
5	myauth_rtr@docker	https	Host(``)	chain-myauth@file	myauth_svc	docker	enabled
6	whoami_rtr@docker	https	Host(``)	chain-myauth@file	whoami-docker	docker	enabled
````Preformatted text`

I have this middleware 

      - middlewares-rate-limit
      - middlewares-https-redirectscheme
      - middlewares-secure-headers
      - middlewares-compress
      - middlewares-rate-limit
      - middlewares-https-redirectscheme
      - middlewares-secure-headers
      - middlewares-authelia
      - middlewares-compress
      - middlewares-rate-limit
      - middlewares-https-redirectscheme
      - middlewares-secure-headers
      - middlewares-myauth
      - middlewares-compress

    address: "http://myauth:4181" # Make sure you have the myauth service in docker-compose.yml
    trustForwardHeader: true
      - "X-Forwarded-User"
    address: "http://authelia:9091/api/verify?rd=https://authelia.{{env "DOMAINNAME0"}}"
    trustForwardHeader: true
      - "Remote-User"
      - "Remote-Groups"

Traefik labels (docker-compose)

  - traefik.enable=true
  # HTTP-to-HTTPS Redirect
  - traefik.http.routers.http-catchall.entrypoints=http
  - traefik.http.routers.http-catchall.rule=HostRegexp(`{host:.+}`)
  - traefik.http.routers.http-catchall.middlewares=redirect-to-https
  - traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https
  # HTTP Routers
  - traefik.http.routers.traefik_rtr.entrypoints=https
  - traefik.http.routers.traefik_rtr.rule=Host(`traefik.$DOMAINNAME0`)
  ## Services - API
  - traefik.http.routers.traefik_rtr.service=api@internal
  ## Middlewares
  - traefik.http.routers.traefik_rtr.middlewares=chain-no-auth@file
  # - traefik.http.routers.traefik_rtr.middlewares=chain-myauth@file 
  # - traefik.http.routers.traefik_rtr.middlewares=chain-authelia@file

    <<: *common-keys-core # See EXTENSION FIELDS at the top  
    container_name: apache2
    image: httpd:latest
      - ./website:/usr/local/apache2/htdocs
      - traefik.enable=true
      ## HTTP Routers
      - traefik.http.routers.Apache2_rtr.entrypoints=https
      - traefik.http.routers.Apache2_rtr.rule=Host(`apache.$DOMAINNAME0`)
      ## Middlewares
      - traefik.http.routers.Apache2_rtr.middlewares=chain-no-auth@file
      # - traefik.http.routers.Apache2_rtr.middlewares=chain-myauth@file
      # - traefik.http.routers.Apache2_rtr.middlewares=chain-authelia@file
      ## HTTP Services
      - traefik.http.routers.Apache2_rtr.service=Apache2_svc

I have put several middleware in traefik service and apache2 and comment/uncomment for testing purpose
I think the problem comes from traefik middleware with authentication :
if chain-no-auth@file then everything is ok
if chain-authelia@file then do not work, but is ok

firefox debug windows

Uncaught SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data onload

if chain-myauth@file then do not work, but is ok

firefox debug windows:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at (Reason: CORS header ‘Access-Control-Allow-Origin’ missing). Status code: 200.

I was first looking to solve CORS problem because the last error is saying : (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)
But in fact if I swith to authelia authentication then I have a different problem.
Also with the test.html which is not requested traefik api back this works without problem

I hope that can help

1 Like