Muhammed Ozdogan
Muhammed Ozdogan

Reputation: 5877

Keycloak Invalid token issuer

I have a mobile app(react-native), a resource service(spring boot) and Keycloak Authenticatioin Service(Auth-Service).

Client makes authentication directly with Auth-Service and gets the access token. When I do a request to the resource service, the resource service checks the access token by asking to the Auth-Service. But token obtained by the client app and iss field is http://10.0.2.2:8060/auth/realms/sau and my resource service at http://localhost:8110.

Keycloak says: error="invalid_token", error_description="Invalid token issuer. Expected 'http://localhost:8060/auth/realms/sau', but was 'http://10.0.2.2:8060/auth/realms/sau'"

My question is how can I make authentication in resource service behalf my client?

Mobile App:

 export const prepareRequestBody = credentials => {
  const params = new URLSearchParams();
  params.append('username', credentials.username);
  params.append('password', credentials.password);
  params.append('client_id', "nasilim-mobile-app");
  params.append('grant_type', "password");
  return params;
};

export const login = credentials => {
  const params = prepareRequestBody(credentials);
  return axios.post(LOGIN, params);
};

enter image description here

Resource-Service:

application.yml

keycloak:
  realm: sau
  resource: photo-service
  bearer-only: false
  auth-server-url: http://localhost:8060/auth
  credentials:
     secret: 69a3e80c-8360-42df-bcec-b6575a6949dc

enter image description here

Note: I have checked this question and I have tried to set "X-Forwarded-For" : "http://localhost:8060/" but It didn't work Keycloak returns: { "error": "invalid_request", "error_description": "HTTPS required" }

Here is a Sample Access Token that obtained by mobile client.

Upvotes: 15

Views: 50596

Answers (8)

Anton
Anton

Reputation: 730

Fast answer: use KC_HOSTNAME_URL if uses quay.io/keycloak/keycloak image

Explanation:

Using https://jwt.io/ make sure that iss property in the JWT token is the same URL as issuer uri. For image quay.io/keycloak/keycloak should be used KC_HOSTNAME_URL property.

As mentioned here its 'iss' issue. To be specific, this logic is located in org.springframework.security.oauth2.jwt.JwtDecoderProviderConfigurationUtils which is part of org.springframework:spring-security-oauth2-jose:6.1.2(my version)

And here is the code: just compare issuer with meta issuer (which we override by using KC_HOSTNAME_URL property)

static void validateIssuer(Map<String, Object> configuration, String issuer) {
        String metadataIssuer = getMetadataIssuer(configuration);
        Assert.state(issuer.equals(metadataIssuer), () -> "The Issuer \"" + metadataIssuer
                + "\" provided in the configuration did not " + "match the requested issuer \"" + issuer + "\"");
    }

Upvotes: 1

UN..D
UN..D

Reputation: 603

I had same error, I have keyclok run inside container and my service on localhost, solved that by open page clients/yourClientName/settings & changed Access Settings (Root,Home,valid redirect, valid post, admin URL) to my service local address:

http://localhost:servicePort

So if you have service running inside container I think you will have to try change above Access Settings to the new IP Address. You can get your container ip address by using:

docker inspect \ -f "{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}"  container_name_or_id

Upvotes: 0

mflorczak
mflorczak

Reputation: 363

Problem is because inside "container" there is different ip(host). Keycloak has property hostname-url. You should inform keycloak about your frontend(hosts). You can do that during starting new instance of keycloak. Command to start your keycloak is start-dev --hostname-url=url-to-your-frontend you can provide the hostname of frontend, so the command will be look like this:

start-dev --hostname-url=http://10.0.2.2:8060

This solution is working for Keycloak version 19 and up

Upvotes: 1

Michael Pap
Michael Pap

Reputation: 1

At keycloak go to your realm then to realm settings and place the url you want at frontend url.

Upvotes: 0

Rots
Rots

Reputation: 787

Use the proxy-url in the adapter configuration to provide an alternative URL. See docs.

Spring application.yml:

keycloak:
  authServerUrl: http://10.0.2.2:8060/auth
  proxyUrl: http://localhost:8060/auth
  ...

Or keycloak.json:

{
  "auth-server-url": "http://10.0.2.2:8060/auth",
  "proxy-url": "http://localhost:8060/auth",
  ...
}

Upvotes: 0

Canatto Filipe
Canatto Filipe

Reputation: 609

The "iss" claim vary in function of the request. The variable KEYCLOAK_FRONTEND_URL can change this behavior. So try do as follow in your docker-compose file:

KEYCLOAK_FRONTEND_URL: http://10.0.2.2:8060/auth

Upvotes: 14

nono
nono

Reputation: 1702

What if you can not access the auth server using the external address? This will not work. Check https://issues.redhat.com/browse/KEYCLOAK-6984 One workaround is to set the reaml public key. But it's not recommended as the adapter will not check for new key if the key is rotated.

Upvotes: 2

Aritz
Aritz

Reputation: 31679

You need to configure access from your Spring Boot app to the Auth server in an external fashion, not localhost:

keycloak:
  realm: sau
  resource: photo-service
  bearer-only: false
  auth-server-url: http://10.0.2.2:8060/auth
  credentials:
     secret: 69a3e80c-8360-42df-bcec-b6575a6949dc

This way the token issuers will match. This will probably require either to disable SSL requirement for external request in keycloak or to configure proper SSL communication. If this is meant for production, do the right way.

See also:

Upvotes: 3

Related Questions