Search code examples
springkeycloakaws-application-load-balancerkeycloak-services

Keycloak "invalid credentials" error after login when access through Load Balancer


I'm requesting your help about the "invalid credentials" error after login into Keycloak, specifically when accessing it from the Load Balancer.

Infrastructure and Application Setup:

Two EC2 instances - node A and node B - running an application on port 8082:

In Node A, I also have Keycloak running (port 8443) which should provide authentication to applications running on port 8082 of both nodes.

Both nodes are served through an AWS Application Load Balancer.

(These hostnames are obviously not the real ones, but they follow the same pattern.)

Issue:

If I access application on 8082 directly through each node's hostname, I am redirected to Keycloak login page,and then redirected successfully to the application itself. For example, accessing the app through https://scdf-01b.aws.net:8082 works fine.

But if I try to do the same through the Load Balancer hostname, I am redirected to the Keycloak login page, I login, but then I see the "invalid credentials" error. enter image description here

Still, although I get this "invalid credentials" error which does not allow me to access application running on port 8082, I can see, through the Keycloak admin console, that a session was created for the login user.

Current configuration:

I am running Keycloak v20.0.1.

My Keycloak's conf/keycloak.conf file:

# Basic settings for running in production. Change accordingly before deploying the server.

# Database

# The database vendor.
db=oracle

# The username of the database user.
db-username=xxx_KEYCLOAK_SCHEMA

# The password of the database user.
db-password=xxxxxxx

# The full database JDBC URL. If not provided, a default URL is set based on the selected database vendor.
db-url=jdbc:oracle:thin:@xxxxxx

# Observability

# If the server should expose healthcheck endpoints.
#health-enabled=true

# If the server should expose metrics endpoints.
#metrics-enabled=true

# HTTP

http-enabled=false
https-key-store-file=/etc/ssl/certs/keystore.p12
https-key-store-type=PKCS12
https-key-store-password=xxxxx
#https-key-password=xxxxx

# The file path to a server certificate or certificate chain in PEM format.
#https-certificate-file=${kc.home.dir}conf/server.crt.pem

# The file path to a private key in PEM format.
#https-certificate-key-file=${kc.home.dir}conf/server.key.pem

# The proxy address forwarding mode if the server is behind a reverse proxy.
#proxy=reencrypt

# Do not attach route to cookies and rely on the session affinity capabilities from reverse proxy
#spi-sticky-session-encoder-infinispan-should-attach-route=false

# Hostname for the Keycloak server.
hostname=scdf-01a.aws.net

My script to start Keycloak:

#!/bin/bash
./keycloak/keycloak-20.0.1/bin/kc.sh start

My application's (8082) application.yml:

...
spring:
  autoconfigure:
    exclude:
    - org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
  security:
    authorization:
      provider-role-mappings:
        keycloak-oidc:
          map-oauth-scopes: true
    oauth2:
      client:
        provider:
          keycloak-oidc:
            issuer-uri: https://scdf-01a.aws.net:8443/realms/smdm
            jwk-set-uri: https://scdf-01a.aws.net:8443/realms/smdm/protocol/openid-connect/certs
            token-uri: https://scdf-01a.aws.net:8443/realms/smdm/protocol/openid-connect/token
            user-info-uri: https://scdf-01a.aws.net:8443/realms/smdm/protocol/openid-connect/userinfo
        registration:
          keycloak-oidc:
            authorization-uri: https://scdf-01a.aws.net:8443/realms/smdm/protocol/openid-connect/auth
            client-id: quartz-client
            client-secret: xxxx
            scope: openid,profile,roles,quartz.user,quartz.admin
      resourceserver:
        jwt:
          issuer-uri: https://scdf-01a.aws.net:8443/auth/realms/smdm

My client configuration in Keycloak Admin dashboard: enter image description here enter image description here

Other Things I Tried:

I've tried to test --proxy=edge, --proxy=passthrough options when starting Keycloak, but with no success.

I've tried to set the next environment variables to Keycloak, also with no success:

export KC_HOSTNAME=scdf-01a.aws.net
export KC_HOSTNAME_STRICT_HTTPS=false
export KC_HTTP_ENABLED=true
export KC_PROXY_ADDRESS_FORWARDING=true
export KC_HOSTNAME_STRICT=false

I also tried to disable the Client Configuration in Keycloak dashboard, but:

  • Although I was able to remove the client-secret from the application's application.yml and I was still able to login;
  • When I tried to access through the Load Balancer hostname, I received the same "invalid credentials" error.

Other Notes:

I have other applications running on both nodes on different ports, that should also be authenticated with Keycloak.For those applications, I'm getting the exact behavior described above for app running on port 8082.

The client-id and client-secret are correctly set in the application.yml. Again, everything works when accessing directly one of the nodes, but not when accessing through the Load Balancer.

My Load Balancer does not terminate HTTPS. I have: User --HTTPS-> Load Balancer --HTTPS-> Server/App


Solution

  • This issue was solved by enabling sticky sessions in the Application Load Balancer.

    I used ALB generated cookies and the default 1 day expiration time.

    Thank you all for your contributions.