I am trying to deploy an application that uses Keycloak as an authentication service and GraphDB as repository. The application is running behind a proxy and I am having trouble setting up the OpenID configuration in GraphDB. I created a minimal example with just Keycloak, GraphDB and nginx proxy (custom-nginx
just contains a nginx.conf
with reverse proxy declarations for the services):
version: "3.9"
services:
nginx:
build:
context: nginx
image: custom-nginx
ports:
- 80:80
- 443:443
depends_on:
- auth-server
- db-server
auth-server-db:
image: postgres:13
environment:
POSTGRES_DB:
POSTGRES_USER:
POSTGRES_PASSWORD:
volumes:
- auth-server-db:/var/lib/postgresql/data
auth-server:
image: quay.io/keycloak/keycloak:22.0
command:
- start
environment:
KC_HOSTNAME_URL: ${URL}/auth
KC_HOSTNAME_ADMIN_URL: ${URL}/auth/
KC_HOSTNAME_STRICT_BACKCHANNEL: false
KC_PROXY: edge
KC_HTTP_ENABLED: true
KEYCLOAK_ADMIN: admin
KEYCLOAK_ADMIN_PASSWORD: ${KC_ADMIN_PASS}
DB_VENDOR: POSTGRES
DB_ADDR: auth-server-db
DB_DATABASE: ${POSTGRES_DB}
DB_USER: ${POSTGRES_USER}
DB_SCHEMA: public
DB_PASSWORD: ${POSTGRES_PASSWORD}
ports:
- "127.0.0.1:8088:8080"
volumes:
- auth-server:/opt/keycloak/data
depends_on:
- auth-server-db
db-server:
image: ontotext/graphdb:10.3.2
depends_on:
- auth-server
environment:
GDB_JAVA_OPTS: -Dgraphdb.external-url=${URL}/db-server -Dgraphdb.auth.methods=openid -Dgraphdb.auth.openid.issuer=http://auth-server:8080/realms/termit -Dgraphdb.auth.openid.token_issuer=${URL}/auth/realms/termit -Dgraphdb.auth.openid.client_id=${GDB_CLIENTID} -Dgraphdb.auth.openid.username_claim=preferred_username -Dgraphdb.auth.openid.auth_flow=code -Dgraphdb.auth.openid.token_type=access -Dgraphdb.auth.openid.proxy=true -Ddefault.min.distinct.threshold=67108864 -Dgraphdb.workbench.cors.enable=true -Dgraphdb.workbench.cors.origin=* -Dgraphdb.workbench.cors.expose-headers=*
restart: always
ports:
- "127.0.0.1:7200:7200"
volumes:
- db-server:/opt/graphdb/home
volumes:
auth-server-db:
auth-server:
db-server:
When I try this setup with GraphDB, I get the following error:
The Issuer "http://localhost/auth/realms/termit" provided in the configuration did not match the requested issuer "http://auth-server:8080/realms/termit"
. But if I set the issuer URI to localhost, it cannot connect to it.
My experience with Spring-based applications behind a proxy is that I would set JWT issuer URI to the public URL of the authentication server (e.g., http://localhost/auth/realms/termit
) and JWK Set URI to the internal Docker service URL. Is there any similar setting in GraphDB so that I could get both services working behind a proxy (in Docker)?
Any help or examples are much appreciated. Thanks
The nginx.conf
contains the following:
worker_processes 1;
events {
worker_connections 1024;
}
http {
client_max_body_size 25M;
include mime.types;
default_type application/octet-stream;
server {
listen 80;
server_name localhost;
add_header Access-Control-Allow-Origin *;
location /auth/ {
proxy_pass http://auth-server:8080/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $server_name;
proxy_set_header X-Forwarded-Port $http_x_forwarded_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Cookie $http_cookie;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# Increase buffer sizes to handle large headers sent by Keycloak and its clients
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
location = /db-server {
return 302 /db-server/;
}
location /db-server/ {
rewrite ^/graphdb/(.*) /$1 break;
proxy_pass http://db-server:7200;
proxy_redirect http://db-server:7200/ /db-server/;
proxy_set_header X-Forwarded-Host $host;
}
}
}
Answering my own question: I was able to get the configuration working, although not the way I was hoping to achieve. My working setup (minimal sample can be found with explanation on GitHub) configures GraphDB to access Keycloak via its public URL (e.g., http://172.17.0.1/auth) instead of the Docker service URL (http://auth-server:8080).
On Keycloak's side it is necessary to configure the client with public
access and ensure that the access token contains roles and audience claim.
For local testing, it is not possible to use http://localhost
as public URL because the services interpret the URL as localhost within the service's container instead of the Docker host (my computer). Instead, I used http://172.17.0.1
which is the network interface created by Docker on the host system (IP may vary per system).