'Keycloak Redirect URI is adding port zero to the url
Encountered redirect_uri error in keycloak. Found same issue logged at JIRA KEYCLOAK-7237, just want to check any work around? Anyone can help? Thank you in advance.
2018-06-30 11:34:13,996 WARN [org.keycloak.events] (default task-8) type=LOGIN_ERROR, realmId=Victz, clientId=portal, userId=null, ipAddress=, error=invalid_redirect_uri, redirect_uri=https://www.example.com:0/home
I am using apache http reverse proxy running on centos7, wildly 10, keycloak 3.4.3. has also tried in below environment but same error.
Tried in wildly 10, wildly 11, jboss 7.1, Keycloak 3.4.3 as well as keycloak 4.0
Also tried shutdown apache http and access directly to http://www.example.org:8080/home , but seems return_uri automatically been converted to https with port 0.
Please see below standalone.xml, tried removed below proxy-peer and request-dumper config but no luck.
<subsystem xmlns="urn:jboss:domain:undertow:4.0">
<buffer-cache name="default"/>
<server name="default-server">
<http-listener name="default" socket-binding="http" proxy-address-forwarding="true" enable-http2="true"/>
<https-listener name="https" socket-binding="https" proxy-address-forwarding="true" security-realm="ApplicationRealm" enable-http2="true"/>
<host name="default-host" alias="localhost">
<location name="/" handler="welcome-content"/>
<location name="/drive" handler="drive"/>
<access-log pattern="%h %l %u %t "%r" %s %b "%{i,Referer}" "%{i,User-Agent}" "%{i,COOKIE}" "%{o,SET-COOKIE}" %S "%I %T"" prefix="access."/>
<filter-ref name="server-header"/>
<filter-ref name="x-powered-by-header"/>
<http-invoker security-realm="ApplicationRealm"/>
</host>
<host name="example1" alias="example.com1,www.example.com1" default-web-module=“example1-0.1.war">
<location name="/drive" handler="drive”/>
<filter-ref name="proxy-peer"/>
<filter-ref name="request-dumper" priority="30"/>
</host>
<host name="example2" alias="example.com2,www.example.com2" default-web-module="example2-0.1.war">
<location name="/drive" handler="drive"/>
<filter-ref name="proxy-peer"/>
<filter-ref name="request-dumper" priority="30"/>
</host>
<host name="example3" alias="example.com3,www.example.com3" default-web-module="example3-0.1.war">
<location name="/drive" handler="drive"/>
<filter-ref name="proxy-peer"/>
<filter-ref name="request-dumper" priority="30"/>
</host>
</server>
<servlet-container name="default">
<jsp-config/>
<websockets/>
</servlet-container>
<handlers>
<file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
<file name="drive" path="/app/drive"/>
</handlers>
<filters>
<response-header name="server-header" header-name="Server" header-value="JBoss-EAP/7"/>
<response-header name="x-powered-by-header" header-name="X-Powered-By" header-value="Undertow/1"/>
<filter name="proxy-peer" class-name="io.undertow.server.handlers.ProxyPeerAddressHandler" module="io.undertow.core"/>
<filter name="request-dumper" class-name="io.undertow.server.handlers.RequestDumpingHandler" module="io.undertow.core"/>
</filters>
</subsystem>
Solution 1:[1]
I was having the same exact problem. My spring boot app sits behind nginx. I updated nginx to pass through the x-forwarded headers and updated the spring boot config with
spring boot yaml config:
server:
use-forward-headers: true
keycloak:
realm: myrealm
public-client: true
resource: myclient
auth-server-url: https://sso.example.com:443/auth
ssl-required: external
confidential-port: 443
nginx config:
upstream app {
server 1.2.3.4:8042 max_fails=1 fail_timeout=60s;
server 1.2.3.5:8042 max_fails=1 fail_timeout=60s;
}
server {
listen 443;
server_name www.example.com;
...
location / {
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-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port 443;
proxy_next_upstream error timeout invalid_header http_500;
proxy_connect_timeout 2;
proxy_pass http://app;
}
}
The specific change that made it work for me was adding keycloak.confidential-port. Once I added that it was no longer adding port 0 in the redirect_uri.
Hope that helps.
Solution 2:[2]
Context
When using Keycloak's Spring Boot client adapter behind a reverse proxy, the URL query parameter redirect_uri set by OAuthRequestAuthenticator.java may contain a port suffix :0 due to incomplete or false configuration.
Basic Problem
In order to construct the redirect_uri, the Spring Boot app needs to guess its public URL, including at least protocol and hostname, and possibly also the IP port. Behind a reverse proxy, this requires cooperation with the proxy, and/or explicit configuration.
Explanation for the :0
The :0, if present, was probably set by OAuthRequestAuthenticator.java (This loose handling may be considered a bug, but in the present case stems from incomplete configuration.): Keycloak recognized that the Spring Boot app is talking HTTPS, but it found no HTTPS port configuration, so it defaulted to zero.
Solution Steps
Assuming that:
- this is about a Spring Boot app
- running behind a reverse proxy
- acting as a Keycloak client
you need to ensure following things to solve the problem:
- configure the reverse proxy to add following headers
x-forwarded-fortelling the hostnamex-forwarded-prototelling whether the connection is secure or not
- configure the Spring Boot app to act correctly
- just read the current Spring Boot "How-to" Guide on running behind a proxy server (one concise screen page)
- configure Keycloak's Spring Boot adapter
- maybe you need to explicitly set the
confidential-portto443
- maybe you need to explicitly set the
Trouble-Shooting/Cross Check
Only one point: Assuming that this is about a Spring Boot app behind a reverse proxy, you should be able to use tcpdump or similar to monitor the unencrypted traffic (like -i lo -s0 -A) and see the HTTP headers. Any requests sent to the Spring Boot app should feature the headers required according to the Spring Boot Security How-to mentioned above (x-forwarded-for and x-forwarded-proto), otherwise, the proxy is misconfigured.
Solution 3:[3]
I was facing the similar issue. To make it work I have updated standalone.xml as below
Server config
<http-listener name="default" socket-binding="http" allow-unescaped-characters-in-url="true" redirect-socket="https" proxy-address-forwarding="true" enable-http2="true"/>
SSO config
<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
<realm name="myrealm">
<auth-server-url>https://sso.example.com:443/auth</auth-server-url>
<ssl-required>external</ssl-required>
<enable-cors>true</enable-cors>
<confidential-port>0</confidential-port>
</realm>
<secure-deployment name="mywar.war">
<realm>myrealm</realm>
<ssl-required>external</ssl-required>
<resource>myclient</resource>
<public-client>true</public-client>
</secure-deployment>
</subsystem>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | Milind D |
