Keycloak带上下文路径时获取OAuth2令牌报404问题求助
我在使用Keycloak对部署在/myclient路径下的应用做认证时,遇到报错:[invalid_token_response] 尝试获取OAuth 2.0 Access Token Response时出错:404 not found。
登录页URL看起来是正确的:
https://somedomain.com/keycloakt1/realms/myrealm/protocol/openid-connect/auth?response_type=code&client_id=myclient&scope=openid&state=DoA9p8UZDdTmWSldH4iL-R1NESKN13IUbzdSw5qbtsE%3D&redirect_uri=https://somedomain/myclient/login/oauth2/code/keycloak&nonce=-KmNNXpETgea6mgDXubuBxXG9pLxVjssWTYQ6xmfifA
用Postman请求https://somedomain.com/keycloakt1/realms/myclient/protocol/openid-connect/token能成功拿到令牌。
我的Keycloak运行在上下文路径/keycloakt1下,应用的application.yaml配置如下:
spring.security.oauth2.client.provider.keycloak.issuer-uri: 'https://somedomain.com/keycloakt1/realms/myrealm' spring.security.oauth2.client.registration.keycloak.client-id: myclient spring.security.oauth2.resourceserver.jwt.issuer-uri: 'https://somedomain.com/keycloakt1/realms/myrealm'
另外有个无上下文路径的Keycloak环境,相同应用配置能正常登录。
更新
查看/.well-known/openid-configuration的端点信息时,发现部分URI缺失/keycloakt1/路径,尤其是token_endpoint,这应该就是报错的原因:
"issuer": "https://somedomain/keycloakt1/realms/myclient", "authorization_endpoint": "https://somedomain/keycloakt1/realms/myclient/protocol/openid-connect/auth", -----> 缺失/keycloakt1/ "token_endpoint": "https://somedomain/realms/myclient/protocol/openid-connect/token", -----> 缺失/keycloakt1/ "introspection_endpoint": "https://somedomain/realms/myclient/protocol/openid-connect/token/introspect", -----> 缺失/keycloakt1/ "userinfo_endpoint": "https://somedomain/realms/myclient/protocol/openid-connect/userinfo", "end_session_endpoint": "https://somedomain/keycloakt1/realms/myclient/protocol/openid-connect/logout", "frontchannel_logout_session_supported": true, "frontchannel_logout_supported": true, -----> 缺失/keycloakt1/ "jwks_uri": "https://somedomain/realms/myclient/protocol/openid-connect/certs",
1. 修正Keycloak Realm的Frontend URL配置
进入Keycloak管理控制台,找到目标Realm(myrealm)的Realm Settings → General页面,确保Frontend URL配置正确,必须包含上下文路径/keycloakt1,格式为:
https://somedomain.com/keycloakt1/
这个配置直接决定了OpenID配置端点返回的所有外部可访问URL,是此类问题最常见的根源。
2. 手动指定Spring OAuth2客户端的端点URL
如果Frontend URL配置后问题仍未解决,可以在Spring Boot的application.yaml中手动覆盖自动发现的端点,避免依赖Keycloak的配置返回:
spring.security.oauth2.client.provider.keycloak: issuer-uri: 'https://somedomain.com/keycloakt1/realms/myrealm' token-uri: 'https://somedomain.com/keycloakt1/realms/myrealm/protocol/openid-connect/token' authorization-uri: 'https://somedomain.com/keycloakt1/realms/myrealm/protocol/openid-connect/auth' user-info-uri: 'https://somedomain.com/keycloakt1/realms/myrealm/protocol/openid-connect/userinfo' jwk-set-uri: 'https://somedomain.com/keycloakt1/realms/myrealm/protocol/openid-connect/certs' spring.security.oauth2.client.registration.keycloak.client-id: myclient spring.security.oauth2.resourceserver.jwt.issuer-uri: 'https://somedomain.com/keycloakt1/realms/myrealm'
3. 检查反向代理/负载均衡的头信息传递
如果Keycloak部署在反向代理或负载均衡之后,必须确保代理正确传递以下头信息,Keycloak依赖这些头生成正确的外部URL:
X-Forwarded-Proto:传递请求的协议(http/https)X-Forwarded-Host:传递请求的主机名X-Forwarded-Prefix:传递上下文路径/keycloakt1
以Nginx为例,需要添加如下配置:
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Prefix /keycloakt1;
同时,Keycloak启动时需要开启代理模式,添加启动参数:
--proxy edge
内容的提问来源于stack exchange,提问作者Michael

