I have K8S cluster running on my host (docker desktop)
I have 6 components, each of them in it’s own deployment.
Each of them has service (Loadbalancer or ClusterIP)
-
Spring API GW (host api-gw on port 8000)
-
Spring eureka server (host service-discovery on port 8001)
-
Order service (host order-service on port 8002)
-
Product Service (host product-service on port 8003)
-
MariaDB (host db on port 3306)
-
PHPMyAdmin (host phpmyadmin on port 8004)
everything work fine while I navigate to localhost:8000
I added keycloak for autn to my system with all configuration in my spring-apigw (acts as oauth2 client)
keycloak(host kyecloak on port 8005)
Now, when I navigate to localhost:8000 it direct me to keycloak:8005 (which it’s fine).
How can I remain it as localhost
so it work (without modify my hosts
file, I know this way it will work)
Does the solution can come from the spring-gw application.yml
file?
server:
port: 8000
spring:
application:
name: api-gateway
security:
oauth2:
client:
provider:
keycloak:
issuer-uri: http://keycloak:8005/auth/realms/myapp
registration:
keycloak:
provider: keycloak
client-id: my-client
client-secret: *****
scope:
- email
- profile
- roles
eureka:
client:
service-url:
defaultZone: http://service-discovery:8001/eureka
instance:
hostname: ${spring.application.name}
Or via K8S configuration?
Thanks!
The problem is this:
client -> server -> oidc discovery -> http://keycloack/authorize
The place where I say oidc discovery
refers to this spec, https://swagger.io/docs/specification/authentication/openid-connect-discovery/.
You could, instead of doing OIDC discovery, tell the client the URLs directly.
client -> server -> http://localhost/authorize
I found this example in a blog post. The solution lies within.
In the below config you can see how the URIs, are set manually instead of only setting the issuer URL and relying on discovery like you do.
pring:
security:
oauth2:
client:
registration:
messaging-gateway-oidc:
provider: gateway-client-provider
client-id: relive-client
client-secret: relive-client
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
scope:
- openid
- profile
client-name: messaging-gateway-oidc
provider:
gateway-client-provider:
authorization-uri: http://127.0.0.1:8080/oauth2/authorize
token-uri: http://127.0.0.1:8080/oauth2/token
jwk-set-uri: http://127.0.0.1:8080/oauth2/jwks
user-info-uri: http://127.0.0.1:8080/userinfo
user-name-attribute: sub
This way, you could send the right URL to the user without having to look them up on the discovery endpoint of the issuer.
The ODIC, lookup would result in the same URIs, we see in above example except for having the issuer URLs, hostname. That’s exactly what you do not want.
So by setting the URIs manually, you have more control and can set it the way you want.
Just make sure that your ingress controller understands a request without hostname and routes to your oauth2 service.
With URIs, I mean these properties
- authorization-uri: http://127.0.0.1:8080/oauth2/authorize
- token-uri: http://127.0.0.1:8080/oauth2/token
- jwk-set-uri: http://127.0.0.1:8080/oauth2/jwks
- user-info-uri: http://127.0.0.1:8080/userinfo
instead of:
- issuer-uri: http://keycloak:8005/auth/realms/myapp
Note, this is only conceptionally the solution. HOW to do this specific thing with your stack of choice, I don’t know, but this is WHAT you have to do.
the issuer url could be the culprint. If this is OIDC, it will discover other endpoints from a path on this url. These endpints will contain the same hostname, and since the users browser is involved, it gets that “internal” hostname while it wants to have ,localhost. It would be easier if you could set the token and auth endpoint in this config, instead of using OIDC. Then you could simply set them to localhost