All Projects → ivangfr → springboot-keycloak-mongodb-testcontainers

ivangfr / springboot-keycloak-mongodb-testcontainers

Licence: other
Goals: 1) Create a Spring Boot application that manages books; 2) Use Keycloak as authentication and authorization server; 3) Test using Testcontainers; 4) Explore the utilities and annotations that Spring Boot provides when testing applications.

Programming Languages

java
68154 projects - #9 most used programming language
shell
77523 projects

Projects that are alternatives of or similar to springboot-keycloak-mongodb-testcontainers

MealsCatalogue
Flutter application using base architecture component like BLoC pattern, RxDart, Http, SQFlite, Flavor, Unit Testing (Mockito), Instrumentation Testing and etc 🔥
Stars: ✭ 45 (+150%)
Mutual labels:  unit-testing, integration-testing
springboot-junit5-mockito2
Show case for how to use junit 5 and mockito 2 for unit testing and integration test in spring boot 2
Stars: ✭ 18 (+0%)
Mutual labels:  unit-testing, integration-testing
Dntframeworkcore
Lightweight and Extensible Infrastructure for Building Web Applications - Web Application Framework
Stars: ✭ 208 (+1055.56%)
Mutual labels:  unit-testing, integration-testing
awesome-javascript-testing
🔧 Awesome JavaScript testing resources
Stars: ✭ 28 (+55.56%)
Mutual labels:  unit-testing, integration-testing
secure-oauth2-oidc-workshop
Hands-On Workshop for OAuth 2.0 and OpenID Connect 1.0
Stars: ✭ 58 (+222.22%)
Mutual labels:  keycloak, testcontainers
Systemwrapper
.NET library for easier testing of system APIs.
Stars: ✭ 153 (+750%)
Mutual labels:  unit-testing, integration-testing
pythonista-chromeless
Serverless selenium which dynamically execute any given code.
Stars: ✭ 31 (+72.22%)
Mutual labels:  unit-testing, integration-testing
Automation Arsenal
Curated list of popular Java and Kotlin frameworks, libraries and tools related to software testing, quality assurance and adjacent processes automation.
Stars: ✭ 105 (+483.33%)
Mutual labels:  unit-testing, integration-testing
Fineract-CN-mobile
DEPRECATED project - Check the Apache fineract-cn-mobile project instead
Stars: ✭ 17 (-5.56%)
Mutual labels:  unit-testing, integration-testing
SqlInMemory
SqlInMemory is a library for creating SqlServer database on Memory instead of hard disk, at last Drops and Disposes database when you're done with it. This is useful for Integration Testing.
Stars: ✭ 24 (+33.33%)
Mutual labels:  unit-testing, integration-testing
Android Client
An android client for the MifosX platform
Stars: ✭ 150 (+733.33%)
Mutual labels:  unit-testing, integration-testing
hivemq-testcontainer
Automatic starting HiveMQ docker containers for JUnit4 and JUnit5 tests. This enables testing MQTT client applications and integration testing of custom HiveMQ extensions.
Stars: ✭ 17 (-5.56%)
Mutual labels:  integration-testing, testcontainers
Dockertest
Write better integration tests! Dockertest helps you boot up ephermal docker images for your Go tests with minimal work.
Stars: ✭ 2,254 (+12422.22%)
Mutual labels:  unit-testing, integration-testing
Onion Architecture Asp.net Core
WhiteApp API solution template which is built on Onion Architecture with all essential feature using .NET 5!
Stars: ✭ 196 (+988.89%)
Mutual labels:  unit-testing, integration-testing
Movieapp
🎬 MovieApp is a Flutter application built to demonstrate the use of modern development tools with best practices implementation like Modularization, BLoC, Dependency Injection, Dynamic Theme, Cache, Shimmer, Testing, Flavor, CI/CD, etc.
Stars: ✭ 117 (+550%)
Mutual labels:  unit-testing, integration-testing
Hexagonal-architecture-ASP.NET-Core
App generator API solution template which is built on Hexagnonal Architecture with all essential feature using .NET Core
Stars: ✭ 57 (+216.67%)
Mutual labels:  unit-testing, integration-testing
Testing Workshop
A workshop for learning how to test JavaScript applications
Stars: ✭ 1,276 (+6988.89%)
Mutual labels:  unit-testing, integration-testing
Unit Threaded
Advanced unit test framework for D
Stars: ✭ 100 (+455.56%)
Mutual labels:  unit-testing, integration-testing
toUUID
Simple integer to UUID generator for unit and integration tests written in Java or Kotlin
Stars: ✭ 12 (-33.33%)
Mutual labels:  unit-testing, integration-testing
StoreCleanArchitecture-NET
This is a basic project to demonstrate an introduction about the implementation of Clean Architecture on .NET
Stars: ✭ 19 (+5.56%)
Mutual labels:  unit-testing, integration-testing

