{"id":18048030,"url":"https://github.com/ivangfr/springboot-keycloak-mongodb-testcontainers","last_synced_at":"2025-10-12T00:40:07.862Z","repository":{"id":51911666,"uuid":"130677018","full_name":"ivangfr/springboot-keycloak-mongodb-testcontainers","owner":"ivangfr","description":"The goals of this project are to: 1) Create a Spring Boot application that manages books, called book-service; 2) Use Keycloak as OpenID Connect provider; 3) Test using Testcontainers; 4) Explore the utilities and annotations that Spring Boot provides for testing applications.","archived":false,"fork":false,"pushed_at":"2025-04-27T06:33:36.000Z","size":1352,"stargazers_count":37,"open_issues_count":0,"forks_count":22,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-12T00:40:06.434Z","etag":null,"topics":["docker","integration-testing","java","keycloak","mongodb","oauth2-resourceserver","spring-boot","spring-data-mongodb","spring-security","spring-web-mvc","springdoc-openapi","testcontainers","unit-testing"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ivangfr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"ivangfr"}},"created_at":"2018-04-23T10:02:11.000Z","updated_at":"2025-07-15T18:47:46.000Z","dependencies_parsed_at":"2023-01-22T11:45:41.780Z","dependency_job_id":"c8d59706-ce23-45ab-af0c-96075ecaa522","html_url":"https://github.com/ivangfr/springboot-keycloak-mongodb-testcontainers","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ivangfr/springboot-keycloak-mongodb-testcontainers","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fspringboot-keycloak-mongodb-testcontainers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fspringboot-keycloak-mongodb-testcontainers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fspringboot-keycloak-mongodb-testcontainers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fspringboot-keycloak-mongodb-testcontainers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ivangfr","download_url":"https://codeload.github.com/ivangfr/springboot-keycloak-mongodb-testcontainers/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivangfr%2Fspringboot-keycloak-mongodb-testcontainers/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279009510,"owners_count":26084609,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-11T02:00:06.511Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","integration-testing","java","keycloak","mongodb","oauth2-resourceserver","spring-boot","spring-data-mongodb","spring-security","spring-web-mvc","springdoc-openapi","testcontainers","unit-testing"],"created_at":"2024-10-30T20:11:03.907Z","updated_at":"2025-10-12T00:40:07.845Z","avatar_url":"https://github.com/ivangfr.png","language":"Java","funding_links":["https://github.com/sponsors/ivangfr"],"categories":[],"sub_categories":[],"readme":"# springboot-keycloak-mongodb-testcontainers\n\nThe goals of this project are:\n\n- Create a [`Spring Boot`](https://docs.spring.io/spring-boot/index.html) application that manages books, called `book-service`;\n- Use [`Keycloak`](https://www.keycloak.org) as OpenID Connect provider;\n- Test using [`Testcontainers`](https://testcontainers.com/);\n- Explore the utilities and annotations that `Spring Boot` provides for testing applications.\n\n## Proof-of-Concepts \u0026 Articles\n\nOn [ivangfr.github.io](https://ivangfr.github.io), I have compiled my Proof-of-Concepts (PoCs) and articles. You can easily search for the technology you are interested in by using the filter. Who knows, perhaps I have already implemented a PoC or written an article about what you are looking for.\n\n## Additional Readings\n\n- \\[**Medium**\\] [**Implementing and Securing a Simple Spring Boot REST API with Keycloak**](https://medium.com/@ivangfr/how-to-secure-a-spring-boot-app-with-keycloak-5a931ee12c5a)\n- \\[**Medium**\\] [**Implementing and Securing a Simple Spring Boot UI (Thymeleaf + RBAC) with Keycloak**](https://medium.com/@ivangfr/how-to-secure-a-simple-spring-boot-ui-thymeleaf-rbac-with-keycloak-ba9f30b9cb2b)\n- \\[**Medium**\\] [**Implementing and Securing a Spring Boot GraphQL API with Keycloak**](https://medium.com/@ivangfr/implementing-and-securing-a-spring-boot-graphql-api-with-keycloak-c461c86e3972)\n- \\[**Medium**\\] [**Building a Single Spring Boot App with Keycloak or Okta as IdP: Introduction**](https://medium.com/@ivangfr/building-a-single-spring-boot-app-with-keycloak-or-okta-as-idp-introduction-2814a4829aed)\n\n## Application\n\n- ### book-service\n  \n  `Spring Boot` Web application that manages books. [`MongoDB`](https://www.mongodb.com) is used as storage, and the application's sensitive endpoints (like create, update and delete books) are secured.\n  \n  ![book-service-swagger](documentation/book-service-swagger.jpeg)\n\n## Prerequisites\n\n- [`Java 21`](https://www.oracle.com/java/technologies/downloads/#java21) or higher;\n- A containerization tool (e.g., [`Docker`](https://www.docker.com), [`Podman`](https://podman.io), etc.)\n- [`jq`](https://jqlang.github.io/jq/)\n\n## Start Environment\n\nOpen a terminal and, inside the `springboot-keycloak-mongodb-testcontainers` root folder, run the script below\n```bash\n./init-environment.sh\n```\n\n## Configure Keycloak\n\nThere are two ways: running a script or using the `Keycloak` website\n\n### Running Script\n\n- In a terminal, make sure you are inside the `springboot-keycloak-mongodb-testcontainers` root folder\n\n- Run the following script to configure `Keycloak` for `book-service` application\n  ```bash\n  ./init-keycloak.sh\n  ```\n\n  This script will create:\n  - `company-services` realm;\n  - `book-service` client;\n  - `manage_books` client role;\n  - user with _username_ `ivan.franchin` and _password_ `123` and with the role `manage_books` assigned.\n\n- The `book-service` client secret (`BOOK_SERVICE_CLIENT_SECRET`) is shown at the end of the execution. It will be used in the next step.\n\n- You can check the configuration in `Keycloak` by accessing http://localhost:8080. The credentials are `admin/admin`. \n\n### Using Keycloak Website\n\n#### Login\n\n- Access http://localhost:8080\n\n- Login with the credentials\n  ```text\n  Username: admin\n  Password: admin\n  ```\n\n#### Create a new Realm\n\n- On the left menu, click the dropdown button that contains `Keycloak` and then, click `Create Realm` button\n- Set `company-services` to the `Realm name` field and click `Create` button\n\n### Disable Required Action Verify Profile\n\n- On the left menu, click `Authentication`\n- Select `Required actions` tab\n- Disable `Verify Profile`\n\n#### Create a new Client\n\n- On the left menu, click `Clients`\n- Click `Create client` button\n- In `General Settings`\n  - Set `book-service` to `Client ID`\n  - Click `Next` button\n- In `Capability config`\n  - Enable `Client authentication` toggle switch\n  - Click `Next` button\n- In `Login settings` tab\n  - Set `http://localhost:9080/*` to `Valid redirect URIs`\n  - Click `Save` button\n- In `Credentials` tab, you can find the secret generated for `book-service`\n- In `Roles` tab\n  - Click `Create role` button\n  - Set `manage_books` to `Role Name`\n  - Click `Save` button\n\n#### Create a new User\n\n- On the left menu, click `Users`\n- Click `Create new user` button\n- Set `ivan.franchin` to `Username` field\n- Click `Create`\n- In `Credentials` tab\n  - Click `Set password` button\n  - Set the value `123` to `Password` and `Password confirmation`\n  - Disable the `Temporary` toggle switch\n  - Click `Save` button\n  - Confirm by clicking `Save password` button\n- In `Role Mappings` tab\n  - Click `Assign role` button\n  - Click `Filter by realm roles` dropdown button and select `Filter by clients`\n  - Select `[book-service] manage_books` name and click `Assign` button\n\n## Running book-service with Gradle\n\n- Open a new terminal and navigate to the `springboot-keycloak-mongodb-testcontainers` root folder\n\n- Run the following command to start the application\n  ```bash\n  ./gradlew book-service:clean book-service:bootRun --args='--server.port=9080'\n  ```\n\n## Running book-service as a Docker Container\n\n- In a terminal, navigate to the `springboot-keycloak-mongodb-testcontainers` root folder\n\n- Build Docker Image\n  ```bash\n  ./build-docker-images.sh\n  ```\n  | Environment Variable | Description                                                       |\n  |----------------------|-------------------------------------------------------------------|\n  | `MONGODB_HOST`       | Specify host of the `Mongo` database to use (default `localhost`) |\n  | `MONGODB_PORT`       | Specify port of the `Mongo` database to use (default `27017`)     |\n  | `KEYCLOAK_HOST`      | Specify host of the `Keycloak` to use (default `localhost`)       |\n  | `KEYCLOAK_PORT`      | Specify port of the `Keycloak` to use (default `8080`)            |\n\n- Run `book-service` docker container, joining it to project Docker network\n  ```bash\n  docker run --rm --name book-service \\\n    -p 9080:8080 \\\n    -e MONGODB_HOST=mongodb \\\n    -e KEYCLOAK_HOST=keycloak \\\n    --network=springboot-keycloak-mongodb-testcontainers-net \\\n    ivanfranchin/book-service:1.0.0\n  ```\n\n## Getting Access Token\n\n- In a terminal, create an environment variable that contains the `Client Secret` generated by `Keycloak` to `book-service` at [Configure Keycloak](#configure-keycloak) step\n  ```bash\n  BOOK_SERVICE_CLIENT_SECRET=...\n  ```\n\n- **When running book-service with Gradle**\n\n  Run the commands below to get an access token for `ivan.franchin`\n  ```bash\n  ACCESS_TOKEN=$(curl -s -X POST \\\n    \"http://localhost:8080/realms/company-services/protocol/openid-connect/token\" \\\n    -H \"Content-Type: application/x-www-form-urlencoded\" \\\n    -d \"username=ivan.franchin\" \\\n    -d \"password=123\" \\\n    -d \"grant_type=password\" \\\n    -d \"client_secret=$BOOK_SERVICE_CLIENT_SECRET\" \\\n    -d \"client_id=book-service\" | jq -r .access_token)\n  echo $ACCESS_TOKEN\n  ```\n\n- **When running book-service as a Docker Container**\n\n  Run the commands below to get an access token for `ivan.franchin`\n  ```bash\n  ACCESS_TOKEN=$(\n    docker run -t --rm -e CLIENT_SECRET=$BOOK_SERVICE_CLIENT_SECRET --network springboot-keycloak-mongodb-testcontainers-net alpine/curl:latest sh -c '\n      curl -s -X POST http://keycloak:8080/realms/company-services/protocol/openid-connect/token \\\n        -H \"Content-Type: application/x-www-form-urlencoded\" \\\n        -d \"username=ivan.franchin\" \\\n        -d \"password=123\" \\\n        -d \"grant_type=password\" \\\n        -d \"client_secret=$CLIENT_SECRET\" \\\n        -d \"client_id=book-service\"' | jq -r .access_token)\n  echo $ACCESS_TOKEN\n  ```\n  \u003e **Note**: We are running a alpine/curl Docker container and joining it to the project Docker network. By specifying `\"keycloak:8080\"` as host/port, we won't encounter the error related to an invalid token issuer.\n\n- In [jwt.io](https://jwt.io), you can decode and verify the `JWT` access token\n\n## Test using cURL\n\n- In terminal, call the endpoint `GET /api/books`\n  ```bash\n  curl -i http://localhost:9080/api/books\n  ```\n  It should return:\n  ```text\n  HTTP/1.1 200\n  []\n  ```\n\n- Try to call the endpoint `POST /api/books`, without access token\n  ```bash\n  curl -i -X POST http://localhost:9080/api/books \\\n    -H \"Content-Type: application/json\" \\\n    -d '{\"authorName\": \"Ivan Franchin\", \"title\": \"Java 8\", \"price\": 10.5}'\n  ```\n  It should return:\n  ```text\n  HTTP/1.1 401\n  ```\n\n- Get the Access Token as explained on section [Getting Access Token](#getting-access-token)\n\n- Call the endpoint `POST /api/books`, now informing the access token\n  ```bash\n  curl -i -X POST http://localhost:9080/api/books \\\n    -H \"Authorization: Bearer $ACCESS_TOKEN\" \\\n    -H \"Content-Type: application/json\" \\\n    -d '{\"authorName\": \"Ivan Franchin\", \"title\": \"Java 8\", \"price\": 10.5}'\n  ```\n  It should return something like:\n  ```text\n  HTTP/1.1 201\n  {\"id\":\"612f4f9438e39e473c4d098b\", \"authorName\":\"Ivan Franchin\", \"title\":\"Java 8\", \"price\":10.5}\n  ```\n\n## Test using Swagger\n\n- Access http://localhost:9080/swagger-ui.html\n\n- Click `GET /api/books` to open it. Then, click `Try it out` button and, finally, click `Execute` button.\n\n  It will return a HTTP status code `200` and an empty list or a list with some books if you've already added them.\n\n- Now, let's try to call a secured endpoint without authentication. Click `POST /api/books` to open it. Then, click `Try it out` button (you can use the default values) and, finally, click `Execute` button.\n\n  It will return:\n  ```text\n  Code: 401\n  Details: Error: response status is 401\n  ```\n\n- Get the Access Token as explained on section [Getting Access Token](#getting-access-token)\n\n- Copy the token generated and go back to `Swagger`\n\n- Click the `Authorize` button and paste the access token in the `Value` field. Then, click `Authorize` and, to finalize, click `Close`\n\n- Go to `POST /api/books`, click `Try it out` and, finally, click `Execute` button.\n\n  It should return something like:\n  ```text\n  HTTP/1.1 201\n  {\n    \"id\": \"612f502f38e39e473c4d098c\",\n    \"authorName\": \"Ivan Franchin\",\n    \"title\": \"SpringBoot\",\n    \"price\": 10.5\n  }\n  ```\n\n## Useful Links \u0026 Commands\n\n- **MongoDB**\n\n  List books\n  ```bash\n  docker exec -it mongodb mongosh bookdb\n  db.books.find()\n  ```\n  \u003e Type `exit` to get out of MongoDB shell\n\n## Shutdown\n\n- To stop `book-service`, go to the terminal where the application is running and press `Ctrl+C`;\n- To stop the Docker containers started using the `./init-environment.sh` script, make sure you are in `springboot-keycloak-mongodb-testcontainers` and run the script below:\n  ```bash\n  ./shutdown-environment.sh\n  ```\n\n## Cleanup\n\nTo remove the Docker image created by this project, go to a terminal and, inside the `springboot-keycloak-mongodb-testcontainers` root folder, run the following script:\n```bash\n./remove-docker-images.sh\n```\n\n## Running Unit and Integration Tests\n\n- In a terminal and inside the `springboot-keycloak-mongodb-testcontainers` root folder, run the command below to run unit and integration tests\n  ```bash\n  ./gradlew book-service:clean book-service:assemble \\\n    book-service:cleanTest \\\n    book-service:test \\\n    book-service:integrationTest\n  ```\n  \u003e **Note**: During integration tests, `Testcontainers` will automatically start `MongoDB` and `Keycloak` containers before the tests begin and shut them down when the tests finish.\n\n- From the `springboot-keycloak-mongodb-testcontainers` root folder, the **Unit Testing Report** can be found at:\n  ```text\n  book-service/build/reports/tests/test/index.html\n  ```\n\n- From the `springboot-keycloak-mongodb-testcontainers` root folder, the **Integration Testing Report** can be found at:\n  ```text\n  book-service/build/reports/tests/integrationTest/index.html\n  ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivangfr%2Fspringboot-keycloak-mongodb-testcontainers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivangfr%2Fspringboot-keycloak-mongodb-testcontainers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivangfr%2Fspringboot-keycloak-mongodb-testcontainers/lists"}