Keycloak NodeJS 适配器忽略 X-Forwarded-Proto

Keycloak NodeJS adapter ignores X-Forwarded-Proto

keycloak-connect, which is the recommended NodeJS adapter 来自 Keycloak 文档,没有考虑 X-Forwarded-Proto header 当受保护的应用程序位于 Apache 后面时反向代理。

确实 redirectUri 是这样构建的:

let host = request.hostname;
let headerHost = request.headers.host.split(':');
let port = headerHost[1] || '';
let protocol = request.protocol;*
let hasQuery = ~(request.originalUrl || request.url).indexOf('?');

let redirectUrl = protocol + '://' + host + (port === '' ? '' : ':' + port) + (request.originalUrl || request.url) + (hasQuery ? '&' : '?') + 'auth_callback=1';
由于反向代理,

request.protocol 始终是 "http",因此 redirectUri 没有预期的协议 (HTTPS)。

如果这是故意的而不是错误,即使客户端重定向到 HTTPS,在 redirectUri 中使用 HTTP 是否是一个安全漏洞?令牌不能同时暴露吗?

原来是 受保护应用程序端 的配置问题,这也涉及其他 Keycloak 适配器,例如 Java Servlet Filter adapter or the Spring adapter

默认情况下,任何受保护的应用程序都会忽略 X-Forwarded-Proto header。

NodeJS

所使用的 Web 框架(例如 Express)需要配置为考虑代理 header。

对于 Express,the documentation 声明应用程序应该信任代理,例如:

app.set('trust proxy', 'loopback');

Java 适配器

对于Spring,在application.properties中几乎没有像per the docs那样的配置:

server.tomcat.remote-ip-header=x-forwarded-for
server.tomcat.protocol-header=x-forwarded-proto 

对于JavaServlet Filter,有以下几种解决方案:

一个Tomcat阀门可以添加到server.xml:

<Valve className="org.apache.catalina.valves.RemoteIpValve" 
           internalProxies="127.0.0.1" 
           remoteIpHeader="x-forwarded-for" 
           proxiesHeader="x-forwarded-by" 
           protocolHeader="x-forwarded-proto" /> 

也可以实现一个新的Servlet Filter beforeKeycloak的Filter Adapter,注册在web.xml,就像在 this example.