使用反向代理后面的 keycloak 进行身份验证失败

Posted

技术标签:

【中文标题】使用反向代理后面的 keycloak 进行身份验证失败【英文标题】:Authentification with keycloak behind a reverse proxy is failing 【发布时间】:2020-10-30 13:11:12 【问题描述】:

以下设置完成:

我为 postgres-database、java 应用程序、keycloak 和 nginx-server(运行 angularjs-app)分别创建了一个 docker-container。

使用 docker-compose 生成的设置是:

version: '3.3'
services:
  nginx:
    build:
      context: frontend
    image: 127.0.0.1:5000/abe_frontend
    ports:
      - "80:80"
    logging:
      driver: "json-file"
      options:
        max-size: "100k"
        max-file: "10"
    restart: unless-stopped

  backend:
    build:
      context: backend
    image: 127.0.0.1:5000/abe_backend
    volumes:
      - ./data/abe_backend/data:/abedata
    expose:
      - "8080"
    depends_on:
      - postgres
    environment:
      SPRING_PROFILES_ACTIVE: docker
      SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/abe_db
      DB_USER: abe_user
      DB_PASSWORD: test
      KEYCLOAK_ENABLED: "true"
      KEYCLOAK_URL: "http://keycloak:8080/auth"
     KEYCLOAK_REALM: abe
      KEYCLOAK_RESOURCE: "abe_backend"
    logging:
      driver: "json-file"
      options:
        max-size: "100k"
        max-file: "10"
    restart: unless-stopped


  postgres:
    build:
      context: postgres
    image: 127.0.0.1:5000/abe_postgres
    volumes:
      - ./data/postgres/data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    environment:
      POSTGRES_DB: postgres
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: "test"
      PG_DATA: "/var/lib/postgresql/data/pgdata"
      KEYCLOAK_DB: "keycloak_db"
      KEYCLOAK_DB_USER: "keycloak_admin"
      KEYCLOAK_DB_PASSWORD: "test"
      ABE_DB: "abe_db"
      ABE_DB_USER: "abe_user"
      ABE_DB_PASSWORD: "test"
    logging:
      driver: "json-file"
      options:
        max-size: "200k"
        max-file: "10"

  keycloak:
    build:
      context: keycloak
    image: 127.0.0.1:5000/abe_keycloak
#    expose:
#      - "8080"
    ports:
      - "8282:8080"
    depends_on:
      - postgres
    environment:
      DB_VENDOR: "POSTGRES"
      DP_PORT: "5432"
      DB_ADDR: "postgres"
      DB_DATABASE: "keycloak_db"
      DB_USER: "keycloak_admin"
      DB_PASSWORD: "test"
      KEYCLOAK_USER: "admin"
      KEYCLOAK_PASSWORD: "test"
      PROXY_ADDRESS_FORWARDING: "true"
    logging:
      driver: "json-file"
      options:
        max-size: "200k"
        max-file: "10"

angularjs.app中的keycloak.json是从keycloak服务器下载的:


  "realm": "abe",
  "auth-server-url": "http://localhost:8282/auth/",
  "ssl-required": "external",
  "resource": "abe_frontend",
  "public-client": true,
  "confidential-port": 0

反向 nginx-proxy 传递前端和 keycloak 的请求:

location /service 
    include /etc/nginx/cors.conf;
    proxy_set_header Host $host;
    proxy_pass http://backend:8080/;


location /auth/ 
    proxy_pass http://keycloak:8080/auth/;
    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;

现在,当我在 localhost:80 中启动 angularjs-app 时,我在后端容器的控制台输出中收到以下错误:

 Failed to verify token: org.keycloak.common.VerificationException: Invalid token issuer. Expected 'http://keycloak:8080/auth/realms/abe', but was 'http://localhost:8282/auth/realms/abe'

【问题讨论】:

当您的 Angular 应用程序下载 keycloak.json 时,它请求的 URL 是什么?如果您使用keycloak:8080 验证颁发者,那么我认为您始终需要将您的密钥斗篷服务器称为keycloak:8080,而不是localhost:8282。即使它可能在两个地址都做出响应,但它可能需要保持一致,以使令牌发行者与预期相匹配。这是我最好的猜测。 我从 localhost:8282 下载了 keycloak.json,是的,这是真的,当在 keycloak.json 中,url 设置为 keycloak:8080,然后在 Chrome 中请求时,Keycloak-Server 无法访问。也许是因为 nginx 期望所有请求都是localhost/auth? 可以设置 keycloak 领域 frontendURL 以覆盖令​​牌中设置的颁发者。 任何后续@user3133542? 敬请期待正在解决该问题...您的解决方案无法解决问题...我仍然从上面得到 VerificationException 【参考方案1】:

由于您在 Keycloak 和您的前端前面有一个代理,因此您必须使用它并确保令牌颁发者、身份验证服务器和 url 相同。

假设您通过代理 (localhost:80) 访问您的应用程序,那么在您的情况下,有效的配置可能是:

"auth-server-url": "http://localhost/auth/"

location /auth/ 
    ...
    proxy_set_header    Host               localhost
    proxy_set_header    X-Forwarded-Host   localhost
    ...

为了让事情变得更简洁更好,您稍后需要设置代理主机或公共 DNS 名称,而不是 localhost

【讨论】:

以上是关于使用反向代理后面的 keycloak 进行身份验证失败的主要内容,如果未能解决你的问题,请参考以下文章

在 EC2 上部署的 docker 中使用 flask_oidc 和 nginx 反向代理的烧瓶应用程序在使用 keycloak 进行身份验证后给出未授权错误

keycloak 无效参数:redirect_uri 在反向代理后面

使用 nginx 反向代理后面的 keycloak 保护 nodejs 中的路由

在反向代理后面使用 Keycloak:无法打开管理员登录页面,因为内容混合

反向代理后面的 .NET 6 OAuth 身份验证:质询时重定向 url 错误

为啥带有 Netflix Zuul 反向代理的 Keycloak OAUTH2 不传递令牌