反向代理背后的 Keycloak 混合了内部和外部地址

Keycloak behind reverse proxy mixes internal and external addresses

我正在尝试使用 nginx 在反向代理后面设置一个 keycloak 实例,我几乎做到了。

我的(部分)docker-撰写:

version: '3.4'                                                                          
                                                                                    
services:  
  [...]
                                                                                                                                                                                                                                                 
  keycloak:                                                                             
    image: jboss/keycloak                                                                                                                                     
    environment:                                                                        
      - DB_VENDOR=[vendor]
      - DB_USER=[user]                                                                      
      - DB_PASSWORD=[password]
      - DB_ADDR=[dbaddr]
      - DB_DATABASE=[dbname]
      - KEYCLOAK_USER=[adminuser]                                                         
      - KEYCLOAK_PASSWORD=[adminpassword]                                                       
      - KEYCLOAK_IMPORT=/tmp/my-realm.json                                           
      - KEYCLOAK_FRONTEND_URL=https://auth.mydomain.blah/auth                          
      - PROXY_ADDRESS_FORWARDING=true                                                   
      - REDIRECT_SOCKET=proxy-https
                                                 
  [...]

我的 nginx conf 只是

server {
    listen       443 ssl;
    server_name  auth.mydomain.blah;
  
    ssl_certificate /etc/letsencrypt/live/auth.mydomain.blah/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/auth.mydomain.blah/privkey.pem;

    location / {
        proxy_pass http://keycloak:8080;
    }
}

它有效,我可以从 https://auth.mydomain.blah/auth 但是 访问 keycloak 当我查看 https://auth.mydomain.blah/auth/realms/campi/.well-known/openid-configuration 我得到这个:

{
  "issuer": "https://auth.mydomain.blah/auth/realms/campi",
  "authorization_endpoint": "https://auth.mydomain.blah/auth/realms/campi/protocol/openid-connect/auth",
  "token_endpoint": "http://keycloak:8080/auth/realms/campi/protocol/openid-connect/token",
  "introspection_endpoint": "http://keycloak:8080/auth/realms/campi/protocol/openid-connect/token/introspect",
  "userinfo_endpoint": "http://keycloak:8080/auth/realms/campi/protocol/openid-connect/userinfo",
  "end_session_endpoint": "https://auth.mydomain.blah/auth/realms/campi/protocol/openid-connect/logout",
  "jwks_uri": "http://keycloak:8080/auth/realms/campi/protocol/openid-connect/certs",
  "check_session_iframe": "https://auth.mydomain.blah/auth/realms/campi/protocol/openid-connect/login-status-iframe.html",
  [...]

为什么 keycloak 会混合内部和外部 uris?我错过了什么?

我们公司也有同样的“问题”。

通过 keycloak-admin.internaldomain.com 在内部访问它,但对于我们的普通用户,他们在外部访问 keycloak.externaldomain.com。

如果我在内部加载 .well-known/openid-configuration url 它有内部地址,但是使用外部加载它 url 它有那个。

除了偶尔向看到差异的工程师解释之外,它对我们没有造成任何问题。否则,没问题。

看来 keycloak 只使用它正在访问的任何域。

https://www.keycloak.org/docs/latest/server_installation/index.html#_setting-up-a-load-balancer-or-proxy

你的反向 proxy/nginx 没有正确转发主机头,所以 Keycloak 不知道请求使用了哪个 host/protocol 并且它使用 backend/internal 主机名。您需要设置几 proxy_set_header 行:

server {
    listen       443 ssl;
    server_name  auth.mydomain.blah;
  
    ssl_certificate /etc/letsencrypt/live/auth.mydomain.blah/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/auth.mydomain.blah/privkey.pem;

    location / {
            proxy_pass          http://keycloak:8080;
            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-Host   $host;
            proxy_set_header    X-Forwarded-Server $host;
            proxy_set_header    X-Forwarded-Port   $server_port;
            proxy_set_header    X-Forwarded-Proto  $scheme;
    }
}