0

I'm creating a microservices project. The idea is that a reactjs application get a token from Keycloack and send this jwt token to a springboot rest api in the backend. I'm using docker compose to manage the containers in my local machine. With Postman I get the token form keycloack, but when I use this token as bearer token to call the rest api with Postman,I'm getting 401. I configured keycloak, but in the backend, in the logs I found the error:

2021-02-28 10:37:14.134 ERROR 1 --- [nio-8081-exec-4] o.k.a.rotation.AdapterTokenVerifier      : Didn't find publicKey for kid: fbb8f5e8-2341-4d1d-82d8-6efe736c90c5

In the logs of keycloak I see:

    10:22:19,590 INFO  [org.keycloak.keys.DefaultKeyManager] (default task-4) No keys found for realm=master and algorithm=HS256 for use=SIG. Generating keys.
10:22:25,423 INFO  [org.keycloak.keys.DefaultKeyManager] (default task-5) No keys found for realm=master and algorithm=RS256 for use=SIG. Generating keys.
10:23:18,927 WARN  [org.keycloak.events] (default task-4) type=LOGIN_ERROR, realmId=todo-realm, clientId=todo-app, userId=null, ipAddress=172.29.0.1, error=invalid_client_credentials, grant_type=password

In the Springboot application.properties i put these properties:

keycloak.realm                      = todo-realm
keycloak.auth-server-url            = http://keycloak:8080/auth
keycloak.ssl-required               = external
keycloak.resource                   = todo-app
keycloak.credentials.secret        = the secret of the client in keycloack
keycloak.use-resource-role-mappings = true
keycloak.bearer-only                = true

In the keycloak I created a realm called: todo-realm. I created a client called todo-app and two roles:

  • app-user
  • app-admin

I creted a user, called user1, with the role: app-user. In my springboot app, the pom is:

 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.cammisa.filippo.todolist</groupId>
    <artifactId>todo-list</artifactId>
    <version>0.0.3-SNAPSHOT</version>
    <name>todo-list</name>
    <description>Demo project with Spring Boot for A To do List</description>

    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <docker.image.prefix>fcammisa</docker.image.prefix>
        <docker-image-name>todo-list-backend</docker-image-name>
        <keycloak.version>12.0.3</keycloak.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- link: http://localhost:8080/api/swagger-ui/index.html?configUrl=/api/v3/api-docs/swagger-config -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-data-rest</artifactId>
            <version>1.5.2</version>
        </dependency>
        <!-- restdocs -->
        <dependency>
            <groupId>org.springframework.restdocs</groupId>
            <artifactId>spring-restdocs-mockmvc</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.restdocs</groupId>
            <artifactId>spring-restdocs-restassured</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.github.cloudyrock.mongock</groupId>
            <artifactId>mongock-spring-v5</artifactId>
        </dependency>
        <dependency>
            <groupId>com.github.cloudyrock.mongock</groupId>
            <artifactId>mongodb-springdata-v3-driver</artifactId>
        </dependency>
    </dependencies>


    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.github.cloudyrock.mongock</groupId>
                <artifactId>mongock-bom</artifactId>
                <version>4.1.17</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.keycloak.bom</groupId>
                <artifactId>keycloak-adapter-bom</artifactId>
                <version>12.0.3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    
</project>

I created a class to configure keycloack:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(jsr250Enabled = true)
public class KeycloakSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
        http.authorizeRequests()
                .antMatchers("/api/todo/todos").hasAnyRole("user")
                /*.antMatchers("/api/todo/insert").hasAnyRole("user")
                .antMatchers("/api/todo/update").hasAnyRole("user")
                .antMatchers("/api/todo/get/{id}").hasAnyRole("user","admin")
                .antMatchers("/api/todo/todos").hasAnyRole("user")
                .antMatchers("/api/todos/{pageNo}/{pageSize}").hasAnyRole("user")
                .antMatchers("/api/todo/delete").hasAnyRole("user")
                .antMatchers("/api/todo/delete/{id}").hasAnyRole("user")*/
                .anyRequest()
                .permitAll();
        http.csrf().disable();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
        keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
        auth.authenticationProvider(keycloakAuthenticationProvider);
    }

    @Bean
    @Override
    protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
        return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
    }

    @Bean
    public KeycloakConfigResolver KeycloakConfigResolver() {
        return new KeycloakSpringBootConfigResolver();
    }
}

This is my docker compose file:

    version: "3.7"
services:
  tododb-service:
    image: mongo:latest
    container_name: tododb
    restart: always
    environment:
        MONGO_INITDB_ROOT_USERNAME: admin
        MONGO_INITDB_ROOT_PASSWORD: password
        MONGO_INITDB_DATABASE: todo
        MONGO_INITDB_ROLE: userAdminAnyDatabase
    ports:
      - 27017:27017
  todo-app:
    build:
      context: .
    container_name: todo-app
    ports:
      - 8081:8081

  keycloak-db:
    image: postgres
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: password

  keycloak:
    image: jboss/keycloak:12.0.3
    volumes:
      - ./imports:/opt/jboss/keycloak/imports
    #command:
    #  - "-b 0.0.0.0 -Dkeycloak.import=/opt/jboss/keycloak/imports/realm-export.json"
    environment:
      DB_VENDOR: POSTGRES
      DB_ADDR: keycloak-db
      DB_DATABASE: keycloak
      DB_USER: keycloak
      DB_SCHEMA: public
      DB_PASSWORD: password
      KEYCLOAK_USER: admin
      KEYCLOAK_PASSWORD: password
      # Uncomment the line below if you want to specify JDBC parameters. The parameter below is just an example, and it shouldn't be used in production without knowledge. It is highly recommended that you read the PostgreSQL JDBC driver documentation in order to use it.
      #JDBC_PARAMS: "ssl=true"
    ports:
      - 8080:8080
      - 9990:9990
    depends_on:
      - keycloak-db

Can someone help me to get the result of the rest api using Postaman of my rest api ? Thank you so much.

Connell.O'Donnell
  • 3,603
  • 11
  • 27
  • 61
fcammisa
  • 1
  • 1
  • How does the keycloak.credentials.secret get configured in the keycloak container? I'm guessing this is a shared secret, and would therefore need to be configured with the same secret as the spring boot app. – Hopey One Feb 28 '21 at 21:08
  • Did you resolve this? any idea where was the problem? – user565 Sep 26 '21 at 21:49
  • Yes, I solved. I put in the /etc/hosts file this line: 127.0.0.1 keycloak and it's works – fcammisa Feb 13 '22 at 16:06

0 Answers0