Spring Boot
Implementing JWT Authentication in Spring Boot 3: A Complete Guide
By Utility Zone · 2025-11-01T16:22:25.832766
This comprehensive tutorial walks through implementing JWT (JSON Web Token) authentication in a Spring Boot 3 application with Spring Security 6. You'll build a complete authentication system from scratch with user registration, login, and token-based access control.
Step 1: Add Required Dependencies
Maven Dependencies
Add the following dependencies to your pom.xml file:12
<dependencies>
<!-- Spring Boot Starters -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JWT Dependencies -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<!-- Database (H2 for this example) -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
Gradle Dependencies
For Gradle projects, add to your build.gradle file:1
dependencies {
// Spring Security
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
// JJWT (Java JWT) API, Implementation, and Jackson support
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'
// Database
runtimeOnly 'com.h2database:h2'
}
Step 2: Configure Application Properties
Add JWT configuration to application.properties:2
# Database Configuration (H2 example)
spring.h2.console.enabled=true
spring.h2.console.path=/h2-ui
spring.datasource.url=jdbc:h2:file:./testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
# JPA Configuration
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update
# JWT Properties
app.jwtSecret======================YourSecretKeyHere===========================
app.jwtExpirationMs=86400000
app.jwtCookieName=authToken
Important: The JWT secret should be at least 256 bits (32 characters) for HS256 algorithm. For production, store this in environment variables or a secure vault.3
Step 3: Create Domain Models
User Entity
package com.example.security.models;
import jakarta.persistence.*;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import java.util.HashSet;
import java.util.Set;
@Entity
@Table(name = "users",
uniqueConstraints = {
@UniqueConstraint(columnNames = "username"),
@UniqueConstraint(columnNames = "email")
})
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@Size(max = 20)
private String username;
@NotBlank
@Size(max = 50)
@Email
private String email;
@NotBlank
@Size(max = 120)
private String password;
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set<Role> roles = new HashSet<>();
// Constructors
public User() {}
public User(String username, String email, String password) {
this.username = username;
this.email = email;
this.password = password;
}
// Getters and Setters
// ... (add all getters and setters)
}
Role Entity
package com.example.security.models;
import jakarta.persistence.*;
@Entity
@Table(name = "roles")
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Enumerated(EnumType.STRING)
@Column(length = 20)
private ERole name;
// Constructors
public Role() {}
public Role(ERole name) {
this.name = name;
}
// Getters and Setters
// ... (add all getters and setters)
}
ERole Enum
package com.example.security.models;
public enum ERole {
ROLE_USER,
ROLE_MODERATOR,
ROLE_ADMIN
}
Step 4: Create Repositories
UserRepository
package com.example.security.repository;
import com.example.security.models.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
Boolean existsByUsername(String username);
Boolean existsByEmail(String email);
}
RoleRepository
package com.example.security.repository;
import com.example.security.models.ERole;
import com.example.security.models.Role;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
Optional<Role> findByName(ERole name);
}
Step 5: Implement UserDetailsService
UserDetailsImpl
package com.example.security.services;
import com.example.security.models.User;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class UserDetailsImpl implements UserDetails {
private static final long serialVersionUID = 1L;
private Long id;
private String username;
private String email;
@JsonIgnore
private String password;
private Collection<? extends GrantedAuthority> authorities;
public UserDetailsImpl(Long id, String username, String email, String password,
Collection<? extends GrantedAuthority> authorities) {
this.id = id;
this.username = username;
this.email = email;
this.password = password;
this.authorities = authorities;
}
public static UserDetailsImpl build(User user) {
List<GrantedAuthority> authorities = user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority(role.getName().name()))
.collect(Collectors.toList());
return new UserDetailsImpl(
user.getId(),
user.getUsername(),
user.getEmail(),
user.getPassword(),
authorities);
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
public Long getId() {
return id;
}
public String getEmail() {
return email;
}
@Override
public String getPassword() {
return password;
}
@Override
@Override
public String getUsername() {
return username;
}
}
<span style="display:none">45678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364</span>
<div align="center">⁂</div>
Footnotes
-
https://ademtonay.com/posts/authentication-with-jwt-and-spring-boot ↩ ↩2
-
https://www.reddit.com/r/SpringBoot/comments/1kdnv1g/where_should_i_store_my_jwt_secret_instead_of/ ↩
-
https://blog.devops.dev/spring-boot-3-spring-security-6-with-jwt-authentication-and-authorization-new-2024-989323f29b84?gi=e37f918c9c33 ↩
-
https://www.geeksforgeeks.org/springboot/spring-boot-3-0-jwt-authentication-with-spring-security-using-mysql-database/ ↩
-
https://stackoverflow.com/questions/74828917/maven-dependencies-for-jjwt-json-web-token-on-a-spring-boot-project ↩
-
https://dev.to/abhi9720/a-comprehensive-guide-to-jwt-authentication-with-spring-boot-117p ↩
-
https://docs.spring.io/spring-security/reference/getting-spring-security.html ↩
-
https://stackoverflow.com/questions/72715967/spring-security-implement-jwt-filter ↩
-
https://stackoverflow.com/questions/41975045/how-to-design-a-good-jwt-authentication-filter ↩
-
https://evoila.com/blog/spring-boot-3-jwt-authentication-leveraging-spring-securitys-support/ ↩
-
https://github.com/nomemory/spring-boot-jwt-example/blob/master/build.gradle ↩
-
https://stackoverflow.com/questions/75791404/how-do-i-check-if-a-jwt-token-is-valid-in-spring-boot ↩
-
https://gist.github.com/abhi9720/0384b96419e7b18f7cad2d7962b84404 ↩
-
https://stackoverflow.com/questions/77353001/spring-boot-3-jwt-token-generation ↩
-
https://www.reddit.com/r/SpringBoot/comments/184ixyw/does_anyone_know_how_to_enable_jwt_security_and/ ↩
-
https://github.com/ramazan/spring-boot-jwt-security-example/blob/master/src/main/java/com/ramazan/security/configuration/jwt/service/JwtUserDetailsService.java ↩
-
https://stackoverflow.com/questions/50803727/spring-with-jwt-auth-get-current-user ↩
-
https://www.unlogged.io/post/integrating-jwt-with-spring-security-6-in-spring-boot-3 ↩
-
https://stackoverflow.com/questions/58685218/spring-security-how-to-use-a-userdetailsservice-with-jwtauthenticationprovider ↩
-
https://docs.spring.io/spring-security/reference/servlet/authentication/passwords/user-details-service.html ↩
-
https://docs.spring.io/spring-security/reference/servlet/configuration/java.html ↩
-
https://www.javaguides.net/2024/04/spring-security-authentication-manager.html ↩
-
https://stackoverflow.com/questions/78836490/validate-jwt-java17-spring-security-jwt0-12-6 ↩
-
https://github.com/spring-projects/spring-boot/issues/11136 ↩
-
https://github.com/Java-Techie-jt/spring-security-jwt-example/blob/master/src/main/java/com/javatechie/jwt/api/util/JwtUtil.java ↩
-
https://docs.spring.io/spring-security/reference/servlet/authentication/passwords/index.html ↩
-
https://codersee.com/spring-boot-3-spring-security-6-with-kotlin-jwt/ ↩
-
https://stackoverflow.com/questions/75841399/manual-login-authenticationmanager-spring-security-6 ↩
-
https://www.codingshuttle.com/spring-boot-handbook/jwt-creation-and-verification ↩
-
https://www.tothenew.com/blog/migrating-to-spring-security-6/ ↩
-
https://www.netjstech.com/2021/02/spring-boot-spring-security-jwt-authentication.html ↩
-
https://www.reddit.com/r/SpringBoot/comments/1bd5aub/best_approach_to_implement_jwt_with_spring/ ↩
-
https://github.com/spring-projects/spring-security/issues/11926 ↩
-
https://igventurelli.io/javaspring-boottestingunit-testingprogramming/ ↩
-
https://blog.tericcabrel.com/jwt-authentication-springboot-spring-security/ ↩
-
https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/jwt.html ↩
-
https://howtodoinjava.com/spring-security/jwt-auth-vuejs-spring-boot-security/ ↩
-
https://stackoverflow.com/questions/78197265/spring-boot-jwt-signup-login ↩
-
https://docs.spring.io/spring-boot/appendix/application-properties/index.html ↩
-
https://www.reddit.com/r/SpringBoot/comments/zyrna4/how_would_i_configure_spring_security_to_return_a/ ↩
-
https://stackoverflow.com/questions/71683030/how-to-include-jwt-secret-in-application-yaml-for-java-spring ↩
-
https://stackoverflow.com/questions/53809244/difficulty-importing-jwt-json-web-token-in-spring-boot-gradle-project ↩
-
https://ahmadkanaan.hashnode.dev/jwt-authentication-and-authorisation-using-spring-boot-3-and-spring-security-6 ↩