springboot-keycloak-mongodb-testcontainers

The goals of this project are:

  • Create a Spring Boot application that manages books, called book-service;
  • Use Keycloak as OpenID Connect Provider;
  • Test using Testcontainers;
  • Explore the utilities and annotations that Spring Boot provides when testing applications.

Application

  • book-service

    Spring Boot Web application that manages books. MongoDB is used as storage, and the application's sensitive endpoints (like create, update and delete books) are secured.

    book-service-swagger

Prerequisites

Start Environment

  • Open a terminal and inside springboot-keycloak-mongodb-testcontainers root folder run

    docker-compose up -d
    
  • Wait for keycloak and mongodb Docker containers to be up and running. To check it, run

    docker-compose ps
    

Configure Keycloak

There are two ways: running a script or using Keycloak website

Running Script

  • In a terminal, make sure you are in springboot-keycloak-mongodb-testcontainers root folder

  • Run the following script to configure Keycloak for book-service application

    ./init-keycloak.sh
    

    This script creates:

    • company-services realm;
    • book-service client;
    • manage_books client role;
    • user with username ivan.franchin and password 123 and with the role manage_books assigned.
  • 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

  • You can check the configuration in Keycloak by accessing http://localhost:8080. The credentials are admin/admin.

Using Keycloak Website

keycloak

Login

Create a new Realm

  • Go to top-left corner and hover the mouse over Master realm. Click the Add realm blue button that will appear
  • Set company-services to the Name field and click Create button

Create a new Client

  • On the left menu, click Clients
  • Click Create button
  • Set book-service to Client ID and click Save button
  • In Settings tab
    • Set confidential to Access Type
    • Set http://localhost:9080/* to Valid Redirect URIs
    • Click Save button
  • In Credentials tab, you can find the secret Keycloak generated for simple-service
  • In Roles tab
    • Click Add Role button
    • Set manage_books to Role Name and click Save button

Create a new User

  • On the left menu, click Users
  • Click Add User button
  • Set ivan.franchin to Username field
  • Click Save
  • In Credentials tab
    • Set the value 123 to Password and Password Confirmation
    • Turn off the Temporary field
    • Click Set password button
    • Confirm the popup and click Set Password red button
  • In Role Mappings tab
    • Select book-service on the combo-box Client Roles
    • In Available Roles, select manage_books role and click Add selected >> button

Running book-service with Gradle

  • Open a new terminal and navigate to springboot-keycloak-mongodb-testcontainers root folder

  • Run the following command to start the application

    ./gradlew book-service:clean book-service:bootRun --args='--server.port=9080'
    
  • The application Swagger URL is http://localhost:9080/swagger-ui.html

Getting Access Token

  • Open a terminal and make sure you are in springboot-keycloak-mongodb-testcontainers root folder

  • Create an environment variable that contains the Client Secret generated by Keycloak to book-service at Configure Keycloak step

    BOOK_SERVICE_CLIENT_SECRET=...
    
  • Run the commands below to get an access token for ivan.franchin

    ACCESS_TOKEN=$(./get-access-token.sh $BOOK_SERVICE_CLIENT_SECRET) && echo $ACCESS_TOKEN
    
  • The access token has a default expiration time of 5 minutes

Test using cURL

  • In terminal, call the endpoint GET /api/books

    curl -i http://localhost:9080/api/books
    

    It should return:

    HTTP/1.1 200
    []
    
  • Try to call the endpoint POST /api/books, without access token

    curl -i -X POST http://localhost:9080/api/books \
      -H "Content-Type: application/json" \
      -d '{ "authorName": "Ivan Franchin", "title": "Java 8", "price": 10.5 }'
    

    It should return:

    HTTP/1.1 302
    
  • If you do not have the access token stored in ACCESS_TOKEN environment variable, get it by following the steps describe at Getting Access Token

  • Call the endpoint POST /api/books, now informing the access token

    curl -i -X POST http://localhost:9080/api/books \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{ "authorName": "Ivan Franchin", "title": "Java 8", "price": 10.5 }'
    

    It should return something like

    HTTP/1.1 201
    { "id":"612f4f9438e39e473c4d098b", "authorName":"Ivan Franchin", "title":"Java 8", "price":10.5 }
    

