Loading repository data…
Loading repository data…
ivangfr / repository
The goal of this project is to create a simple Spring Boot REST API, called simple-service, and secure it with Keycloak. Furthermore, the API users will be loaded into Keycloak from OpenLDAP server.
The goal of this project is to create a simple Spring Boot REST API, called simple-service, and secure it with Keycloak. Furthermore, the API users will be loaded into Keycloak from OpenLDAP server.
Note: In the
springboot-react-keycloakrepository, we have implemented amovies-appusingKeycloak(withPKCE). This application consists of two services: the backend that was implemented usingSpring Bootand the frontend implemented withReactJS.
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.
Spring Boot Web Java application that exposes the following endpoints:
GET /api/public: it's a not secured endpoint, everybody can access it.GET /api/private: it's a secured endpoint, only accessible by users that provide a JWT access token issued by Keycloak and the token must contain the role USER.Open a terminal and inside the springboot-keycloak-openldap root folder run:
docker compose up -d
The LDIF file that we will use, springboot-keycloak-openldap/ldap/ldap-mycompany-com.ldif, contains a predefined structure for mycompany.com. Basically, it has 2 groups (developers and admin) and 4 users (Bill Gates, Steve Jobs, Mark Cuban and Ivan Franchin). Additionally, it is defined that Bill Gates, Steve Jobs and Mark Cuban belong to developers group and Ivan Franchin belongs to admin group.
Bill Gates > username: bgates, password: 123
Steve Jobs > username: sjobs, password: 123
Mark Cuban > username: mcuban, password: 123
Ivan Franchin > username: ifranchin, password: 123
There are two ways to import those users: by running a script or by using phpLDAPadmin.
In a terminal and inside the springboot-keycloak-openldap root folder run:
./import-openldap-users.sh
The command below can be used to check the imported users:
ldapsearch -x -D "cn=admin,dc=mycompany,dc=com" \
-w admin -H ldap://localhost:389 \
-b "ou=users,dc=mycompany,dc=com" \
-s sub "(uid=*)"
Access https://localhost:6443
Login with the credentials:
Login DN: cn=admin,dc=mycompany,dc=com
Password: admin
Import the file springboot-keycloak-openldap/ldap/ldap-mycompany-com.ldif.
You should see a tree like the one shown in the picture below:
There are two ways: running a script or using Keycloak website.
In a terminal, make sure you are inside the springboot-keycloak-openldap root folder.
Run the script below to configure Keycloak for simple-service application:
./init-keycloak.sh
It creates company-services realm, simple-service client, USER client role, ldap federation and the users bgates and sjobs with the role USER assigned.
Copy SIMPLE_SERVICE_CLIENT_SECRET value that is shown at the end of the script. It will be needed whenever we call Keycloak to get a JWT access token to access simple-service.
Please have a look at this Medium article, Setting Up OpenLDAP With Keycloak For User Federation
Open a new terminal and make sure you are in the springboot-keycloak-openldap root folder.
Start the application by running the following command:
./mvnw clean spring-boot:run --projects simple-service -Dspring-boot.run.jvmArguments="-Dserver.port=9080"
Open a new terminal.
Call the endpoint GET /api/public:
curl -i http://localhost:9080/api/public
It should return:
HTTP/1.1 200
It is public.
Try to call the endpoint GET /api/private without authentication:
curl -i http://localhost:9080/api/private
It should return:
HTTP/1.1 401
Create an environment variable that contains the Client Secret generated by Keycloak to simple-service at Configure Keycloak step:
SIMPLE_SERVICE_CLIENT_SECRET=...
Run the command below to get an access token for bgates user:
BGATES_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=bgates" \
-d "password=123" \
-d "grant_type=password" \
-d "client_secret=$SIMPLE_SERVICE_CLIENT_SECRET" \
-d "client_id=simple-service" | jq -r .access_token)
echo $BGATES_ACCESS_TOKEN
Note: In jwt.io, you can decode and verify the
JWTaccess token
Call the endpoint GET /api/private:
curl -i http://localhost:9080/api/private -H "Authorization: Bearer $BGATES_ACCESS_TOKEN"
It should return:
HTTP/1.1 200
bgates, it is private.
The access token default expiration period is 5 minutes. So, wait for this time and, using the same access token, try to call the private endpoint.
It should return:
HTTP/1.1 401
WWW-Authenticate: Bearer realm="company-services", error="invalid_token", error_description="Token is not active"
Click GET /api/public to open it. Then, click Try it out button and, finally, click Execute button.
It should return:
Code: 200
Response Body: It is public.
Now click GET /api/private secured endpoint. Let's try it without authentication. Then, click Try it out button and, finally, click Execute button.
It should return:
Code: 401
Details: Error: response status is 401
In order to access the private endpoint, you need an access token. So, open a terminal.
Create an environment variable that contains the Client Secret generated by Keycloak to simple-service at Configure Keycloak step:
SIMPLE_SERVICE_CLIENT_SECRET=...
Run the following commands:
BGATES_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=bgates" \
-d "password=123" \
-d "grant_type=password" \
-d "client_secret=$SIMPLE_SERVICE_CLIENT_SECRET" \
-d "client_id=simple-service" | jq -r .access_token)
echo $BGATES_ACCESS_TOKEN
Copy the token generated and go back to Swagger.
Click Authorize button and paste the access token in the Value field. Then, click Authorize button and, to finalize, click Close.
Go to GET /api/private and call this endpoint again, now with authentication.
It should return:
Code: 200
Response Body: bgates, it is private.
You can get an access token for simple-service using client_id and client_secret
Keycloak and select company-services.Clients.simple-service client.Settings tab:
Capability config and check Service accounts roles checkbox.Save button.Service account roles tab:
service-account-simple-service link present in the info message.
"To manage detail and group mappings, click on the username service-account-simple-service"
Role mapping tab:
Assign role button.Filter by clients is selected in the first dropdown button.Search by role name, type simple-service and press Enter.[simple-service] USER name and click Assign button.service-account-simple-service has the role USER of the simple-service assigned.Open a terminal.
Create an environment variable that contains the Client Secret generated by Keycloak to simple-service at Configure Keycloak step.
SIMPLE_SERVICE_CLIENT_SECRET=...
Run the following command:
CLIENT_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 "grant_type=client_credentials" \
-d "client_secret=$SIMPLE_SERVICE_CLIENT_SECRET" \
-d "client_id=simple-service" | jq -r .access_token)
echo $CLIENT_ACCESS_TOKEN
Try to call the endpoint `GET /api/priv