Akhil
Akhil

Reputation: 99

Running Keycloak container behing Nginx Reverse proxy with Docker swarm

I want to run the Keycloak container in a non-root path ( /auth ) behind a nginx reverse proxy in docker swarm mode.

This is my Dockerfile:

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

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


# Configure a database vendor
ENV KC_DB=mysql

WORKDIR /opt/keycloak

#Generating a Self-Signed Certificate
RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:app.example.com" -keystore conf/server.keystore
RUN /opt/keycloak/bin/kc.sh build

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

#change these values to point to a running Mysql instance
ENV KC_DB=mysql
ENV KC_DB_URL=jdbc:mysql://keycloak_database:3306/keycloak
ENV KC_DB_USERNAME=keycloak
ENV KC_DB_PASSWORD=keycloak
ENV KC_HOSTNAME_URL=https://app.example.com/auth/
ENV KC_HOSTNAME_ADMIN_URL=https://app.example.com/auth/
ENV KC_PROXY=edge
ENV KC_LOG_LEVEL=INFO
ENV KC_HOSTNAME_DEBUG=true
ENV KC_HOSTNAME_STRICT=false

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

Using the above docker file I have used this command to run the keycloak service in which keycloakpro is the image name

docker service create --name keycloak --network test_overlay --constraint node.labels.server==true --env KEYCLOAK_ADMIN=admin --env KEYCLOAK_ADMIN_PASSWORD=admin keycloakpro start --optimized

This is my nginx reverse proxy configuration,

server {
        listen 443 ssl;
        
        index index.html index.htm index.nginx-debian.html;

        server_name app.example.com;
        ssl_certificate /home/certificate.crt;
        ssl_certificate_key /home/private.key;
        
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        access_log /var/log/nginx/reverse-access.log;
        error_log /var/log/nginx/reverse-error.log;


     

        location /backend {
                    rewrite ^/backend(.*)$ $1 break;
                    proxy_pass http://backend-server:9999/;
                    proxy_redirect off;
        }
        
        
        location /auth {
                    rewrite ^/auth(.*)$ $1 break;
                    proxy_set_header Host $host;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header X-Forwarded-Proto https;
                    proxy_set_header X-Forwarded-Host app.example.com;
                    proxy_set_header X-Forwarded-Port 8443;
                    proxy_pass https://keycloak:8443/;
                    add_header Set-Cookie $http_cookie;
       
        }
    
        location / {
                    rewrite ^/(.*)$ /$1 break;
                    proxy_pass http://react-server/;
                    proxy_http_version 1.1;
                    proxy_set_header Upgrade $http_upgrade;
                    proxy_set_header Connection ‘upgrade’;
                    proxy_cache_bypass $http_upgrade;

        }
        
    
}

server {
    listen 80;

    server_name app.example.com;

    return 301 https://$host$request_uri;
}

In the above nginx configuration, I have a backend service running in the "/backend" location block and a react server served by nginx in the root path.

When all the above configurations are used together, keycloak will be accessible through https://app.example.com/auth

When I go to https://app.example.com/auth/, it redirects me to the Keycloak page. This URL takes me to the admin's page: https://app.example.com/auth/admin/.

This will initiate the OAuth2 flow login page: https://app.example.com/auth/realms/master/protocol/openid-connect/auth?client_id=security-admin-console ...

Once I reach this point, Keycloak will store a cookie in the browser, which is not happening in my case. If I access it using https://app.example.com:8443/, the cookie is set, and I am unable to log in. Only if the request goes throw proxy it won't set the cookie.

I have checked various articles related to this but none of them are able to solve my issue. Any help is appreciated.

Keycloak home page

Keycloak login page

Keycloak error page

Upvotes: 1

Views: 978

Answers (1)

Akhil
Akhil

Reputation: 99

It was my mistake actually, I was ignoring the cookie headers in the nginx.conf file of the reverse proxy due to which I got the above issue. To be more specific it's because of these lines,

proxy_ignore_headers Expires Cache-Control Set-Cookie;
proxy_hide_header Set-Cookie;

Commenting these two lines out did the trick.

Upvotes: 2

Related Questions