Test using Swagger

  • Access http://localhost:9080/swagger-ui.html

  • Click GET /api/books to open it. Then, click Try it out button and, finally, click Execute button.

    It will return a http status code 200 and an empty list or a list with some books if you've already added them

  • 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.

    It will return

    Failed to fetch
    
  • Get the access token as explained at Getting Access Token

  • Copy the token generated and go back to Swagger

  • Click the Authorize button and paste the access token in the Value field. Then, click Authorize and, to finalize, click Close

  • Go to POST /api/books, click Try it out and, finally, click Execute button.

    It should return something like

    HTTP/1.1 201
    {
      "id": "612f502f38e39e473c4d098c",
      "authorName": "Ivan Franchin",
      "title": "SpringBoot",
      "price": 10.5
    }
    

Running book-service as a Docker Container

  • In a terminal, navigate to springboot-keycloak-mongodb-testcontainers root folder

  • Build Docker Image

    ./gradlew book-service:clean book-service:jibDockerBuild -x test -x integrationTest
    
    Environment Variable Description
    MONGODB_HOST Specify host of the Mongo database to use (default localhost)
    MONGODB_PORT Specify port of the Mongo database to use (default 27017)
    KEYCLOAK_HOST Specify host of the Keycloak to use (default localhost)
    KEYCLOAK_PORT Specify port of the Keycloak to use (default 8080)
  • Run book-service docker container, joining it to docker-compose network

    docker run --rm --name book-service \
      -p 9080:8080 \
      -e MONGODB_HOST=mongodb \
      -e KEYCLOAK_HOST=keycloak \
      --network=springboot-keycloak-mongodb-testcontainers_default \
      ivanfranchin/book-service:1.0.0
    
  • Open a new terminal and create an environment variable that contains the Client Secret generated by Keycloak

    BOOK_SERVICE_CLIENT_SECRET=...
    
  • In order to get the access token from Keycloak, run the following commands

    Note: the "keycloak:8080" string is informed in the second argument of the script. It changes "localhost:8080" host/port inside the script. This way, we won't have the error complaining about an invalid token due to an invalid token issuer.

    ACCESS_TOKEN=$(./get-access-token.sh $BOOK_SERVICE_CLIENT_SECRET "keycloak:8080") && echo $ACCESS_TOKEN
    
  • Test using cURL or Swagger are the same as explained above

Useful Links & Commands

  • MongoDB

    List books

    docker exec -it mongodb mongo bookdb
    db.books.find()
    

    Type exit to get out of MongoDB shell

  • jwt.io

    With jwt.io you can inform the JWT token received from Keycloak and the online tool decodes the token, showing its header and payload.

Shutdown

  • To stop book-service, go to the terminal where the application is running and press Ctrl+C
  • To stop and remove docker-compose containers, networks and volumes, make sure you are in springboot-keycloak-mongodb-testcontainers and run
    docker-compose down -v
    

Cleanup

To remove the Docker image created by this project, go to a terminal and run the following command

docker rmi ivanfranchin/book-service:1.0.0

Running Unit and Integration Tests

  • In a terminal and inside springboot-keycloak-mongodb-testcontainers root folder, run the command below to run unit and integration tests

    ./gradlew book-service:clean book-service:assemble \
      book-service:cleanTest \
      book-service:test \
      book-service:integrationTest
    

    Note: During integration tests, Testcontainers will start automatically MongoDB and Keycloak containers before the tests begin and shuts them down when the tests finish.

  • From springboot-keycloak-mongodb-testcontainers root folder, Unit Testing Report can be found at

    book-service/build/reports/tests/test/index.html
    
  • From springboot-keycloak-mongodb-testcontainers root folder, Integration Testing Report can be found at

    book-service/build/reports/tests/integrationTest/index.html
    

Issues

  • Disabled BookControllerTest because I am getting the exception below. The adapterConfig parameter passed to internalBuild is null
    java.lang.NullPointerException
    	at org.keycloak.adapters.KeycloakDeploymentBuilder.internalBuild(KeycloakDeploymentBuilder.java:57)
    	at org.keycloak.adapters.KeycloakDeploymentBuilder.build(KeycloakDeploymentBuilder.java:202)
    	at org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver.resolve(KeycloakSpringBootConfigResolver.java:41)
    	at org.keycloak.adapters.springsecurity.config.KeycloakSpringConfigResolverWrapper.resolve(KeycloakSpringConfigResolverWrapper.java:40)
    	at org.keycloak.adapters.AdapterDeploymentContext.resolveDeployment(AdapterDeploymentContext.java:89)
    ...
    

References

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].