Springboot application with keycloak adapter not working behind an HTTPS proxy

Hi
I have a small spring boot application being protected by keycloak 17.0.1 springboot adapter.
It works fine with http but when running behind a https proxy (responsible for offload the https external requests to internal http requests) it always fails because the redirect_url still refers http.
Entry point for the application is https://entry2-pp.domain/public-library/
When calling keycloak for login, the redirect URL still refers http
See below, the debug from class org.keycloak
2022-06-04 18:10:58.016 DEBUG 72966 — [nio-8081-exec-2] o.k.adapters.OAuthRequestAuthenticator : redirecting to auth server
2022-06-04 18:10:58.016 DEBUG 72966 — [nio-8081-exec-2] o.k.adapters.OAuthRequestAuthenticator : callback uri: http://entry2-pp.domain/public-library/books
2022-06-04 18:10:58.023 DEBUG 72966 — [nio-8081-exec-2] o.k.adapters.OAuthRequestAuthenticator : Sending redirect to login page: https://am3-pp.domain/realms/AAAAAA/protocol/openid-connect/auth?response_type=code&client_id=public-library&redirect_uri=http%3A%2F%2Fentry2-pp.domain%2Fpublic-library%2Fbooks&state=a1bca340-9af0-41b2-8f7a-cc3a37ce00cc&login=true&scope=openid

Any suggestion would be very much appreciated.
Thanks

1 Like

Can you show your keycloak adapter configuration?

Hi
My springboot application.properties is below:
----
server.connection-timeout=5000
server.port = 8081
server.use-forwarded-headers=true
# keycloak.enabled = false

logging.level.org.keycloak=DEBUG
keycloak.realm=AAAAAA
keycloak.resource=public-library
keycloak.auth-server-url=https://am3-pp.domain
keycloak.ssl-required=external
keycloak.public-client=true

keycloak.securityConstraints[0].authRoles[0]=libMember
keycloak.securityConstraints[0].authRoles[1]=Librarian
keycloak.securityConstraints[0].securityCollections[0].name=libmember resource
keycloak.securityConstraints[0].securityCollections[0].patterns[0]=/books

keycloak.securityConstraints[1].authRoles[0]=Librarian
keycloak.securityConstraints[1].securityCollections[0].name=librarian resource
keycloak.securityConstraints[1].securityCollections[0].patterns[0]=/manager
----
Thanks

Hi there
Thanks for the help.I’ve posted my configuration.

Hi
I’ve tried to use keycloak.ssl-required=all
As you can see below, i still have references to http but the redirect_url is now https.
However now, is specifying port 0 !?
Which makes it even more wrong: redirect_url is now:
"https://entry2-pp.domain:0/ … "

See below the log from the adapter

2022-06-07 13:54:05.939 DEBUG 19104 — [nio-8081-exec-2] o.k.adapters.OAuthRequestAuthenticator : redirecting to auth server
2022-06-07 13:54:05.943 DEBUG 19104 — [nio-8081-exec-2] o.k.adapters.OAuthRequestAuthenticator : callback uri: http://entry2-pp.domain/public-library/books
2022-06-07 13:54:05.947 DEBUG 19104 — [nio-8081-exec-2] o.keycloak.adapters.KeycloakDeployment : Resolving URLs from https://am3-pp.domain/realms/AAAAA/.well-known/openid-configuration
2022-06-07 13:54:06.624 INFO 19104 — [nio-8081-exec-2] o.keycloak.adapters.KeycloakDeployment : Loaded URLs from https://am3-pp.domain/realms/AAAAA/.well-known/openid-configuration
2022-06-07 13:54:06.632 DEBUG 19104 — [nio-8081-exec-2] o.k.adapters.OAuthRequestAuthenticator : Sending redirect to login page: https://am3-pp.domain/realms/AAAAA/protocol/openid-connect/auth?response_type=code&client_id=public-library&redirect_uri=https%3A%2F%2Fentry2-pp.domain %3A0%2Fpublic-library%2Fbooks&state=830a4e5d-b1a0-4bc4-ad9e-16b845ebb99d&login=true&scope=openid

Any help would be appreciated.
Thanks

Do you have a reverse proxy in front of your application?

I’m not sure which method the adapter uses to determine on which port the external url is called on, but I suppose you can use the conf keycloak.confidential-port: 443 or 80 if it’s your case.

Hi
Yes, I do have an apache proxy in front. My flow is:
HTTPS Incoming requests → F5 (terminates SSL) → Apache (already in HTTP) → Application or keycloak

