Spring Security - Keycloak fails with Invalid credentials after login when reached from docker container - spring

I'm building a spring app using keycloak as identity provider. I use microservices with it. What I want to do is sending the request to api gateway, api gateway communicates with keycloak and authenticate the request (show login page if not). And then reach the service with an authenticated request. Everything works when I run it on my local environment but when I dockerize all the applications (api-gateway, user-service(resource service) and keycloak), I see the login page, I put my credentials and it returns me to a page saying "Invalid credentials". I'm assuming something is wrong with my application.yml but couldnt figure out what.
What I want to achieve is this (Every app seen here runs in docker)
This is how the error looks like
application.yml(api-gateway)
...
cloud:
discovery:
enabled: true
gateway:
default-filters:
- TokenRelay
discovery:
locator:
enabled: true
lowerCaseServiceId: true
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://keycloak:8080/auth/realms/master
client:
provider:
keycloak:
token-uri: http://keycloak:8080/auth/realms/master/protocol/openid-connect/token
authorization-uri: http://127.0.0.1:8972/auth/realms/master/protocol/openid-connect/auth
userinfo-uri: http://keycloak:8080/auth/realms/master/protocol/openid-connect/userinfo
user-name-attribute: preferred_username
registration:
keycloak-kicktipp-client:
provider: keycloak
client-id: ${AUTHENTICATOR_CLIENT_ID}
client-secret: ${AUTHENTICATOR_CLIENT_SECRET}
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
...
application.yml(user-service)
eureka.client.serviceUrl.defaultZone=http://naming-server:8761/eureka
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://keycloak:8080/auth/realms/master
spring.cloud.gateway.default-filters=TokenRelay
docker-compose.yml
...
keycloak:
container_name: keycloak
networks:
- kicktipp-docker-network
ports:
- '8972:8080'
- '8443:8443'
environment:
- KEYCLOAK_USER=${AUTHENTICATOR_USER}
- KEYCLOAK_PASSWORD=${AUTHENTICATOR_PASSWORD}
volumes:
- keycloak:/opt/jboss/keycloak/standalone/data/
image: xxx/keycloak:14.0.0
api-gateway:
container_name: api-gateway
environment:
- AUTHENTICATOR_CLIENT_ID=${AUTHENTICATOR_CLIENT_ID}
- AUTHENTICATOR_CLIENT_SECRET=${AUTHENTICATOR_CLIENT_SECRET}
networks:
- kicktipp-docker-network
depends_on:
- naming-server
- keycloak
ports:
- '80:8765'
# - '8765:8080'
restart: unless-stopped
image: xxx/api-gateway:latest
user-service:
container_name: user-service
depends_on:
- naming-server
networks:
- kicktipp-docker-network
ports:
- '8080:8080'
image: xxx/user-service:latest
...

Related

Connection refused when connecting to keycloak container from backend container

I have two containers backend (spring boot application) and Keycloak. if I run keycloak in a container and backend locally : it works
If both of them are run in container the backend doesn't start and shows the following error :
Failed to instantiate [org.springframework.security.oauth2.jwt.JwtDecoder]: Factory method 'jwtDecoderByIssuerUri' threw exception; nested exception is java.lang.IllegalArgumentException: Unable to resolve the Configuration with the provided Issuer of "http://keycloak:8082/auth/realms/myrealm"
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://keycloak:8082/auth/realms/myrealm/.well-known/openid-configuration": Connection refused (Connection refused);
following are my configs :
docker-compose :
services:
keycloak:
image: jboss/keycloak:8.0.1
command:
- " -b 0.0.0.0"
container_name: "keycloak"
networks:
- myproject
volumes:
- "./keycloak/realm-export.json:/opt/jboss/keycloak/bin/keycloak_export_dir/realm-export.json"
environment:
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: admin
KEYCLOAK_IMPORT: /opt/jboss/keycloak/bin/keycloak_export_dir/realm-export.json
ports:
- "8082:8080"
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: "backend"
environment:
- spring.oauth2.resourceserver.jwt.issuer-uri= http://keycloak:8082/auth/realms/myrealm
links:
- keycloak
networks:
- myproject
restart: on-failure
ports:
- "8080:8080"
networks:
myproject:
driver: bridge
application.yml:
application:
name: backend
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://localhost:8082/auth/realms/myrealm
do you have any Idea why do I get connection refused ?
any help is appreciated :)
Your Keycloak container using the following port configuration
ports:
- "8082:8080"
That mean:
Keycloak is reachable from Outside via Port 8082.
But internally (in this docker network), keycloak is only reachable via the exposed 8080 port. So your backend application need to connect (internally) to http://keycloak:8080

