Login Template nosniff error and laravel socialite 504 Gateway Time-out after filling form

Hello, that’s been now more than two week that I’m stuck with two error in my config.
I’m transitioning my infrastructure to use docker container and Traefik as a reverse proxy. But I’m stuck with two problem

Here is the infra

  • Traefik (reverse proxy)
  • Keycloak (auth server)
  • React.js (frontend) => main website
  • Laravel (backend) => API for main website + admin UI

The laravel backend provide :

I’ve two problem

  • My login theme template is totally broken with error “incorrect (X-Content-Type-Options: nosniff)” concerning index.js and index.css
  • When accessing the laravel admin and trying to connect I’m redirected to
    https://LARAVEL_APP/auth/callback?session_state=… But I get a 504 Gateway Time-out

= From the main website in react you can connect using keycloak and the api side of the backend is working properly. The problem really reside in the backend laravel socialite config or traefik config

Here is the config

Traefik - docker-compose

version: "3.8"
services:

  traefik:
    image: ${TRAEFIK_IMAGE_TAG}
    container_name: traefik
    command:
      - --log.level=WARNING
      - --accesslog=true
      - --api.dashboard=true
      - --api.insecure=true
      - --ping=true
      - --ping.entrypoint=ping
      - --entryPoints.ping.address=:8082
      - --entryPoints.web.address=:80
      - --entryPoints.websecure.address=:443
      - --providers.docker=true
      - --providers.docker.endpoint=unix:///var/run/docker.sock
      - --providers.docker.exposedbydefault=false
      - --certificatesresolvers.myresolver.acme.tlschallenge=true
      - --certificatesresolvers.myresolver.acme.caserver=https://acme-v02.api.letsencrypt.org/directory
      - --certificatesresolvers.myresolver.acme.email=${TRAEFIK_ACME_EMAIL}
      - --certificatesresolvers.myresolver.acme.storage=/etc/traefik/acme/acme.json
      - "--metrics.prometheus=true"
      - "--metrics.prometheus.buckets=0.1,0.3,1.2,5.0"
      - "--global.checkNewVersion=true"
      - "--global.sendAnonymousUsage=false"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - "/etc/traefik/acme:/etc/traefik/acme"
    networks:
      - traefik-network
    ports:
      - "80:80"
      - "443:443"
    labels:
      traefik.enable: true
      traefik.http.routers.dashboard.rule: Host(`${TRAEFIK_HOSTNAME}`)
      traefik.http.routers.dashboard.tls.domains[0].main: ${TRAEFIK_HOSTNAME}
      traefik.http.routers.dashboard.tls.domains[0].sans: ${TRAEFIK_WWW_HOSTNAME}
      traefik.http.routers.dashboard.entrypoints: websecure
      traefik.http.routers.dashboard.service: dashboard@internal
      traefik.http.services.dashboard.loadbalancer.server.port: 8080
      traefik.http.routers.dashboard.tls: true
      traefik.http.routers.dashboard.tls.certresolver: myresolver
      traefik.http.services.dashboard.loadbalancer.passhostheader: true
      traefik.http.routers.dashboard.middlewares: authtraefik
      traefik.http.middlewares.authtraefik.basicauth.users: ${TRAEFIK_BASIC_AUTH}
      traefik.http.routers.api.rule: Host(`${TRAEFIK_HOSTNAME}`) && PathPrefix(`/api`)
      traefik.http.routers.api.service: api@internal
      traefik.http.routers.api.entrypoints: websecure
      traefik.http.routers.api.tls: true
      traefik.http.routers.api.tls.certresolver: myresolver
      traefik.http.routers.httpsonly.rule: HostRegexp(`{any:.*}`)
      traefik.http.middlewares.httpsonly.redirectscheme.scheme: https
      traefik.http.middlewares.httpsonly.redirectscheme.permanent: true
      traefik.http.routers.httpsonly.middlewares: httpsonly
      traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto: https
      traefik.docker.network: traefik-network
    restart: unless-stopped
    logging:
      driver: gelf
      options:
        gelf-address: ${TRAEFIK_LOG_ADDRESS}
        tag: ${TRAEFIK_LOG_TAG}

networks:
  traefik-network:
    external: true

Keycloak - docker-compose

