The goal of this project is to secure movies-app using Keycloak(with PKCE). movies-app consists of two applications: one is a Spring Boot Rest API called movies-api and another is a React application called movies-ui.
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.
- [Medium] Implementing a Full Stack Web App using Spring-Boot and React
- [Medium] Using Keycloak to secure a Full Stack Web App implemented with Spring-Boot and React
- [Medium] Implementing and Securing a Simple Spring Boot REST API with Keycloak
- [Medium] Implementing and Securing a Simple Spring Boot UI (Thymeleaf + RBAC) with Keycloak
- [Medium] Implementing and Securing a Spring Boot GraphQL API with Keycloak
- [Medium] Setting Up OpenLDAP With Keycloak For User Federation
- [Medium] Integrating GitHub as a Social Identity Provider in Keycloak
- [Medium] Integrating Google as a Social Identity Provider in Keycloak
- [Medium] Building a Single Spring Boot App with Keycloak or Okta as IdP: Introduction
- 
Spring BootWeb Java backend application that exposes a REST API to manage movies. Its secured endpoints can just be accessed if an access token (JWT) issued byKeycloakis provided.movies-apistores its data in aMongodatabase.movie-apihas the following endpoints:Endpoint Secured Roles GET /api/userextras/meYes MOVIES_ADMINandMOVIES_USERPOST /api/userextras/me -d {avatar}Yes MOVIES_ADMINandMOVIES_USERGET /api/moviesNo GET /api/movies/{imdbId}No POST /api/movies -d {"imdb","title","director","year","poster"}Yes MOVIES_ADMINDELETE /api/movies/{imdbId}Yes MOVIES_ADMINPOST /api/movies/{imdbId}/comments -d {"text"}Yes MOVIES_ADMINandMOVIES_USER
- 
Reactfrontend application whereuserscan see and comment movies andadminscan manage movies. To access the application,user/adminmust login using his/her username and password. Those credentials are managed byKeycloak. All the requests frommovies-uito secured endpoints inmovies-apiinclude an access token (JWT) that is generated whenuser/adminlogs in.movies-uiusesSemantic UI Reactas CSS-styled framework.
- 
Java 21or higher;
- 
OMDb APIKEYTo use the Wizardoption to search and add a movie, we need to get an API KEY from OMDb API. To do this, access https://www.omdbapi.com/apikey.aspx and follow the steps provided by the website.Once we have the API KEY, create a file called .env.localin thespringboot-react-keycloak/movies-uifolder with the following content:REACT_APP_OMDB_API_KEY=<your-api-key>
As Keycloak supports PKCE (Proof Key for Code Exchange) since version 7.0.0, we are using it in this project.
In a terminal, navigate to the springboot-react-keycloak root folder and run:
./init-environment.shIn a terminal and inside the springboot-react-keycloak root folder run:
./init-keycloak.shThis script will:
- create company-servicesrealm;
- disable the required action Verify Profile;
- create movies-appclient;
- create the client role MOVIES_USERfor themovies-appclient;
- create the client role MOVIES_ADMINfor themovies-appclient;
- create USERSgroup;
- create ADMINSgroup;
- add USERSgroup as realm default group;
- assign MOVIES_USERclient role toUSERSgroup;
- assign MOVIES_USERandMOVIES_ADMINclient roles toADMINSgroup;
- create useruser;
- assign USERSgroup to user;
- create adminuser;
- assign ADMINSgroup to admin.
- 
movies-api - 
Open a terminal and navigate to the springboot-react-keycloak/movies-apifolder;
- 
Run the following Mavencommand to start the application:./mvnw clean spring-boot:run -Dspring-boot.run.jvmArguments="-Dserver.port=9080"
- 
We can also configure Social Identity Providers such as, GitHub,Google,FacebookandInstagram. I've written two articles in Medium where I explain step-by-step how to integrate GitHub and Google.
 
