Default hostname provider

466 views
Skip to first unread message

Andy To

unread,
Jul 6, 2021, 1:48:47 AM7/6/21
to Keycloak User
Hi, 

I'm trying to setup a test app in docker containers.  It consist of the following apps in a docker-compose:
  1. Keycloak + posgresql
  2. A Simple NodeJS app that has routes protected via RBAC (using keycloak-connect), this is configured with a bearer only client
  3. A React App (using @react-keycloak/web), this is configured with a public client
The above 3 apps have service names in the docker-compose file and are all port mapped to localhost under different ports.

The issue I am running into now is that after I login with the react app, the token i receive has an issuer host of "localhost", while the NodeJS app expects the service name "keycloak" as the host instead.  Attempting to use the token anyway results in a mismatch issuer error being thrown.

While digging into the issue, i found https://issues.redhat.com/browse/KEYCLOAK-5014, which was marked as a duplicate of https://issues.redhat.com/browse/KEYCLOAK-6073  which is marked as closed and fixed in 8.0.0.  


I understand the following from this and my testing:
  • frontendUrl is configurable, and can be used to override the issuer for all requests for tokens
  • This should be used for front-end URLs as the name of the property "frontendUrl" implies as it modifies the issuer, authorization_endpoint, end_session_endpoint, and check_session_iframe values in the well-known openid discovery point to be the same as its configured value
  • token_endpoint, introspection_endpoint, userinfo_endpoint, and jwks_uri will remain as the incoming request host as they are considered "backend" values
  • there is another property "forceBackendUrlToFrontendUrl", which i assume will force the backend url to be the frontend url, effectively making every request return only the frontend url as the issuer in tokens
  • frontendUrl can be overriden through a realm level config
What I don't understand is, how this fits into resolving the issues.  I've tried the following:
  • Setting the frontendURL to localhost, this doesn't change anything as the keycloak-connect library does not have a separate configurations for the specifying back channel, and frontend urls, the only configurable URL i can find is "authServerUrl", which is used for everything else
  • Setting the frontendURL to "keycloak" (the backend expected value), this might have worked, however, it seems to override the redirect value of the login process, so after login, i get redirected back to the domain "keycloak" instead of the domain "localhost" even though its the domain listed on the query param.
  • Based on the description of "forceBackendUrlToFrontendUrl", i do not think that would help in any way, so i've ignored it.
Has anyone solved this issue? and if so, what did you do to resolve it?  From what I can tell, i don't think my particular issue is resolvable with the default host provider.  The most straight forward solution seems to be allowing multiple issuers like the original ticket suggested.  But as there was no other activities on those tickets after they where closed, and no new ones where created, I assumed I am missing something obvious here...

Thanks,
Andy

Pedro Igor Craveiro e Silva

unread,
Jul 6, 2021, 3:13:53 PM7/6/21
to Andy To, Keycloak User
On Tue, Jul 6, 2021 at 2:48 AM Andy To <andy...@gmail.com> wrote:
Hi, 

I'm trying to setup a test app in docker containers.  It consist of the following apps in a docker-compose:
  1. Keycloak + posgresql
  2. A Simple NodeJS app that has routes protected via RBAC (using keycloak-connect), this is configured with a bearer only client
  3. A React App (using @react-keycloak/web), this is configured with a public client
The above 3 apps have service names in the docker-compose file and are all port mapped to localhost under different ports.

The issue I am running into now is that after I login with the react app, the token i receive has an issuer host of "localhost", while the NodeJS app expects the service name "keycloak" as the host instead.  Attempting to use the token anyway results in a mismatch issuer error being thrown.

While digging into the issue, i found https://issues.redhat.com/browse/KEYCLOAK-5014, which was marked as a duplicate of https://issues.redhat.com/browse/KEYCLOAK-6073  which is marked as closed and fixed in 8.0.0.  


I understand the following from this and my testing:
  • frontendUrl is configurable, and can be used to override the issuer for all requests for tokens
  • This should be used for front-end URLs as the name of the property "frontendUrl" implies as it modifies the issuer, authorization_endpoint, end_session_endpoint, and check_session_iframe values in the well-known openid discovery point to be the same as its configured value
  • token_endpoint, introspection_endpoint, userinfo_endpoint, and jwks_uri will remain as the incoming request host as they are considered "backend" values
  • there is another property "forceBackendUrlToFrontendUrl", which i assume will force the backend url to be the frontend url, effectively making every request return only the frontend url as the issuer in tokens
  • frontendUrl can be overriden through a realm level config
You git it right.
 
What I don't understand is, how this fits into resolving the issues.  I've tried the following:
  • Setting the frontendURL to localhost, this doesn't change anything as the keycloak-connect library does not have a separate configurations for the specifying back channel, and frontend urls, the only configurable URL i can find is "authServerUrl", which is used for everything else
  • Setting the frontendURL to "keycloak" (the backend expected value), this might have worked, however, it seems to override the redirect value of the login process, so after login, i get redirected back to the domain "keycloak" instead of the domain "localhost" even though its the domain listed on the query param.
  • Based on the description of "forceBackendUrlToFrontendUrl", i do not think that would help in any way, so i've ignored it.
Has anyone solved this issue? and if so, what did you do to resolve it?  From what I can tell, i don't think my particular issue is resolvable with the default host provider.  The most straight forward solution seems to be allowing multiple issuers like the original ticket suggested.  But as there was no other activities on those tickets after they where closed, and no new ones where created, I assumed I am missing something obvious here...

#2 above is what you should usually do and it is expected that any front-end URL built by the server (those you mentioned) is going to be based on the value you defined.

It is not clear to me why you are using (if I understood correctly) different "auth server URLs" in both frontend and backend apps. Could you elaborate, please?
 

Thanks,
Andy

--
You received this message because you are subscribed to the Google Groups "Keycloak User" group.
To unsubscribe from this group and stop receiving emails from it, send an email to keycloak-use...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/keycloak-user/44c7f20c-93c5-4fd6-8578-31c85bb0845fn%40googlegroups.com.

Andy To

unread,
Jul 6, 2021, 3:48:19 PM7/6/21
to Keycloak User
This specific scenario is because i'm using docker compose, but i'd imagine a similar scenario would happen if you had your backend services + keycloak behind a VPC, and an SPA that would connect to keycloak via a LB with a separate domain.

As stated in my original question, I have 3 components:
  1. Keycloak - localhost:8080 - docker hostname: keycloak
  2. Backend app - localhost:8000 - docker hostname: server
  3. Frontend app (SPA) - localhost:3000 - docker hostname: frontend
These are deployed via docker-compose with port maps to localhost.  docker-compose automatically creates its own internal network and each of the apps can only reach each other through their docker host names within the network.  

The frontend is served via localhost:3000, and talks to keycloak/backend app through localhost:8080, and localhost:8000 respectively.  The backend, however, can only talk to keycloak via the docker hostname or docker assigned ip, hence there being 2 different auth server URLS for frontend apps and backend apps.

Pedro Igor Craveiro e Silva

unread,
Jul 7, 2021, 9:16:10 AM7/7/21
to Andy To, Keycloak User
On Tue, Jul 6, 2021 at 4:48 PM Andy To <andy...@gmail.com> wrote:
This specific scenario is because i'm using docker compose, but i'd imagine a similar scenario would happen if you had your backend services + keycloak behind a VPC, and an SPA that would connect to keycloak via a LB with a separate domain.

As stated in my original question, I have 3 components:
  1. Keycloak - localhost:8080 - docker hostname: keycloak
  2. Backend app - localhost:8000 - docker hostname: server
  3. Frontend app (SPA) - localhost:3000 - docker hostname: frontend
These are deployed via docker-compose with port maps to localhost.  docker-compose automatically creates its own internal network and each of the apps can only reach each other through their docker host names within the network.  

The frontend is served via localhost:3000, and talks to keycloak/backend app through localhost:8080, and localhost:8000 respectively.  The backend, however, can only talk to keycloak via the docker hostname or docker assigned ip, hence there being 2 different auth server URLS for frontend apps and backend apps.

I think I see the issue now. It should be related to how the keycloak-connect resolves the issuer. Perhaps, the problem here is that the library is not loading the issuer from the discovery document, which should be using the "keycloak" host after you set the frontendUrl. 

Perhaps this is the code failing for you https://github.com/keycloak/keycloak-nodejs-connect/blob/master/middleware/auth-utils/grant-manager.js#L427. I did only a few contributions to this library so I might be wrong. There are others more fluent than me in this area.

IIRC, other adapters (e.g.: java ones) do fetch issuer from discovery document.

It is OK to have the backend accessing Keycloak within a different network (possibly a private one). In fact, that should avoid unnecessary hops.

Btw, one issue I see with backend URLs is that in case you want to expose those URLs publicly (e.g.: forcingBackendUrlToFrontend) your backends will always fetch from the discovery document the public URL and not something else they could access Keycloak directly if in the same network.
 

Andy To

unread,
Jul 7, 2021, 9:44:23 AM7/7/21
to Keycloak User
Right, that makes sense, so the keycloak-connect adapter should be retrieving the iss from the discovery document, but is currently getting it from the config.realmUrl which is configured via the keycloak.json.

I had initially made that connection, and had already determined that the keycloak-connect library did not retrieve the discovery document, but wasn't sure if that was intended or not.  I guess I'll make a bug report and/or PR for this.  Can you point me to the appropriate channels to submit a bug report?  I assume its at: https://issues.redhat.com/projects/KEYCLOAK/issues/KEYCLOAK-18576?filter=allopenissues ?

Also, I'd agree with you on the backend URL comment, but as its a flag, i see no actual harm in it.  Especially since the default is false for it.  There's likely some obscure use-case for it that we're missing that makes this useful for some users.
Reply all
Reply to author
Forward
0 new messages