GithubHelp home page GithubHelp logo

ivangfr / springboot-keycloak-mongodb-testcontainers Goto Github PK

View Code? Open in Web Editor NEW
34.0 3.0 21.0 1.21 MB

The goals of this project are: 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 when testing applications.

Java 89.79% Shell 10.21%
spring-boot mongodb keycloak unit-testing integration-testing testcontainers java mapstruct oauth2-resourceserver docker

springboot-keycloak-mongodb-testcontainers's Introduction

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.

Proof-of-Concepts & Articles

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

Additional Readings

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 the script below

./init-environment.sh

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

Login

Create a new Realm

  • On the left menu, click the dropdown button that contains Keycloak and then, click Create Realm button
  • Set company-services to the Realm name field and click Create button

Disable Required Action Verify Profile

  • On the left menu, click Authentication
  • Select Required actions tab
  • Disable Verify Profile

Create a new Client

  • On the left menu, click Clients
  • Click Create client button
  • In General Settings
    • Set book-service to Client ID
    • Click Next button
  • In Capability config
    • Enable Client authentication toggle switch
    • Click Next button
  • In Login settings tab
    • Set http://localhost:9080/* to Valid redirect URIs
    • Click Save button
  • In Credentials tab, you can find the secret generated for book-service
  • In Roles tab
    • Click Create role button
    • Set manage_books to Role Name
    • Click Save button

Create a new User

  • On the left menu, click Users
  • Click Create new user button
  • Set ivan.franchin to Username field
  • Click Create
  • In Credentials tab
    • Click Set password button
    • Set the value 123 to Password and Password confirmation
    • Disable the Temporary field toggle switch
    • Click Save button
    • Confirm by clicking Save password button
  • In Role Mappings tab
    • Click Assign role button
    • Click Filter by realm roles dropdown button and select Filter by clients
    • Select [book-service] manage_books name and click Assign 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'
    

Running book-service as a Docker Container

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

  • Build Docker Image

    ./docker-build.sh
    
    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 project Docker network

    docker run --rm --name book-service \
      -p 9080:8080 \
      -e MONGODB_HOST=mongodb \
      -e KEYCLOAK_HOST=keycloak \
      --network=springboot-keycloak-mongodb-testcontainers-net \
      ivanfranchin/book-service:1.0.0
    

Getting Access Token

  • In a terminal, create an environment variable that contains the Client Secret generated by Keycloak to book-service at Configure Keycloak step

    BOOK_SERVICE_CLIENT_SECRET=...
    
  • When running book-service with Gradle

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

    ACCESS_TOKEN=$(curl -s -X POST \
      "http://localhost:8080/realms/company-services/protocol/openid-connect/token" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "username=ivan.franchin" \
      -d "password=123" \
      -d "grant_type=password" \
      -d "client_secret=$BOOK_SERVICE_CLIENT_SECRET" \
      -d "client_id=book-service" | jq -r .access_token)
    echo $ACCESS_TOKEN
    
  • When running book-service as a Docker Container

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

    ACCESS_TOKEN=$(
      docker run -t --rm -e CLIENT_SECRET=$BOOK_SERVICE_CLIENT_SECRET --network springboot-keycloak-mongodb-testcontainers-net alpine/curl:latest sh -c '
        curl -s -X POST http://keycloak:8080/realms/company-services/protocol/openid-connect/token \
          -H "Content-Type: application/x-www-form-urlencoded" \
          -d "username=ivan.franchin" \
          -d "password=123" \
          -d "grant_type=password" \
          -d "client_secret=$CLIENT_SECRET" \
          -d "client_id=book-service"' | jq -r .access_token)
    echo $ACCESS_TOKEN
    

    Note: We are running a alpine/curl Docker container and joining it to the project Docker network. By informing "keycloak:8080" host/port we won't have the error complaining about an invalid token due to an invalid token issuer.

  • In jwt.io, you can decode and verify the JWT access token

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 401
    
  • Get the Access Token as explained on section 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

    Code: 401
    Details: Error: response status is 401
    
  • Get the Access Token as explained on section 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
    }
    

Useful Links & Commands

  • MongoDB

    List books

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

    Type exit to get out of MongoDB shell

Shutdown

  • To stop book-service, go to the terminal where the application is running and press Ctrl+C;
  • To stop the Docker containers started using ./init-environment.sh script, make sure you are in springboot-keycloak-mongodb-testcontainers and run the script below:
    ./shutdown-environment.sh
    

Cleanup

To remove the Docker image created by this project, go to a terminal and, inside springboot-keycloak-mongodb-testcontainers root folder, run the following script

./remove-docker-images.sh

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
    

springboot-keycloak-mongodb-testcontainers's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

springboot-keycloak-mongodb-testcontainers's Issues

[Question] creating frontend service

First of all, you have done a great job with this repository., many things became clear for me regarding keycloak.
You seem as a knowledgable person in the keycloak topic. I'm trying to create similar integration, but in my case I want to have public frontend and confidential/bearer-only backend. I have tried to create two keycloak clients, however the token is not passed between services. Maybe you had the similar issue?

I'm not sure if this is a place to ask that kind of question.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.