version: "3.8"
services:

  postgres-keycloak:
    image: ${KEYCLOAK_POSTGRES_IMAGE_TAG}
    container_name: postgres-keycloak
    environment:
      POSTGRES_DB: ${KEYCLOAK_DB_NAME}
      POSTGRES_USER: ${KEYCLOAK_DB_USER}
      POSTGRES_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
    volumes:
      - keycloak-data:/var/lib/postgresql/data
      - /var/log/keycloak/postgres:/var/lib/postgresql/logs
    networks:
      - keycloak-network
    ports:
      - ":5432"
    healthcheck:
      test: [ "CMD", "pg_isready", "-q", "-d", "${KEYCLOAK_DB_NAME}", "-U", "${KEYCLOAK_DB_USER}" ]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 60s
    restart: unless-stopped
    logging:
      driver: gelf
      options:
        gelf-address: ${KEYCLOAK_LOG_ADDRESS}
        tag: ${KEYCLOAK_POSTGRES_LOG_TAG}

  keycloak:
    build:
      context: .
      args:
        KEYCLOAK_VERSION: ${KEYCLOAK_VERSION}
    command: ['start','--optimized']
    container_name: keycloak
    environment:
      JAVA_OPTS_APPEND: -Dkeycloak.profile.feature.upload_scripts=enabled
      KC_DB_USERNAME: ${KEYCLOAK_DB_USER}
      KC_DB_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
      KC_DB_URL: jdbc:postgresql://postgres-keycloak:5432/${KEYCLOAK_DB_NAME}
      KC_HEALTH_ENABLED: 'true'
      KC_HTTP_ENABLED: 'true'
      KC_METRICS_ENABLED: 'true'
      KC_HOSTNAME_STRICT: 'false'
      KC_HOSTNAME: ${KEYCLOAK_HOSTNAME}
      KC_PROXY: reencrypt
      KEYCLOAK_ADMIN: ${KEYCLOAK_USER}
      KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_PASSWORD}
      # KC_LOG_LEVEL: debug
    networks:
      - keycloak-network
      - traefik-network
    ports:
      - ":8080"
    healthcheck:
      test: timeout 10s bash -c ':> /dev/tcp/127.0.0.1/8080' || exit 1
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 90s
    labels:
      traefik.enable: true
      traefik.http.routers.keycloak.rule: Host(`${KEYCLOAK_HOSTNAME}`)
      traefik.http.routers.keycloak.tls.domains[0].main: ${KEYCLOAK_HOSTNAME}
      traefik.http.routers.keycloak.tls.domains[0].sans: ${KEYCLOAK_WWW_HOSTNAME}
      traefik.http.routers.keycloak.service: keycloak
      traefik.http.routers.keycloak.entrypoints: websecure
      traefik.http.services.keycloak.loadbalancer.server.port: 8080
      traefik.http.services.keycloak.loadbalancer.passhostheader: true
      traefik.http.routers.keycloak.tls: true
      traefik.http.routers.keycloak.tls.certresolver: myresolver
      # Middelwares
      traefik.http.middlewares.keycloak-headers.headers.customrequestheaders.X-Forwarded-Proto: https
      traefik.http.middlewares.keycloak-headers.headers.customrequestheaders.X-Forwarded-For: 127.0.0.1
      traefik.http.middlewares.keycloak-headers.headers.customrequestheaders.X-Forwarded-Host: ${KEYCLOAK_HOSTNAME}
      traefik.http.routers.keycloak.middlewares: keycloak-headers
      traefik.docker.network: traefik-network
    restart: unless-stopped
    depends_on:
      postgres-keycloak:
        condition: service_healthy
    logging:
      driver: gelf
      options:
        gelf-address: ${KEYCLOAK_LOG_ADDRESS}
        tag: ${KEYCLOAK_LOG_TAG}

  keycloak-backups:
    image: ${KEYCLOAK_POSTGRES_IMAGE_TAG}
    container_name: keycloak-backups
    command: >-
      sh -c 'sleep $KEYCLOAK_BACKUP_INIT_SLEEP &&
      while true; do
        pg_dump -h postgres-keycloak -p 5432 -d $KEYCLOAK_DB_NAME -U $KEYCLOAK_DB_USER | gzip > $KEYCLOAK_POSTGRES_BACKUPS_PATH/$KEYCLOAK_POSTGRES_BACKUP_NAME-$(date "+%Y-%m-%d_%H-%M").gz &&
        find $KEYCLOAK_POSTGRES_BACKUPS_PATH -type f -mtime +$KEYCLOAK_POSTGRES_BACKUP_PRUNE_DAYS | xargs rm -f &&
        sleep $KEYCLOAK_BACKUP_INTERVAL; done'
    volumes:
      - keycloak-postgres-backup:/var/lib/postgresql/data
      - keycloak-database-backups:${KEYCLOAK_POSTGRES_BACKUPS_PATH}
      - /var/log/keycloak/backups:/var/lib/postgresql/logs  # Added volume for backup logs
    environment:
      KEYCLOAK_DB_NAME: ${KEYCLOAK_DB_NAME}
      KEYCLOAK_DB_USER: ${KEYCLOAK_DB_USER}
      PGPASSWORD: ${KEYCLOAK_DB_PASSWORD}
      KEYCLOAK_BACKUP_INIT_SLEEP: ${KEYCLOAK_BACKUP_INIT_SLEEP}
      KEYCLOAK_BACKUP_INTERVAL: ${KEYCLOAK_BACKUP_INTERVAL}
      KEYCLOAK_POSTGRES_BACKUP_PRUNE_DAYS: ${KEYCLOAK_POSTGRES_BACKUP_PRUNE_DAYS}
      KEYCLOAK_POSTGRES_BACKUPS_PATH: ${KEYCLOAK_POSTGRES_BACKUPS_PATH}
      KEYCLOAK_POSTGRES_BACKUP_NAME: ${KEYCLOAK_POSTGRES_BACKUP_NAME}
      KEYCLOAK_LOG: console,gelf
      KEYCLOAK_LOG_GELF_HOST: localhost
      KEYCLOAK_LOG_GELF_PORT: 12201
    networks:
      - keycloak-network
    restart: unless-stopped
    depends_on:
      postgres-keycloak:
        condition: service_healthy
    logging:
      driver: gelf
      options:
        gelf-address: ${KEYCLOAK_LOG_ADDRESS}
        tag: ${KEYCLOAK_BACKUPS_LOG_TAG}

