You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用反向代理时Oauth2 Bff无法连接Keycloak的问题修复

修复Keycloak反向代理下的颁发者不匹配问题

问题描述

将BFF应用通过反向代理连接Keycloak时,出现错误:配置元数据中的颁发者"http://localhost:8080/auth/realms/baeldung"与请求的颁发者"http://localhost:7080/auth/realms/baeldung"不匹配。核心原因是Keycloak默认使用自身服务地址作为颁发者,而反向代理改变了外部访问地址,导致元数据与实际请求地址不一致。

解决方案

1. 配置Keycloak领域的前端URL

登录Keycloak管理控制台,进入baeldung领域的领域设置 -> 常规页面,设置前端URL为反向代理的访问地址:

http://localhost:7080/auth/realms/baeldung

该配置会让Keycloak在生成OIDC元数据和JWT令牌时,使用这个反向代理地址作为颁发者,确保与BFF配置一致。

2. 确保反向代理正确传递转发头

反向代理需要传递X-Forwarded-*系列头,让Keycloak和BFF识别真实的外部请求地址。以Nginx为例,添加以下配置:

location /auth {
    proxy_pass http://localhost:8080/auth;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $host:$server_port;
}

3. 调整BFF的网关配置

在BFF的YML配置中,开启Spring Cloud Gateway对转发头的支持,确保网关能正确处理代理传递的地址信息:

spring:
  cloud:
    gateway:
      x-forwarded:
        enabled: true

4. 验证配置有效性

访问反向代理地址下的Keycloak OIDC元数据端点:

http://localhost:7080/auth/realms/baeldung/.well-known/openid-configuration

检查返回结果中的issuer字段,确认其值为http://localhost:7080/auth/realms/baeldung,与BFF配置中的issuer一致即可。

用户提供的BFF配置(已添加转发头支持)

# Custom properties to ease configuration overrides
# on command-line or IDE launch configurations
scheme: http
hostname: localhost
reverse-proxy-port: 7080
reverse-proxy-uri: ${scheme}://${hostname}:${reverse-proxy-port}
authorization-server-prefix: /auth
issuer: http://localhost:7080${authorization-server-prefix}/realms/baeldung
client-id: baeldung-confidential
client-secret: secret
username-claim-json-path: $.preferred_username
authorities-json-path: $.realm_access.roles
bff-port: 7081
bff-prefix: /bff
resource-server-port: 7084
audience:

server:
  port: ${bff-port}
  ssl:
    enabled: false

spring:
  cloud:
    gateway:
      routes:
        - id: bff
          uri: ${scheme}://${hostname}:${resource-server-port}
          predicates:
            - Path=/api/**
          filters:
            - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
            - TokenRelay=
            - SaveSession
            - StripPrefix=1
      x-forwarded:
        enabled: true # 新增转发头支持配置
  security:
    oauth2:
      client:
        provider:
          baeldung:
            issuer-uri: ${issuer}
        registration:
          baeldung:
            provider: baeldung
            authorization-grant-type: authorization_code
            client-id: ${client-id}
            client-secret: ${client-secret}
            scope: openid,profile,email,offline_access

com:
  c4-soft:
    springaddons:
      oidc:
        ops:
          - iss: ${issuer}
            authorities:
              - path: ${authorities-json-path}
            aud: ${audience}
        # SecurityFilterChain with oauth2Login() (sessions and CSRF protection enabled)
        client:
          client-uri: ${reverse-proxy-uri}${bff-prefix}
          security-matchers:
            - /api/**
            - /login/**
            - /oauth2/**
            - /logout/**
          permit-all:
            - /api/**
            - /login/**
            - /oauth2/**
            - /logout/connect/back-channel/baeldung
          post-logout-redirect-host: ${hostname}
          csrf: cookie-accessible-from-js
          oauth2-redirections:
            rp-initiated-logout: ACCEPTED
          back-channel-logout:
            enabled: true
            # internal-logout-uri: ${reverse-proxy-uri}${bff-prefix}/logout
            # should work too,  but there is no reason to go through the reverse proxy for this internal call
            internal-logout-uri: ${scheme}://localhost:${bff-port}/logout
        # SecurityFilterChain with oauth2ResourceServer() (sessions and CSRF protection disabled)
        resourceserver:
          permit-all:
            - /login-options
            - /error
            - /v3/api-docs/**
            - /swagger-ui/**
            - /actuator/health/readiness
            - /actuator/health/liveness

management:
  endpoint:
    health:
      probes:
        enabled: true
  endpoints:
    web:
      exposure:
        include: '*'
  health:
    livenessstate:
      enabled: true
    readinessstate:
      enabled: true

logging:
  level:
    root: INFO
    org:
      springframework:
        boot: INFO
        security: TRACE
        web: INFO

---
spring:
  config:
    activate:
      on-profile: ssl
server:
  ssl:
    enabled: true
scheme: https

---
spring:
  config:
    activate:
      on-profile: cognito
issuer: https://cognito-idp.us-west-2.amazonaws.com/us-west-2_RzhmgLwjl
client-id: 12olioff63qklfe9nio746es9f
client-secret: change-me
username-claim-json-path: username
authorities-json-path: $.cognito:groups
com:
  c4-soft:
    springaddons:
      oidc:
        client:
          oauth2-logout:
            baeldung:
              uri: https://spring-addons.auth.us-west-2.amazoncognito.com/logout
              client-id-request-param: client_id
              post-logout-uri-request-param: logout_uri

---
spring:
  config:
    activate:
      on-profile: auth0
issuer: https://dev-ch4mpy.eu.auth0.com/
client-id: yWgZDRJLAksXta8BoudYfkF5kus2zv2Q
client-secret: change-me
username-claim-json-path: $['https://c4-soft.com/user']['name']
authorities-json-path: $['https://c4-soft.com/user']['roles']
audience: bff.baeldung.com
com:
  c4-soft:
    springaddons:
      oidc:
        client:
          authorization-params:
            baeldung:
              audience: ${audience}
          oauth2-logout:
            baeldung:
              uri: ${issuer}v2/logout
              client-id-request-param: client_id
              post-logout-uri-request-param: returnTo

内容的提问来源于stack exchange,提问作者Kado

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 08:23:11