- 
- 
movies-ui - 
Open another terminal and navigate to the springboot-react-keycloak/movies-uifolder;
- 
Run the command below if you are running the application for the first time: npm install 
- 
Run the npmcommand below to start the application:npm start 
 
- 
| Application | URL | Credentials | 
|---|---|---|
| movie-api | http://localhost:9080/swagger-ui.html | Access Token | 
| movie-ui | http://localhost:3000 | admin/adminoruser/user | 
| Keycloak | http://localhost:8080 | admin/admin | 
- 
The gif below shows an adminlogging in and adding one movie using the wizard feature:
- 
The gif below shows a userlogging in using his Github account; then he changes his avatar and comment on a movie:
We can manage movies by directly accessing movies-api endpoints using the Swagger website or curl. For the secured endpoints like POST /api/movies, PUT /api/movies/{id}, DELETE /api/movies/{id}, etc, we need to inform an access token issued by Keycloak.
- 
Open a terminal. 
- 
Run the following commands to get the access token: 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=admin" \ -d "password=admin" \ -d "grant_type=password" \ -d "client_id=movies-app" | jq -r .access_token)" echo $ACCESS_TOKEN Note: In jwt.io, we can decode and verify the JWTaccess token.
- 
Trying to add a movie without access token: curl -i -X POST "http://localhost:9080/api/movies" \ -H "Content-Type: application/json" \ -d '{ "imdbId": "tt5580036", "title": "I, Tonya", "director": "Craig Gillespie", "year": 2017, "poster": "https://m.media-amazon.com/images/M/MV5BMjI5MDY1NjYzMl5BMl5BanBnXkFtZTgwNjIzNDAxNDM@._V1_SX300.jpg"}' It should return: HTTP/1.1 401
- 
Trying again to add a movie, now with access token (obtained at getting-access-token): curl -i -X POST "http://localhost:9080/api/movies" \ -H "Authorization: Bearer $ACCESS_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "imdbId": "tt5580036", "title": "I, Tonya", "director": "Craig Gillespie", "year": 2017, "poster": "https://m.media-amazon.com/images/M/MV5BMjI5MDY1NjYzMl5BMl5BanBnXkFtZTgwNjIzNDAxNDM@._V1_SX300.jpg"}' It should return: HTTP/1.1 201 { "imdbId": "tt5580036", "title": "I, Tonya", "director": "Craig Gillespie", "year": "2017", "poster": "https://m.media-amazon.com/images/M/MV5BMjI5MDY1NjYzMl5BMl5BanBnXkFtZTgwNjIzNDAxNDM@._V1_SX300.jpg", "comments": [] }
- 
Getting the list of movies. This endpoint does not require access token: curl -i http://localhost:9080/api/movies It should return: HTTP/1.1 200 [ { "imdbId": "tt5580036", "title": "I, Tonya", "director": "Craig Gillespie", "year": "2017", "poster": "https://m.media-amazon.com/images/M/MV5BMjI5MDY1NjYzMl5BMl5BanBnXkFtZTgwNjIzNDAxNDM@._V1_SX300.jpg", "comments": [] } ]
- 
Access movies-apiSwagger website, http://localhost:9080/swagger-ui.html.
- 
Click Authorizebutton.
- 
In the form that opens, paste the access token(obtained at getting-access-token) in theValuefield. Then, clickAuthorizeandCloseto finalize.
- 
Done! We can now access the secured endpoints. 
- 
MongoDB List all movies: docker exec -it mongodb mongosh moviesdb db.movies.find() Type exitto exit of MongoDB shell.
- 
To stop movies-apiandmovies-ui, go to the terminals where they are running and pressCtrl+C;
- 
To stop and remove docker containers, network and volumes, go to a terminal and, inside the springboot-react-keycloakroot folder, run the command below:./shutdown-environment.sh 
- 
In a terminal, make sure you are in the springboot-react-keycloak/movies-uifolder;
- 
Run the following commands: npm upgrade npm i -g npm-check-updates ncu -u npm install 


