Search code examples
spring-bootspring-securityopenshiftkeycloakredhat-sso

Spring Boot Application using Keycloak, single sign on doesn't work behind an Apache Web Server


I have a Spring Boot + Spring Security application with RedhatSSO (Keycloak) as OIDC provider. This application is deployed on Openshift which assings it a route like this: http://my-app.cloud.mycompany.com/. The application has this context path: /my-app.

When I access a protected resource using the application's Openshift route address, http://my-app.cloud.mycompany.com/my-app/someProtectedResource, I am redirected to the Keycloak login page https://sso.mycompany.com where I login and I'm sent back to http://my-app.cloud.mycompany.com/my-app/sso/login. Then it exchanges the code for an access token and works without any problem allowing the access to the protected path.

However this isn't our target scenario since all applications are accessed through an Apache server with this url http://intranet.mycompany.com.

When I enter http://intranet.mycompany.com/my-app/someProtectedResource the request gets to my-app's pod in Openshift which redirects to the login form in https://sso.mycompany.com. BUT the URL the param redirect_uri is pointing at the application's Openshift route address http://my-app.cloud.mycompany.com/my-app/sso/login instead of http://intranet.mycompany.com/my-app/sso/login:

16:38:21,634 DEBUG [org.keycloak.adapters.OAuthRequestAuthenticator] (default task-59) there was no code
16:38:21,634 DEBUG [org.keycloak.adapters.OAuthRequestAuthenticator] (default task-59) redirecting to auth server
16:38:21,634 DEBUG [org.keycloak.adapters.OAuthRequestAuthenticator] (default task-59) callback uri: http://my-app.cloud.mycompany.com/my-app/sso/login

This way, after successfully logging in I am sent to the wrong address and the single sign on fails.

I am using this configuration:

Gradle:

springBootVersion = '1.5.10.RELEASE'
keycloakVersion = '3.4.3.Final'
...
mavenBom "org.keycloak.bom:keycloak-adapter-bom:${keycloakVersion}"
...
compile 'org.keycloak:keycloak-spring-boot-starter',
        'org.keycloak:keycloak-spring-security-adapter',

Spring Boot:

keycloak:
  auth-server-url: https://sso.mycompany.com/auth
  realm: MYREALM
  resource: my-app
  public-client: false
  principal-attribute: preferred_username
  credentials:
    secret: 99988877766655555444333
  autodetect-bearer-only: true
  ssl-required: external

How can I make the application realize its actual redirect_uri should have intranet.mycompany.com when it is behind an Apache Server?


Solution

  • We are using two kinds of Spring Boot applications and solved this for both of them:

    First off this is the necessary Apache configuration:

    RequestHeader set "Host" "intranet.mycompany.com"
    UseCanonicalName on
    ProxyPreserveHost on
    
    ProxyPass /my-app http://my-app.cloud.mycompany.com/my-app
    ProxyPassreverse /my-app http://my-app.cloud.mycompany.com/my-app
    

    Spring Boot jar running on Tomcat:

    To make the server use the X-Fowarded-* headers just add:

    server:
      context-path: /my-app
      use-forward-headers: true
    

    Spring Boot war running on JBoss:

    Update your standalone.xml setting proxy-address-forwarding="true":

    <http-listener name="default" proxy-address-forwarding="true" socket-binding="http" redirect-socket="https"/>