Invalid token issuer

I am attempting to use the Azure API Management Gateway in conjunction with the KeyCloak Identity service to generate OAUTH 2.0 tokens.

Essentially it goes like this currently:

Token Generation

  1. Frontend of https:///token to generate token
  2. Backend/redirect/rewrite to https:///auth/realms/sr15/protocol/openid-connect/token
  3. Success, token is returned

Get Resources

  1. Frontend of https:///resources
  2. Backend/redirect/rewrite to https:///aps/2/resources/
  3. Fails due to “ Invalid token issuer https://https/auth/realms/sr15! Brand domain incorrect: .”

From research online it suggests that the token that I receive can only ever target the same URL is was generated from.

E.g. If I generated the token by going to the Azure API gateway, which redirects to the API backend URL, then the token can then only be re-used when it targets the API Backend URL.

Can anyone assist on this? Super stuck and I suspect there must be a way to workaround it. I’ve attempted to add in redirect URL’s, base URL’s and all sorts into the keycloak realm/client but no joy…

I have just run into the same issue with Keycloak 10.0.1

Issuer has to be the same for both front-end and back-end.

However, back-end should be able to access the issuer privately through a different address instead of having to access issuer publicly.
This doesn’t make sense.

I believe a reverse proxy has to be used.

“Frontend URL” may be your friend. Consult the docs for this.

Thanks, this is indeed perfectly related.

Also, the associated “forceBackendUrlToFrontendUrl” option is set to “false” by default and should be working even without “frontendUrl” being set, but unexpectedly it is not.

see https://www.keycloak.org/docs/10.0/server_installation/index.html#default-provider

Thankfully, the official Docker image supports an environment variable to set “frontendUrl” as well as an option for reverse proxy scenario.

see https://hub.docker.com/r/jboss/keycloak

I have finally realized that

When back-end and front-end endpoints are different, which is quite sensible and expected
with back-end being private and front-end public

A reverse proxy is genuinely required, to forward the real client’s IP

see https://www.keycloak.org/docs/10.0/server_installation/#identifying-client-ip-addresses

This implies use of proxy-address-forwarding=true which is controlled by PROXY_ADDRESS_FORWARDING=true environment variable in official Docker image
see https://hub.docker.com/r/jboss/keycloak

frontendUrl property is also required, to correctly generate the page redirects

see https://www.keycloak.org/docs/10.0/server_installation/index.html#default-provider

This is controlled by the KEYCLOAK_FRONTEND_URLenvironment variable in official Docker image
see https://hub.docker.com/r/jboss/keycloak

Unfortunately, with both a reverse proxy and frontendUrl set Keycloak is still getting confused about the issuer.

Invalid token issuer. Expected “internal endpoint/auth/realms/realm”, but was “public endpoint/auth/realms/realm

Correction, this works.

Both a reverse proxy and “frontendUrl” are required.

For reverse proxy chains the last proxy in the chain must override the “X-Forwarded-Host”, “X-Forwarded-Proto” headers of the forwarded request to match “frontendUrl”

I have this same setup, a React frontend client served from an Nginx proxy, and then backend and keycloak containers which are within a docker network accessible via the proxy. Page redirects and authentication in the client is fine, but still getting issues with the token issuer being invalid when doing API calls to backend.

My client accesses keycloak using https://localhost/auth (proxy passes to https://keycloak:8443/auth where keycloak is the container name), the token issuer is localhost.

When doing backend token auth, connection to keycloak is done using the internal docker network (keycloak:8443) rather than localhost (for obvious reasons) and therefore there’s a mismatch.

I’ve set headers to no avail, but curious as to which header affects the issuer of the original token, and whether it’s correct that this issuer needs to become localhost in order to work.

I’m using keycloak server and adapters 12.0.2

Regardless of Keycloak version,

The “X-Forwarded-Host” and “X-Forwarded-Proto” headers passed to your Keycloak instance through your proxy must match the “frontendUrl” setting in your Keycloak instance, which seems to be http://localhost/auth in your case

It is one additional reason to use a proxy.

In other words, “frontendUrl” must be reflecting your public access.

I suspect somehow this is carried in the authentication token through HTTP requests and validated at application access time.

X-Forwarded-Host=localhost:80
X-Forwarded-Proto=http

I hope this helps you.

Hi Eliasbalasis,

Can u tell me how u fixed the above issue? I’m currently having the same issue. I’m running a keycloak docker container inside a kubernetes cluster with a frontend and backend server.
Everything works fine but when I try to do a call from the frontend to backend I get the error above.
Currently I only have the PROXY_ADDRESS_FORWARDING=true option when running the keycloak docker. When I try to add the KEYCLOAK_FRONTEND_URL=“https://keycloak.publicdomain.com/auth” nothing changes.
Thanks in advance!

