Reputation: 99
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.
Upvotes: 1
Views: 978
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