DEV Community

Cover image for Let’s Implement JWT Based Authentication in Spring boot
Nil Madhab
Nil Madhab

Posted on • Edited on • Originally published at api.simplecoding.dev

1

Let’s Implement JWT Based Authentication in Spring boot

Part 2: Integrate database and implement Signup, Login features

Photo by [Markus Winkler](https://unsplash.com/@markuswinkler?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

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() {
}
}
view raw JwtUser.java hosted with ❤ by GitHub

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();
}
Enter fullscreen mode Exit fullscreen mode

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"));
}

signup

Step 6 Implement the signIn

  1. we authenticate the user, by the spring security authenticate method

  2. set the authentication in context

  3. get the user from DB

  4. Create JWT and send it in response

    @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

JWT expired 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

  1. create various roles like ADMIN, USER, MODERATOR

  2. We will integrate it in our e-commerce tutorial

  3. We will use social login using GitHub and create a frontend using Vue.js

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay