Part 2: Integrate database and implement Signup, Login features
In part 1, we implemented the basic JWT auth without real database, by hardcoding user
In this tutorial, we will extend the JWT auth by integrating with real users in the MySQL database and implementing signup, login functionality using BCryptPasswordEncoder for hashing password.
You can find the github code here
Step 1 : Create the User Model
create Jwtuser model and reimplement the UserDetailsService interface of spring security.
package com.simplecoding.jwt.model; | |
import javax.persistence.*; | |
@Entity | |
@Table(name = "users") | |
public class JwtUser { | |
@Id | |
@GeneratedValue(strategy = GenerationType.IDENTITY) | |
private Integer id; | |
@Column(name = "email") | |
private String email; | |
@Column(name = "password") | |
private String password; | |
public Integer getId() { | |
return id; | |
} | |
public void setId(Integer id) { | |
this.id = id; | |
} | |
public String getEmail() { | |
return email; | |
} | |
public void setEmail(String email) { | |
this.email = email; | |
} | |
public String getPassword() { | |
return password; | |
} | |
public void setPassword(String password) { | |
this.password = password; | |
} | |
public JwtUser( String email, String password) { | |
this.email = email; | |
this.password = password; | |
} | |
public JwtUser() { | |
} | |
} |
Step 2: Reimplement the UserDetailsService Interface of Spring Security
Reimplement the UserDetailsService and override the loadUserByUsername method which we previously hardcoded.
package com.simplecoding.jwt.service; | |
import com.simplecoding.jwt.model.JwtUser; | |
import com.simplecoding.jwt.repo.JwtUserRepository; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.security.core.userdetails.User; | |
import org.springframework.security.core.userdetails.UserDetails; | |
import org.springframework.security.core.userdetails.UserDetailsService; | |
import org.springframework.security.core.userdetails.UsernameNotFoundException; | |
import org.springframework.stereotype.Service; | |
import java.util.ArrayList; | |
@Service | |
public class CustomUserDetailsService implements UserDetailsService { | |
@Autowired | |
JwtUserRepository jwtUserRepository; | |
@Override | |
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { | |
JwtUser jwtUser = jwtUserRepository.findUserByEmail(email); | |
if (jwtUser == null) { | |
throw new UsernameNotFoundException("email Not found" + email); | |
} | |
return new User(jwtUser.getEmail(), jwtUser.getPassword(), new ArrayList<>()); | |
} | |
} |
Step 3: Update the SecurityConfigurer
We change the passwordencoder method in SecurityConfigurer file to encrypt the password
@Bean
**public **PasswordEncoder passwordEncoder(){
**return new **BCryptPasswordEncoder();
}
We also need to update the anteaters to not use authentication when using Signup, signIn methods
@Override | |
public void configure(HttpSecurity security) throws Exception { | |
security.csrf().disable() | |
.authorizeRequests() | |
.antMatchers("/authenticate", "/signin", "/signup").permitAll() | |
.anyRequest().authenticated().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); | |
security.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); | |
} |
Step 4 Implement the Signup Api
The code is self explanatory, we find if email is not present already, hash the password by passwordencoder, and save the user in DB.
@PostMapping("/signup") | |
public ResponseEntity<?> registerUser(@Valid @RequestBody SignUpRequest signUpRequest) { | |
if(userRepository.findUserByEmail(signUpRequest.getEmail()) != null) { | |
return new ResponseEntity(new ApiResponse(false, "Email Address already in use!"), | |
HttpStatus.BAD_REQUEST); | |
} | |
// Creating user's account | |
JwtUser jwtUser = new JwtUser(); | |
jwtUser.setEmail(signUpRequest.getEmail()); | |
jwtUser.setPassword(passwordEncoder.encode(signUpRequest.getPassword())); | |
userRepository.save(jwtUser); | |
return ResponseEntity.ok(new ApiResponse(true, "User registered successfully")); | |
} |

Step 6 Implement the signIn
we authenticate the user, by the spring security authenticate method
set the authentication in context
get the user from DB
-
Create JWT and send it in response
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters@PostMapping("/signin") public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) { Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken( loginRequest.getUsernameOrEmail(), loginRequest.getPassword() ) ); SecurityContextHolder.getContext().setAuthentication(authentication); UserDetails userDetails = userDetailsService.loadUserByUsername(loginRequest.getUsernameOrEmail()); final String jwt = jwtUtil.generateToken(userDetails); return ResponseEntity.ok(new AuthenticationResponse(jwt)); }
Step 7 : Test an API with an Authorization header consist of JWT token
If the token is expired, we will get this error
If the token is valid, we will get the user from the JWT token and we can create various rules for authorization
@GetMapping("/checkUser") | |
public String checkUser(){ | |
Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | |
String currentPrincipalName = authentication.getName(); | |
return currentPrincipalName; | |
} |

Next steps
create various roles like ADMIN, USER, MODERATOR
We will integrate it in our e-commerce tutorial
We will use social login using GitHub and create a frontend using Vue.js
Top comments (0)