volumes:
  keycloak-data:
    driver: local
  keycloak-postgres-backup:
    driver: local
  keycloak-database-backups:
    driver: local

networks:
  traefik-network:
    external: true
  keycloak-network:
    external: true

Keycloak - Dockerfile

FROM quay.io/keycloak/keycloak:22.0.5 as builder

# Enable health and metrics support
ENV KC_HEALTH_ENABLED=true
ENV KC_METRICS_ENABLED=true

# Configure a database vendor
ENV KC_DB=postgres

WORKDIR /opt/keycloak
# for demonstration purposes only, please make sure to use proper certificates in production instead
# RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore conf/server.keystore
RUN /opt/keycloak/bin/kc.sh build

FROM quay.io/keycloak/keycloak:22.0.5
COPY --from=builder /opt/keycloak/ /opt/keycloak/

# change these values to point to a running postgres instance
ENV KC_HOSTNAME=***********
ENV JAVA_OPTS_APPEND: -Dkeycloak.profile.feature.upload_scripts=enabled
ENV KC_DB_USERNAME: ${KEYCLOAK_DB_USER}
ENV KC_DB_PASSWORD: ${KEYCLOAK_DB_PASSWORD}
ENV KC_DB_URL: jdbc:postgresql://postgres-keycloak:5432/${KEYCLOAK_DB_NAME}
ENV KC_HTTP_ENABLED: 'true'
ENV KC_HOSTNAME_STRICT: 'false'
ENV KC_HOSTNAME: ${KEYCLOAK_HOSTNAME}
ENV KC_PROXY: reencrypt
ENV KEYCLOAK_ADMIN: ${KEYCLOAK_USER}
ENV KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_PASSWORD}
# ENV KC_LOG_LEVEL: debug