Seting up keycloak.confidential-port: 443 helped to solve the “:0” issue in the redirect_url but still having problems with references to http. Now i’m able to login but it fails on the next step. See the log below, where you can find the references to http and the request failling:

2022-06-09 08:46:55.037 INFO 20770 — [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 8 ms
2022-06-09 08:46:55.357 DEBUG 20770 — [nio-8081-exec-2] o.k.adapters.PreAuthActionsHandler : adminRequest http://entry2-pp.domain/public-library/css/style.css
2022-06-09 08:46:55.357 DEBUG 20770 — [nio-8081-exec-2] .k.a.t.AbstractAuthenticatedActionsValve : AuthenticatedActionsValve.invoke /public-library/css/style.css
2022-06-09 08:46:55.358 DEBUG 20770 — [nio-8081-exec-2] o.k.a.AuthenticatedActionsHandler : AuthenticatedActionsValve.invoke http://entry2-pp.domain/public-library/css/style.css
2022-06-09 08:46:55.358 DEBUG 20770 — [nio-8081-exec-2] o.k.a.AuthenticatedActionsHandler : Policy enforcement is disabled.
2022-06-09 08:46:58.815 DEBUG 20770 — [nio-8081-exec-3] o.k.adapters.PreAuthActionsHandler : adminRequest http://entry2-pp.domain/public-library/books
2022-06-09 08:46:58.823 DEBUG 20770 — [nio-8081-exec-3] o.k.adapters.OAuthRequestAuthenticator : there was no code
2022-06-09 08:46:58.823 DEBUG 20770 — [nio-8081-exec-3] o.k.adapters.OAuthRequestAuthenticator : redirecting to auth server
2022-06-09 08:46:58.828 DEBUG 20770 — [nio-8081-exec-3] o.k.adapters.OAuthRequestAuthenticator : callback uri: http://entry2-pp.domain/public-library/books
2022-06-09 08:46:58.833 DEBUG 20770 — [nio-8081-exec-3] o.keycloak.adapters.KeycloakDeployment : Resolving URLs from https://am3-pp.domain/realms/AAAAA/.well-known/openid-configuration
2022-06-09 08:46:59.365 INFO 20770 — [nio-8081-exec-3] o.keycloak.adapters.KeycloakDeployment : Loaded URLs from https://am3-pp.domains/realms/AAAAAA/.well-known/openid-configuration
2022-06-09 08:46:59.380 DEBUG 20770 — [nio-8081-exec-3] o.k.adapters.OAuthRequestAuthenticator : Sending redirect to login page: https://am3-pp.domains/realms/AAAAAA/protocol/openid-connect/auth?response_type=code&client_id=public-library&redirect_uri=https%3A%2F%2Fentry2-pp.domain%2Fpublic-library%2Fbooks&state=273d4208-5d1e-43ea-a342-0af4eab5c42f&login=true&scope=openid
2022-06-09 08:47:07.772 DEBUG 20770 — [nio-8081-exec-5] o.k.adapters.PreAuthActionsHandler : adminRequest http://entry2-pp.domains/public-library/books?state=273d4208-5d1e-43ea-a342-0af4eab5c42f&session_state=dcc73ef3-5f2f-4317-9566-41f8eaaf1aaa&code=172872b0-0f74-42c8-978b-73bdaf9ad9e0.dcc73ef3-5f2f-4317-9566-41f8eaaf1aaa.a994565b-bfab-4b59-acf5-00b2c20b1a1d
2022-06-09 08:47:07.774 DEBUG 20770 — [nio-8081-exec-5] o.k.adapters.OAuthRequestAuthenticator : there was a code, resolving

2022-06-09 08:47:07.774 ERROR 20770 — [nio-8081-exec-5] o.k.adapters.OAuthRequestAuthenticator : Adapter requires SSL. Request: http://entry2-pp.domains/public-library/books?state=273d4208-5d1e-43ea-a342-0af4eab5c42f&session_state=dcc73ef3-5f2f-4317-9566-41f8eaaf1aaa&code=172872b0-0f74-42c8-978b-73bdaf9ad9e0.dcc73ef3-5f2f-4317-9566-41f8eaaf1aaa.a994565b-bfab-4b59-acf5-00b2c20b1a1d

2022-06-09 08:47:07.868 DEBUG 20770 — [nio-8081-exec-6] o.k.adapters.PreAuthActionsHandler : adminRequest http://entry2-pp.domains/public-library/css/style.css
2022-06-09 08:47:07.869 DEBUG 20770 — [nio-8081-exec-6] .k.a.t.AbstractAuthenticatedActionsValve : AuthenticatedActionsValve.invoke /public-library/css/style.css
2022-06-09 08:47:07.869 DEBUG 20770 — [nio-8081-exec-6] o.k.a.AuthenticatedActionsHandler : AuthenticatedActionsValve.invoke http://entry2-pp.domain/public-library/css/style.css
2022-06-09 08:47:07.869 DEBUG 20770 — [nio-8081-exec-6] o.k.a.AuthenticatedActionsHandler : Policy enforcement is disabled.

I had a similar problem recently. I solved it by setting spring-boot property:

server.forward-headers-strategy=NATIVE

See also Spring-Boot doc “Running Behind a Front-end Proxy Server”

Thanks @mduchrow
Unfortunately i had already tried that without success. I think the issue is related with the adapter implementation

By default, ssl is required for all external (non localhost) requests.

You can use ssl-required: none to disable this behavior.

Obviously, this should not be used in production.

Thanks @weltonrodrigo but that is not really the objective.
What I’m testing is exactly the opposite; I’m testing the PRODUCTION deployment

I have exactly the same problem in a spring (non spring boot) application running behind an apache reverse proxy.

Reverse proxy is configured with:

ProxyRequests Off
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"

Keycloak.json:

  "realm": "myrealm",
  "resource": "myresource",
  "auth-server-url": "https://login.sso-migration.example.com/auth",
  "ssl-required": "all",
  "confidential-port": 443,
  "use-resource-role-mappings": true,
  "bearer-only": false,
  "enable-basic-auth": false,
  "expose-token": false,
  "credentials": {
    "secret": "mysecret"
  },
  "connection-pool-size": 20,
  "disable-trust-manager": true,
  "allow-any-hostname": true

The protocol of the redirect_uri param for the keycloak request is correctly “https” (since adding ssl-required: all to keycloak.json) and the port is blank since adding confidential-port: 443.
Nevertheless the request fails at my application:

S 2022-09-09 15:46:52,777 [http-nio-8080-exec-607] DEBUG org.keycloak.adapters.PreAuthActionsHandler - adminRequest http://myapp.example.com/myapp/
S 2022-09-09 15:46:52,780 [http-nio-8080-exec-607] DEBUG org.keycloak.adapters.OAuthRequestAuthenticator - there was no code
S 2022-09-09 15:46:52,781 [http-nio-8080-exec-607] DEBUG org.keycloak.adapters.OAuthRequestAuthenticator - redirecting to auth server
S 2022-09-09 15:46:52,781 [http-nio-8080-exec-607] DEBUG org.keycloak.adapters.OAuthRequestAuthenticator - callback uri: http://myapp.example.com/myapp/
S 2022-09-09 15:46:52,784 [http-nio-8080-exec-607] DEBUG org.keycloak.adapters.OAuthRequestAuthenticator - Sending redirect to login page: https://login.sso-migration.example.com/auth/realms/myrealm/protocol/openid-connect/auth?response_type=code&client_id=myresource&redirect_uri=https%3A%2F%2Fmyapp.example.com%2Fmyapp%2F&state=aaf2342b-82d5-4dac-9010-dcc6029c8a4e&login=true&scope=openid
S 2022-09-09 15:48:13,729 [http-nio-8080-exec-605] DEBUG org.keycloak.adapters.PreAuthActionsHandler - adminRequest http://myapp.example.com/myapp/?state=aaf2342b-82d5-4dac-9010-dcc6029c8a4e&session_state=cf46dace-7b9f-4850-929e-9e11da30b75c&code=80c24aec-ff10-41a2-a9f5-89332ac2362f.cf46dace-7b9f-4850-929e-9e11da30b75c.32c18f21-6c95-4a6a-a757-a8a0a2710924
S 2022-09-09 15:48:13,732 [http-nio-8080-exec-605] DEBUG org.keycloak.adapters.OAuthRequestAuthenticator - there was a code, resolving
S 2022-09-09 15:48:13,732 [http-nio-8080-exec-605] ERROR org.keycloak.adapters.OAuthRequestAuthenticator - Adapter requires SSL. Request: http://myapp.example.com/myapp/?state=aaf2342b-82d5-4dac-9010-dcc6029c8a4e&session_state=cf46dace-7b9f-4850-929e-9e11da30b75c&code=80c24aec-ff10-41a2-a9f5-89332ac2362f.cf46dace-7b9f-4850-929e-9e11da30b75c.32c18f21-6c95-4a6a-a757-a8a0a2710924

Finally I am not sure whether setting “ssl-required” to “all” is the correct way to get keycloak to write a “https”-redirect_uri. I thought that configuring reverse proxy with
"RequestHeader set X-Forwarded-Proto "https"
could be enough but it isn’t.

Any ideas what else to try?

For future readers:

Setting ssl-required to “all” was not the correct way.

Solution was adding the RemoteIpFilter to Tomcat (which is probably comparable of configuring server.forward-headers-strategy in a spring boot application) so that the x-forwarded-proto header is used by Tomcat:

    <filter>
		<filter-name>RemoteIpFilter</filter-name>
		<filter-class>org.apache.catalina.filters.RemoteIpFilter</filter-class>
		<init-param>
			<param-name>protocolHeader</param-name>
			<param-value>x-forwarded-proto</param-value>
		</init-param>
	</filter>

	<filter-mapping>
		<filter-name>RemoteIpFilter</filter-name>
		<url-pattern>/*</url-pattern>
		<dispatcher>REQUEST</dispatcher>
	</filter-mapping>

Were you able to find the solution. I’m also facing the same problem.

Unfortunately not.
I still think this is an issue with the adapter but couldn’t find a solution.
I’ve abandoned the idea.

Me too! :unamused:
Is there any example code for a docker application with nginx, keycloak and tomcat?

A sample docker-compose file it use to test nginx and keycloak

version: '3'

volumes:
  postgres_data_v2:
    driver: local

services:
  postgres:
    image: postgres:11
    volumes:
      - postgres_data_v2:/var/lib/postgresql/data2
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: password
    ports:
      - 5433:5432
  keycloak:
    image: quay.io/phasetwo/phasetwo-keycloak:latest
    container_name: mykeycloak
    volumes:
      - ./realm/realm-export.json:/tmp/import-realm.json
    environment:
      PROXY_ADDRESS_FORWARDING: 'true'
      KEYCLOAK_USER: admin
      KEYCLOAK_PASSWORD: password
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: password
      KC_DB_URL_HOST: postgres
      KC_DB_URL_DATABASE: keycloak
      KC_DB_SCHEMA: public
      KC_DB_USERNAME: keycloak
      KC_DB_PASSWORD: password
      KC_HOSTNAME_STRICT: 'false'
      KC_HTTP_ENABLED: 'true' 
      KC_PROXY: 'edge'
      KC_LOG_LEVEL: INFO
      JAVA_OPTS: '-server -Xms1024m -Xmx1024m'
      KEYCLOAK_IMPORT: /tmp/import-realm.json
    command: start
    ports:
      - 8080:8080
    depends_on:
      - postgres
  rproxy: 
    image: nginx:latest
    container_name: nginx_rproxy
    restart: unless-stopped
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./www:/data/www:ro
      - ./cert:/etc/cert:ro
    ports:
      - 80:80
      - 443:443

Nginx conf

% cat nginx/nginx.conf 
events {
}
http {
  server {
    listen 80;

    server_name _;
    return 301 https://$host$request_uri;
  }
  server {
    
    # settings added upstream sent too big header while 
    proxy_busy_buffers_size   512k;
    proxy_buffers   4 512k;
    proxy_buffer_size   256k;
 
    include       /etc/nginx/mime.types;
   
    listen 443 ssl;

    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_certificate  /etc/cert/fullchain.pem;
    ssl_certificate_key /etc/cert/privkey.pem;

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header Content-Security-Policy "default-src 'self'; frame-ancestors 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src https://my-test-host.com;";   
    #add_header X-Content-Type-Options nosniff;    # cannot apply now because of open keycloak issue https://issues.redhat.com/browse/KEYCLOAK-17076
    add_header X-XSS-Protection: "1; mode=block";

    proxy_set_header X-Forwarded-For $proxy_protocol_addr; # To forward the original client's IP address 
    proxy_set_header X-Forwarded-Proto $scheme; # to forward the  original protocol (HTTP or HTTPS)
    proxy_set_header Host $host; # to forward the original host requested by the client

    location / {
      proxy_pass http://mykeycloak:8080;
    }
  }
}

1 Like

I am using Spring Security rather than Spring Boot. The strategy that worked for me was a variation on that of @olla above. Set ssl-required to “all”, confidential-port to “443” in keycloak.json. I added the filters to my web.xml but it didn’t work for me, adding the following to my tomcat server.conf:

<Valve className="org.apache.catalina.valves.RemoteIpValve"
      remoteIpHeader="x-forwarded-for"
      protocolHeader="x-forwarded-proto"
      protocolHeaderHttpsValue="https" />

and

ProxyRequests Off
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto “https”

In my apache ssl config got it working.