The goal of this project is to implement an application called order-app to manage orders. For it, we will implement a back-end application called order-api using Spring Boot and a font-end application called order-ui using ReactJS. Besides, we will use JWT Authentication to secure both applications.
-
order-api
Spring BootWeb Java backend application that exposes a Rest API to create, retrieve and delete orders. If a user hasADMINrole he/she can also retrieve information of other users or delete them.The application secured endpoints can just be accessed if a valid JWT access token is provided.
order-apistores its data inMySQLdatabase.order-apihas the following endpointsEndpoint Secured Roles POST /auth/authenticate -d {"username","password"}No POST /auth/signup -d {"username","password","name","email"}No GET /public/numberOfUsersNo GET /public/numberOfOrdersNo GET /api/users/meYes ADMIN,USERGET /api/usersYes ADMINGET /api/users/{username}Yes ADMINDELETE /api/users/{username}Yes ADMINGET /api/ordersYes ADMINGET /api/orders/{id}Yes ADMIN,USERPOST /api/orders -d {"description"}Yes ADMIN,USERDELETE /api/orders/{id}Yes ADMIN -
order-ui
ReactJSfrontend application where a user with roleUSERcan create an order and retrieve a specific order. On the other hand, a user with roleADMINas access to all secured endpoints.In order to access the application, a
useroradminmust login using his/herusernameandpassword. All the requests coming fromorder-uito secured endpoints inorder-apihave the JWT access token. This token is generated when theuseroradminlogins.order-uiusesSemantic UI Reactas CSS-styled framework.
-
jq
In order to run some commands/scripts, you must have
jqinstalled on you machine
-
Open a terminal and inside
springboot-react-jwt-tokenroot folder rundocker-compose up -d -
Wait a little bit until
mysqlcontainer is Up (healthy). You can check their status runningdocker-compose ps
-
order-api
-
Open a terminal and navigate to
springboot-react-jwt-token/order-apifolder -
Run the following
Mavencommand to start the application./mvnw clean spring-boot:run
-
-
order-ui
-
Open another terminal and navigate to
springboot-react-jwt-token/order-uifolder -
[Optional] Run the command below if you are running the application for the first time
npm install -
Run the
npmcommand below to start the applicationnpm start
-
| Application | URL | Credentials |
|---|---|---|
| order-api | http://localhost:8080/swagger-ui.html | |
| order-ui | http://localhost:3000 | admin/admin or user/user |
Note: the credentials shown in the table are the ones already pre-defined. You can signup new users
The gif below shows ...
-
Manual Endpoints Test using Swagger
-
Open a browser and access http://localhost:8080/swagger-ui.html. All endpoints with the lock sign are secured. In order to access them, you need a valid JWT access token.
-
Click on
auth-controller, then onPOST /auth/authenticateand, finally, onTry it out -
Provide the
usercredentialsusernameandpasswordand click onExecutebutton{ "password": "user", "username": "user" }It should return something like
Code: 200 { "accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9..." }Note 1: You can use the
admincredentials to access more secured endpointsNote 2: The token will expire in 10 minutes
-
Copy the
accessTokenvalue (without the double quotes) -
Click on the
Authorizebutton on the top of the page -
On
Valueinput field, paste the copied token prefixed byBearerand a spaceBearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9... -
Click on
Authorizeand then onClose -
To create an order, click on
order-controller, then, click onPOST /api/ordersand onTry it out -
Provide the
descriptionof the order{ "description": "Buy two iPhones" } -
Click on
Executebutton. It should return something likeCode: 200 { "id": "ccc4b36d-bda4-4f41-b6c2-f19c77f0243f", "description": "Buy two iPhones" }
-
-
Manual Endpoints Test using curl
-
Open a terminal
-
Call
GET /public/numberOfUserscurl -i localhost:8080/public/numberOfUsersIt should return
HTTP/1.1 200 2 -
Call
GET /api/orders/{id}without JWT access tokencurl -i localhost:8080/api/orders/6ce8cdf5-004d-4511-a6a1-604945246af8As for this endpoint a valid JWT access token is required, it should return
HTTP/1.1 401 -
Call
POST /auth/authenticateto getuserJWT access tokenUSER_ACCESS_TOKEN="$(curl -s -X POST http://localhost:8080/auth/login \ -H 'Content-Type: application/json' \ -d '{"username": "user", "password": "user"}' | jq -r .accessToken)" -
Call again
GET /api/orders/{id}, now withuserJWT access tokencurl -i -H "Authorization: Bearer $USER_ACCESS_TOKEN" localhost:8080/api/orders/6ce8cdf5-004d-4511-a6a1-604945246af8It should return
HTTP/1.1 200 { "id":"6ce8cdf5-004d-4511-a6a1-604945246af8", "description":"Buy one MacBook Pro" } -
Call
GET /api/users/meto get more information about theusercurl -i -H "Authorization: Bearer $USER_ACCESS_TOKEN" localhost:8080/api/users/meIt should return
HTTP/1.1 200 { "id": 2, "username": "user", "name": "User", "email": "user@mycompany.com", "role": "USER", "orders": [ ... ] }
-
-
Automatic Endpoints Test
-
Open a terminal and make sure you are in
springboot-react-jwt-tokenroot folder -
Run the following script
./order-api/test-endpoints.shIt should return something like the output below, where it shows the http code for different requests
GET auth/authenticate ===================== admin access token ------------------ eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJleHAiOjE1ODY2MjM1MjksImlhdCI6MTU4Nj..._ha2pM4LSSG3_d4exgA user access token ----------------- eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJleHAiOjE1ODY2MjM1MjksImlhdCIyOSwian...Y3z9uwhuW_nwaGX3cc5A GET auth/signup =============== user2 access token ------------------ eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJleHAiOjE1ODY2MjM1MjksImanRpIjoiYTMw...KvhQbsMGAlFov1Q480qg Authorization ============= Endpoints | without token | user token | admin token | ------------------------- + ------------- + ----------- + ------------ | GET public/numberOfUsers | 200 | 200 | 200 | GET public/numberOfOrders | 200 | 200 | 200 | ......................... + ............. + ........... + ............ | GET /api/users/me | 401 | 200 | 200 | GET /api/users | 401 | 403 | 200 | GET /api/users/user2 | 401 | 403 | 200 | DELETE /api/users/user2 | 401 | 403 | 200 | ......................... + ............. + ........... + ............ | GET /api/orders | 401 | 403 | 200 | POST /api/orders | 401 | 201 | 201 | GET /api/orders/{id} | 401 | 200 | 200 | DELETE /api/orders/{id} | 401 | 403 | 200 | ------------------------------------------------------------------------ [200] Success - [201] Created - [401] Unauthorized - [403] Forbidden
-
-
MySQL
docker exec -it mysql mysql -uroot -psecret --database=orderdb show tables; -
jwt.io
With jwt.io you can inform the JWT token and the online tool decodes the token, showing its header and payload.
-
Go to
order-apiandorder-uiterminals and pressCtrl+Con each one -
To stop and remove docker-compose containers, networks and volumes, run the command below in
springboot-react-jwt-tokenroot folderdocker-compose down -v
-
In a terminal, make sure you are in
springboot-react-jwt-token/order-uifolder -
Run the following commands
npm i -g npm-check-updates ncu -u npm install