/jwt-spring-react-example

Example application for JWT authentication with Spring and React, using axios.

Primary LanguageJava

P3Admin

Spring JWT React

This is an example application showing how to use JWT authentication within a React app using Spring as a backend.

Backend

This application uses MariaDB as a database. To run it you can use Docker. Run the docker-compose.yml file in the root folder which will setup everything automatically:

  • download mariadb image
  • setup root password of mysql admin user (root)
  • create database (p3admin_db)
  • bind container to port 3306

When you run the BackendApplication then a CommandLineRunner is executed that creates some default roles and users:

  • Roles
    • Admin
    • Therapist
    • Secretary
  • Users
    • admin/admin
    • therapist/therapist
    • secretary/secretary

The configuration package contains the essentials for the JWT security setup. In the SecurityCfg class you will find HttpSecurity configuration which blocks any REST calls to /api/v1/roles if a user does not have the ADMIN role.

.antMatchers("/api/v1/refresh-token").permitAll()
.antMatchers("/api/v1/roles").hasRole(Role.RoleType.ADMIN.name())

The filter package contains the JWT specifics for any request made to the backend.

The JwtAuthenticationFilter is responsible for the authentication via username and password. If it receives valid credentials then an AUTH and REFRESH token is created and returned in the HttpResponse.

The JwtAuthorizationFilter is then used for each future request to validate the passed JWT Token and to inform Spring about the authorities (=roles) that this request has.

If the AUTH token is expired then a user can refresh it by using the /refresh-token endpoint of the UserController.

Here are some example http requests:

### login with admin
curl -X POST --location "http://localhost:8080/api/v1/login" \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "username=admin&password=admin"

### refresh a token
curl -X POST --location "http://localhost:8080/api/v1/refresh-token" \
    -H "Authorization: Bearer %JWT_REFRESH_TOKEN%"
    
### getUsers
curl -X GET --location "http://localhost:8080/api/v1/users?page=0&pageSize=50" \
    -H "Authorization: Bearer %JWT_AUTH_TOKEN%"
    
### getRoles - this will not work for the user secretary because of missing admin role
curl -X GET --location "http://localhost:8080/api/v1/roles?page=0&pageSize=50" \
    -H "Authorization: Bearer %JWT_AUTH_TOKEN%"

Frontend

The frontend is a very basic React application in Typescript using Material UI and Axios.

It has a Login page where you can change the theme between light and dark. Also, in case of an error it will show that. Forgot Password? is not implemented.

After a successful login it fetches the users of the backend with axios. Axios is configured to use interceptors to automatically refresh the JWT Token whenever necessary and to provide the auth token for each request. Also, the user with its tokens and roles is stored in the localStorage until the user logs out or the token cannot be refreshed anymore. The code can be found in the api.ts and auth-service.ts.

image image image