COPY ./themes/*****-keycloak-theme-keywind /opt/keycloak/themes/*******-keycloak-theme-keywind

ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]

Laravel - docker-compose

version: "3.8"
services:

  postgres-web-backend:
    image: ${WEBBACKEND_POSTGRES_IMAGE_TAG}
    container_name: postgres-web-backend
    environment:
      POSTGRES_DB: ${WEBBACKEND_DB_NAME}
      POSTGRES_USER: ${WEBBACKEND_DB_USER}
      POSTGRES_PASSWORD: ${WEBBACKEND_DB_PASSWORD}
    volumes:
      - web-backend-data:/var/lib/postgresql/data
    networks:
      - web-backend-network
    ports:
      - ":5432"
    healthcheck:
      test: [ "CMD", "pg_isready", "-q", "-d", "${WEBBACKEND_DB_NAME}", "-U", "${WEBBACKEND_DB_USER}" ]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 60s
    restart: unless-stopped
    logging:
      driver: gelf
      options:
        gelf-address: ${WEBBACKEND_LOG_ADDRESS}
        tag: ${WEBBACKEND_POSTGRES_LOG_TAG}

  web-backend:
    build:
      args:
        user: www
        uid: 1000
      context: ./
      dockerfile: Dockerfile
    image: web-backend
    container_name: web-backend
    working_dir: /var/www/
    volumes:
      - ./:/var/www/
    networks:
      - web-backend-network
      - traefik-network
    restart: unless-stopped
    depends_on:
      postgres-web-backend:
        condition: service_healthy
    logging:
      driver: gelf
      options:
        gelf-address: ${WEBBACKEND_LOG_ADDRESS}
        tag: ${WEBBACKEND_LOG_TAG}

  web-backend-nginx:
    image: nginx:alpine
    container_name: web-backend-nginx
    volumes:
      - ./:/var/www/
      - ./nginx/:/etc/nginx/conf.d/
    networks:
      - traefik-network
    ports:
      - ":80"
    labels:
      traefik.enable: true
      traefik.http.routers.web-backend.rule: Host(`${WEBBACKEND_HOSTNAME}`)
      traefik.http.routers.web-backend.tls.domains[0].main: ${WEBBACKEND_HOSTNAME}
      traefik.http.routers.web-backend.tls.domains[0].sans: ${WEBBACKEND_WWW_HOSTNAME}
      traefik.http.routers.web-backend.service: web-backend
      traefik.http.routers.web-backend.entrypoints: websecure
      traefik.http.services.web-backend.loadbalancer.server.port: 80
      traefik.http.services.web-backend.loadbalancer.passhostheader: true
      traefik.http.routers.web-backend.tls: true
      traefik.http.routers.web-backend.tls.certresolver: myresolver
      traefik.docker.network: traefik-network
    logging:
      driver: gelf
      options:
        gelf-address: ${WEBBACKEND_LOG_ADDRESS}
        tag: ${WEBBACKEND_NGINX_LOG_TAG}
    depends_on:
      - web-backend

  web-backend-backups:
    image: ${WEBBACKEND_POSTGRES_IMAGE_TAG}
    container_name: web-backend-backups
    command: >-
      sh -c 'sleep $WEBBACKEND_BACKUP_INIT_SLEEP &&
      while true; do
        pg_dump -h postgres-web-backend -p 5432 -d $WEBBACKEND_DB_NAME -U $WEBBACKEND_DB_USER | gzip > $WEBBACKEND_POSTGRES_BACKUPS_PATH/$WEBBACKEND_POSTGRES_BACKUP_NAME-$(date "+%Y-%m-%d_%H-%M").gz &&
        find $WEBBACKEND_POSTGRES_BACKUPS_PATH -type f -mtime +$WEBBACKEND_POSTGRES_BACKUP_PRUNE_DAYS | xargs rm -f &&
        sleep $WEBBACKEND_BACKUP_INTERVAL; done'
    volumes:
      - web-backend-postgres-backup:/var/lib/postgresql/data
      - web-backend-database-backups:${WEBBACKEND_POSTGRES_BACKUPS_PATH}
    environment:
      ZABBIX_DB_NAME: ${WEBBACKEND_DB_NAME}
      ZABBIX_DB_USER: ${WEBBACKEND_DB_USER}
      PGPASSWORD: ${WEBBACKEND_DB_PASSWORD}
      ZABBIX_BACKUP_INIT_SLEEP: ${WEBBACKEND_BACKUP_INIT_SLEEP}
      ZABBIX_BACKUP_INTERVAL: ${WEBBACKEND_BACKUP_INTERVAL}
      ZABBIX_POSTGRES_BACKUP_PRUNE_DAYS: ${WEBBACKEND_POSTGRES_BACKUP_PRUNE_DAYS}
      ZABBIX_POSTGRES_BACKUPS_PATH: ${WEBBACKEND_POSTGRES_BACKUPS_PATH}
      ZABBIX_POSTGRES_BACKUP_NAME: ${WEBBACKEND_POSTGRES_BACKUP_NAME}
    networks:
      - web-backend-network
    restart: unless-stopped
    depends_on:
      postgres-web-backend:
        condition: service_healthy
    logging:
      driver: gelf
      options:
        gelf-address: ${WEBBACKEND_LOG_ADDRESS}
        tag: ${WEBBACKEND_BACKUPS_LOG_TAG}

volumes:
  web-backend-data:
  web-backend-postgres-backup:
  web-backend-database-backups:

networks:
  traefik-network:
    external: true
  web-backend-network:
    external: true

Laravel - Dockerfile

FROM php:8.1-fpm

# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/

# Set working directory
WORKDIR /var/www

# Install dependencies
RUN apt-get update && apt-get install -y \
  git \
  curl \
  libpng-dev \
  libonig-dev \
  libxml2-dev \
  libpq-dev \
  zip \
  unzip \
  nano

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Install extensions
RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql
RUN docker-php-ext-install pdo pdo_pgsql pgsql mbstring exif pcntl bcmath gd

# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www

# Copy existing application directory contents
COPY . /var/www

# Copy existing application directory permissions
COPY --chown=www:www . /var/www

# Change current user to www
USER www

# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]

Thanks all in advance

Feel free to ask question if you need more informations.