Keycloak behind NAT.. Issuer problems

Hi,

In my company we were planning to have Keycloak deployed as demonstrated above…
the Keycloak, Resource Server and the CLI tool we’ve made (a service account client) need to live behind the gateway.
Other service account clients need to be outside of the gateway.

Now my problem is that Resource server is configured with the issuer as the direct address to the keycloak, but the other applications (Accessing by the gateway) are obtaining JWTs with the issuer as the gateway address
So when such applications provide the JWT to the Resource server, the server would deny it because the issuer is not correct.

Is there any configuration / pattern to solve this problem, as it seems a natural NAT environment?
I’ve seen that my resource server (implemented with Spring sec 5) could simulate multi-tenancy by supporting the issuer for keycloak and the issuer for the gateway as somehow different identity providers, but this really feels like an ugly hack

Thanks in advance for all the help

Regards
João

This is not a Keycloak problem, but your architecture design issue. I would use single Keycloak domain everywhere (no problem with issuer) with specific DNS config for intranet (local IP)/internet (public IP).

I’ve now set all service account applications behind the gateway, and I’m testing the frontend client
I’ve set the frontendUrl property at the standalone.xml as described in the documentation.

Now all endpoints are using the frontend url (including the issuer and the token endpoint)
This happens because keycloak endpoint and gateway endpoint actually only change on the used port (for now the gateway is used to hide the internal ports on the same machine (that should be blocked by a firewall))

Looking at the DefaultHostnameProvider.java implementation I see these lines:

// Use frontend URI for backend requests if request hostname matches frontend hostname
if (type.equals(UrlType.BACKEND) && frontendUri != null && originalUriInfo.getBaseUri().getHost().equals(frontendUri.getHost())) {
    type = UrlType.FRONTEND;
}

So as long as only the port changes this code it’s forcing to use the frontEndUrl.
Is there any reason for this that I’m missing? I assume I’ll have to do a HostnameProvider for me that ignores this case?