与 Keycloak 身份验证插件集成时,无法从 rest 客户端调用 nuxeo rest api
Posted
技术标签:
【中文标题】与 Keycloak 身份验证插件集成时,无法从 rest 客户端调用 nuxeo rest api【英文标题】:Unable to call nuxeo rest api from rest client when integrated with Keycloak authentication plugin 【发布时间】:2019-10-27 16:17:17 【问题描述】:我想将 keycloak 集成为在我的本地机器上运行的 nuxeo 平台的身份验证插件
设置详情 Nuxeo 平台版本:10.10(在 tomcat 9 上运行) 密钥斗篷版本:6.0.1 keycloak tomcat 适配器分发:keycloak-tomcat8-adapter-dist
我按照链接https://github.com/nuxeo/nuxeo/tree/master/nuxeo-services/login/nuxeo-platform-login-keycloak中提到的步骤进行操作。 在这里,我为 keycloak 6.0.1 版本构建了 nuxeo-platform-login-keycloak 插件。
在钥匙斗篷上, 我在新创建的领域“演示”下设置了一个身份验证客户端
客户详情可在 client configuration
我将角色创建为“成员”并为其添加了管理员角色 我创建了一个用户“keycloakuser”并添加到“成员”中。
当从浏览器点击 nuxeo ui 时,身份验证流程工作正常。它会将我重定向到 keycloak 的登录页面,在有效凭据上,它会将我重定向到 nuxeo ui。 与分配给它的“成员”组一起创建的用户。
错误场景 为了从 postman 调用 rest api,我配置了 Oauth2 进行身份验证。 授权网址:http://localhost:8080/auth/realms/demo/protocol/openid-connect/auth 令牌网址:http://localhost:8080/auth/realms/demo/protocol/openid-connect/token 客户端:testclient 客户端密码:***** 范围:openid
我使用通过Oauth2流程获得的access_token,以http://localhost:8190/nuxeo/api/v1/id/document_id进行API调用。它失败了
java.lang.ClassCastException: class org.apache.catalina.core.ApplicationHttpRequest cannot be cast to class org.apache.catalina.connector.RequestFacade (org.apache.catalina.core.ApplicationHttpRequest and org.apache.catalina.connector.RequestFacade are in unnamed module of loader java.net.URLClassLoader @39aeed2f)
at org.nuxeo.ecm.platform.ui.web.keycloak.DeploymentResult.invokeOn(DeploymentResult.java:79) [nuxeo-platform-login-keycloak-10.10.jar:?]
at org.nuxeo.ecm.platform.ui.web.keycloak.KeycloakAuthenticatorProvider.provide(KeycloakAuthenticatorProvider.java:56) [nuxeo-platform-login-keycloak-10.10.jar:?]
at org.nuxeo.ecm.platform.ui.web.keycloak.KeycloakAuthenticationPlugin.handleRetrieveIdentity(KeycloakAuthenticationPlugin.java:113) [nuxeo-platform-login-keycloak-10.10.jar:?]
at org.nuxeo.ecm.platform.ui.web.auth.NuxeoAuthenticationFilter.handleRetrieveIdentity(NuxeoAuthenticationFilter.java:1137) [nuxeo-platform-web-common-10.10.jar:?]
at org.nuxeo.ecm.platform.ui.web.auth.NuxeoAuthenticationFilter.doFilterInternal(NuxeoAuthenticationFilter.java:548) [nuxeo-platform-web-common-10.10.jar:?]
观察:
1. API 请求调用未命中 keycloak 端点
2.我尝试在两种情况下都打印reqqest类型(实际上是请求包装器类型)。
对于浏览器请求,它是 org.apache.catalina.connector.RequestFacade
,对于 api 请求,它是 org.apache.catalina.core.ApplicationHttpRequest
,它没有扩展 org.apache.catalina.connector.RequestFacade
问题: 1. 上述行为(第 2 点提及)在 tomcat 9 之前的 tomcat 版本中是否有所不同? 2. 是不是tomcat版本和keycloak adapters jar版本的兼容性问题?
【问题讨论】:
交叉发表于Nuxeo forum 【参考方案1】:答案较晚,但对新读者来说可能会派上用场。几个月前我遇到了完全相同的问题。这似乎是由于 nuxeo-platform-login-keycloak 插件中的错误。
我结束对org.nuxeo.ecm.platform.ui.web.keycloak.DeploymentResult
进行以下更改:
public class DeploymentResult
final static Logger LOGGER = LoggerFactory.getLogger(DeploymentResult.class);
private boolean isOk;
private static KeycloakDeployment keycloakDeployment;
private HttpServletRequest httpServletRequest;
private HttpServletResponse httpServletResponse;
private Request request;
private CatalinaHttpFacade facade;
public DeploymentResult(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
this.httpServletRequest = httpServletRequest;
this.httpServletResponse = httpServletResponse;
boolean isOk()
return isOk;
public static KeycloakDeployment getKeycloakDeployment()
return keycloakDeployment;
public Request getRequest()
return request;
public CatalinaHttpFacade getFacade()
return facade;
public DeploymentResult invokeOn(AdapterDeploymentContext deploymentContext)
// In Tomcat, a HttpServletRequest and a HttpServletResponse are wrapped in a Facades
if (httpServletRequest instanceof RequestFacade)
// Received upon logout.
request = unwrapRequest(httpServletRequest);
else
request = unwrapRequest(((ServletRequestWrapper) httpServletRequest).getRequest());
facade = new CatalinaHttpFacade(httpServletResponse, request);
if (keycloakDeployment == null)
keycloakDeployment = deploymentContext.resolveDeployment(facade);
if (keycloakDeployment.isConfigured())
isOk = true;
return this;
isOk = false;
return this;
/**
* Get the wrapper @link Request hidden in a @link ServletRequest object
*
* @param servletRequest, the main ServletRequest object
* @return the wrapper @link Request in @link ServletRequest
*/
private Request unwrapRequest(final ServletRequest servletRequest)
try
final Field f = servletRequest.getClass().getDeclaredField("request");
f.setAccessible(true); // grant access to (protected) field
return (Request) f.get(servletRequest);
catch (final NoSuchFieldException | IllegalAccessException e)
LOGGER.error("Couldn't unwrap request", e);
throw new RuntimeException(e);
catch (final Exception e)
LOGGER.error("Couldn't unwrap request", e);
throw e;
在使用这些更改构建和部署插件后,我被允许使用通过 Keycloak 获得的访问令牌调用 Nuxeo 的 REST API 和承载身份验证。
免责声明:我专注于让它发挥作用,而不是让它变得干净......
【讨论】:
以上是关于与 Keycloak 身份验证插件集成时,无法从 rest 客户端调用 nuxeo rest api的主要内容,如果未能解决你的问题,请参考以下文章
将Flutter应用程序的Facebook身份验证与Keycloak服务集成在一起
Spring Boot 我无法切换 keycloak 和基本身份验证
如何在 React 应用程序中集成 keycloak 身份验证?
如何在没有登录页面的情况下将 Keycloak 与 Spring Boot(API) 集成