My Spring cloud gateway gets ResourceAccessException for Keycloak while using docker-compose

I have a sample project which consists of a registry module that starts a Eureka server, a spring cloud gateway, and Keycloak.
The problem is by running Keycloak, registry using docker-compose and the gateway as a normal application, everything works, that is, when I want to see the eureka dashboard, I get redirected to Keycloak to authenticate and then redirected to the dashboard, but it is not the case when I execute the gateway together with others using docker-compose and it complains:
Caused by: java.lang.IllegalArgumentException: Unable to resolve Configuration with the provided Issuer of "http://127.0.0.1:8090/auth/realms/dev"
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://127.0.0.1:8090/auth/realms/dev/.well-known/openid-configuration": Connection refused
while I can get the configuration by pasting the link in the browser.
I expect it to be my misconfiguration with docker-compose and I would appreciate it if you can give me some ideas.
gateway application.yml
spring:
application:
name: gateway
cloud:
gateway:
routes:
- id: firstService
uri: lb://first-microservice
predicates:
- Path=/first/**
filters:
- TokenRelay=
- RemoveRequestHeader=Cookie
- id: secondService
uri: lb://second-microservice
predicates:
- Path=/second/**
# filters:
# - StripPrefix=1
filters:
- TokenRelay=
- RemoveRequestHeader=Cookie
- id: registry
uri: lb://registry
predicates:
- Path=/registry/**
filters:
- StripPrefix=1
- id: eureka
uri: lb://registry
predicates:
- Path=/eureka/**
autoconfigure:
# TODO: remove when fixed https://github.com/spring-projects/spring-security/issues/6314
exclude: org.springframework.boot.actuate.autoconfigure.security.reactive.ReactiveManagementWebSecurityAutoConfiguration
security:
oauth2:
client:
registration:
keycloak:
client-id: backend
client-secret: '2baa28ce-9607-44a3-a42c-a0bb2102a66d'
provider:
keycloak:
issuer-uri: ${ISSUER_URI:http://127.0.0.1:8090/auth/realms/dev}
user-name-attribute: preferred_username
server:
port: 8079
info:
app:
name: ${spring.application.name}
eureka:
client:
registerWithEureka: true
serviceUrl:
defaultZone: ${EUREKA_SERVER:http://localhost:8761/eureka}
healthcheck:
enabled: true
docker-compose.yml
version: '3'
volumes:
postgres_data:
driver: local # is already local by default
keycloak-data-volume:
driver: local # is already local by default
# external: true
services:
postgres:
image: postgres
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
networks:
- net
keycloak:
image: jboss/keycloak:11.0.0
environment:
DB_VENDOR: POSTGRES
DB_ADDR: postgres
DB_DATABASE: keycloak
DB_USER: keycloak
DB_SCHEMA: public
DB_PASSWORD: password
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: Pa55w0rd
volumes:
- keycloak-data-volume:/var/lib/keycloak/data
command: ["-Djboss.socket.binding.port-offset=10"]
expose:
- 8090
ports:
- 8090:8090
depends_on:
- postgres
networks:
- net
registry:
image: sample-cloud-registry:latest
container_name: registry
expose:
- 8761
networks:
- net
environment:
- EUREKA_SERVER=http://registry:8761/eureka/
gateway:
image: sample-cloud-gateway:latest
container_name: gateway
expose:
- 8079
ports:
- 127.0.0.1:8080:8079
networks:
- net
restart: always
depends_on:
- registry
- keycloak
environment:
- ISSUER_URI=http://127.0.0.1:8090/auth/realms/dev
- EUREKA_SERVER=http://registry:8761/eureka/
networks:
net:
I managed to solve my issue and here are my changes:
As I am using Eureka, I changed ISSUER_URI=http://127.0.0.1:8090/auth/realms/dev to use the hostname of keycloak container so the result is :
- ISSUER_URI=http://keycloak:8090/auth/realms/dev
You need to pay attention that the port number in the above line is the container port and not necessarily the host port.
And then, you need to add keycloak to your known hosts under etc to let login page be accessible via browser:
127.0.0.1 keycloak

Spring Boot App refuses to connect to the Kafka brokers

So I just recently started on using Kafka and for some odd reason, although the kafka and zookeeper servers containers are running as intended on the documentation and by using the command docker ps. I keep getting this specific error
I have been trying to solve this issue for about a week now with different configs and yet it still keeps giving me the endless loop of an error.
I followed both of these tutorials:
https://rmoff.net/2018/08/02/kafka-listeners-explained/ and https://www.youtube.com/watch?v=-0vrqMMGQbc
docker-compose up runs perfectly fine and the broker starts but when I start the mvn spring-boot:run command that's where it fails.
I've also tried changing the address through my local machine but still nothing. Would appreciate some help
This is my docker-compose.yml
version: '3.2'
services:
zookeeper:
container_name: zookeeper
image: wurstmeister/zookeeper
ports:
- "2181:2181"
environment:
ZOOKEEPER_CLIENT_PORT: 2181
kafka:
container_name: kafka
image: wurstmeister/kafka
ports:
- "9092:9092"
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_LISTENERS: INTERNAL://:19092,EXTERNAL://:9092
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:19092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: INTERNAL
KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'false'
depends_on:
- zookeeper
volumes:
- /var/run/docker.sock:/var/run/docker.sock
And this is my application.yml
# Server
server:
port: 8090
# Spring Kafka & H2
spring:
autoconfigure:
exclude: org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration
kafka:
bootstrap-servers: localhost:9092
h2:
console:
enabled: true
path: /h2
datasource:
url: jdbc:h2:mem:api;MODE=MySQL
username: api
password: root
driverClassName: org.h2.Driver
result:
topic.name: result
# Keycloak
keycloak:
auth-server-url: http://localhost:8080/auth
realm: demo
resource: demo-api
enabled: false
public-client: false
bearer-only : true
principal-attribute: preferred_username
allow-any-hostname: true
# credentials:
# secret:
# Logging
logging:
level:
org.springframework.web: DEBUG
org.hibernate: DEBUG
org: INFO
com.API.demo.Controllers: DEBUG
config: src/main/resources/logback-spring.xml
file:
path: logs/log
The Advertised Listener is not defined correctly
Instead of
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:19092
you need
KAFKA_ADVERTISED_LISTENERS: INTERNAL://kafka:19092,EXTERNAL://localhost:9092
Also note that if you want the broker to create topics automagically you'll want to set
KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'

Connecting Spring Cloud Applications in Docker Container

I am attempting to host a Spring Cloud application in Docker containers.The underlying exception is as follows:
search_1 | Caused by: java.lang.IllegalStateException: Invalid URL: config:8888
I understand the reason is because of the URL specified in my config server.
spring.application.name=inventory-client
#spring.cloud.config.uri=http://localhost:8888
spring.cloud.config.uri=config:8888
On my development machine, I am able to use localhost. However, based on a past question (relating to connecting to my database), I learned that localhost is not appropriate in containers. For my database, I was able to use the following:
spring.jpa.hibernate.ddl-auto=none
spring.jpa.show-sql=false
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.datasource.url=jdbc:postgresql://db:5432/leisurely_diversion
#spring.datasource.url=jdbc:postgresql://localhost:5000/leisurely_diversion
spring.datasource.driver-class-name=org.postgresql.Driver
but this obviously did not work as expected for the configuration server.
My docker-compose file:
# Use postgres/example user/password credentials
version: '3.2'
services:
db:
image: postgres
ports:
- 5000:5432
environment:
POSTGRES_PASSWORD: example
volumes:
- type: volume
source: psql_data
target: /var/lib/postgresql/data
networks:
- app
restart: always
config:
image: kellymarchewa/config_server
networks:
- app
volumes:
- /root/.ssh:/root/.ssh
restart: always
search:
image: kellymarchewa/search_api
networks:
- app
restart: always
ports:
- 8082:8082
depends_on:
- db
- config
- inventory
inventory:
image: kellymarchewa/inventory_api
depends_on:
- db
- config
ports:
- 8081:8081
networks:
- app
restart: always
volumes:
psql_data:
networks:
app:
Both services are running under the same user defined network; how I allow the services to find the configuration service?
Thanks.

How to config spring cloud oauth2 in docker container

I met some problems with micro-spring-docker , i think maybe the sso token-url is not correct.
The demo https://github.com/keryhu/micro-oauth2-docker
In local computer , sso service and auth-service works fine .
But not in docker container ,
the problem is that redirecting to auth-server Timeout .
SSO(pc-gateway service) application.yml:
security:
user:
password: none
oauth2:
client:
accessTokenUri: http://${AUTHSERVER_PORT_9999_TCP_ADDR:localhost}:9999/uaa/oauth/token
userAuthorizationUri: http://${AUTHSERVER_PORT_9999_TCP_ADDR:localhost}:9999/uaa/oauth/authorize
docker-compose.yml
eureka:
image: eureka:0.0.1-SNAPSHOT
container_name: eureka
hostname: eureka
ports:
- "8761:8761"
configserver:
image: config-server:0.0.1-SNAPSHOT
container_name: configserver
hostname: configserver
links:
- eureka
ports:
- "8888:8888"
authserver:
image: auth-server:0.0.1-SNAPSHOT
container_name: authserver
hostname: authserver
links:
- eureka
- configserver
ports:
- "9999:9999"
pcgateway:
image: pc-gateway:0.0.1-SNAPSHOT
container_name: pcgateway
hostname: pcgateway
links:
- eureka
- configserver
- authserver
ports:
- "8080:8080"
After starting in docker container :
http://192.168.99.100:8761/ showing :
Instances currently registered with Eureka
Application AMIs Availability Zones Status
AUTHSERVER n/a(1) (1) UP (1) - authserver:authserver:9999
CONFIGSERVER n/a(1) (1) UP (1) - configserver:configserver:8888
PCGATEWAY n/a(1) (1) UP (1) - pcgateway:pcgateway:8080
But when open the auth page: http://192.168.99.100:8080
It should be redirected to auth-server login page , but it opened Timeout , the Address Bar is:
http://172.17.0.4:9999/uaa/oauth/authorize?client_id=clientapp&redirect_uri=http://192.168.99.100:8080/login&response_type=code&state=cdXhfg
I don't know why , maybe the above sso tokenurl is not correct . How to resolve ?
The 172.17.0.4 IP-address is the IP-address of the authserver container on the internal (container-container) network, which is not reachable from outside the docker host (Virtual Machine).
This may be tricky, because (in this case) you need to provide the IP-address of the Virtual Machine that docker runs on, which may change, and definitely will be different in production.
If you change ${AUTHSERVER_PORT_9999_TCP_ADDR:localhost} to 192.168.99.100, it should work.
I suggest to make the IP-address (or domain) configurable using an environment-variable that you provide in the docker-compose.yml, so something like:
${DOMAIN_NAME:192.168.99.100}
Which defaults to the "standard" IP-address of the Virtual Machine. In production you can then pass the actual domain-name, or IP-address of the server your project runs on.
Note that the "link" environment variables are marked deprecated, and only will
be used on the default (bridge) network. The new linking feature won't create
these variables, but you can simply link to other containers by name. See
https://docs.docker.com/engine/userguide/networking/work-with-networks/#linking-containers-in-user-defined-networks

Resources