It has been quite a while I have to admit but I do recall the principles I mentioned.

I will need to check my source code, perhaps over the weekend and get back to you.

Did you by chance ever resolve your issue with keycloak or find a viable workaround? thanks

I have looked through the code and all I can say is that the recipe I followed is quite complicated and very difficult to explain in simple terms.

However,
the primary principles remain the same and are used to drive everything else:
1.
Use PROXY_ADDRESS_FORWARDING=true
and
KEYCLOAK_FRONTEND_URL=, the one used by public apps to reference Keycloak instance.

Put a proxy in front of your Keycloak instance and
rewrite X-Forwarded-Proto to your public Keycloak URL scheme (http or https)
rewrite X-Forwarded-Host to :

Optionally, use separate Keycloak “resource” for public and private Keycloak access.
Applications use the confidential resource while public clients the public resource.

Make sure you assign to Keycloak clients the correct flows and configurations.
e.g. “Client Protocol”, “Access Type”, “Standard Flow Enabled”, “Direct Access Grants Enabled”, “Valid Redirect URIs”, “Web Origins”

If in doubt read very carefully the documentation, it is a tough read but trust me it will help you derive a full understanding and figure out the details you are possibly be missing.

I am sorry, I cannot make this any simpler.

Hi @eliasbalasis thank you for the quick reply! The frontend_url was the key in solving my problem. I am using the nginx ingress controller in my local K8s cluster. The problem was that the frontend_url was empty and so the authorization_endpoint was being set to something like localhost/keycloak/auth, which is where my keycloak instance exists, but that wasn’t the correct authorization_endpoint to set. I had to set the frontend_url to my Macbook’s IP address, so it looked something like http://myipaddress/keycloak/auth, and when I did that, the authorization_url was set too. Thanks for the help! I do recommend everyone to go through the keycloak documentation because that is where I figured out my issue.

1 Like

I am glad you found the solution.

I had the suspicion this would be the root cause, as I recall myself having to go through the same pain.

I couldn’t agree more, I definitely recommend everyone to go through the Keycloak documentation even though it can be a tough read.

Ran into a similar issue again when utilizing a network load balancer in AWS EKS. The URL mismatch issue is really freaking annoying. There’s a difference between frontendurl and the backend url that your applications use internally. I found this excerpt useful in understanding what was going wrong: Server Installation and Configuration Guide

I also had to pass in an arg to my keycloak container upon start up -Dkeycloak.forceBackendUrlToFrontendUrl=false

If you go into the Keycloak Admin Console, looking at Realm Settings (for your given realm) > General > Endpoints > OpenID Endpoint Configuration, analyzing the “authorization endpoint” and “token endpoint” is important too. The “token endpoint” URL is passed to the “issuer” when you parse a JWT token. Also very important to take a look at Clients > (your client) > Installation > (choose the format of your web adaptor file - I use JSON). This file is what’s needed by your applications to connect to keycloak. Ensure that your applications are using that file and that auth-server-url is set correctly.

Lastly, whatever ingress controller you’re using, make sure your ingress rules are set up right.

I’m having a similar issue, but I think the frontendurl etc. explained above, won’t help.

Say I have one microservice/frontend, secured with Keycloak ie. redirects to Keycloak.

I have two types of users, and I have two different domains that point to the same Keycloak server. Depending on some circumstances, I want the microservice/frontend to redirect to either the 1st or 2nd domain pointing to Keycloak.

I obviously could configure the Keycloak client on the microservice with a single (e.g. 1st domain) auth server URL, so this causes the token ie. issuer being invalid, for all the users that I redirect to the 2nd domain pointing to Keycloak.

I assume that what you tried configuring wouldn’t help in my case @eliasbalasis?

I was thinking that it would be possible to either configure multiple valid issuers on my secured microservice, or that I could explicitly define the issuer on Keycloak itself.

Any ideas how this can be achieved?

Just a FYI if anyone else is using the Node adapter and runs across this issue - as far as I can see, there is no way to check for resource permissions in a backend server on a ticket issued with the frontend url, because the adapter uses the serverUrl from configuration for both connecting to Keycloak and for comparing issuers. If you set that to frontend url, it won’t connect (in the internal network), and if you set it to backend url, issuers don’t match. The only way I could make it work was to modify the adapter so that you can provide it a separate backend url for connecting to keycloak, while setting serverUrl to the frontend url so that issuer comparison works.

1 Like