In this tutorial, we’re gonna build a Spring Boot Application that supports Token based Authentication with JWT. You’ll know:
- Appropriate Flow for User Signup & User Login with JWT Authentication
- Spring Boot Application Architecture with Spring Security
- How to configure Spring Security to work with JWT
- How to define Data Models and association for Authentication and Authorization
- Way to use Spring Data JPA to interact with PostgreSQL/MySQL Database
Lots of interesting things ahead, let’s explore together.
– Related Posts:
- Spring Boot Refresh Token with JWT example
- Spring Boot, Spring Data JPA – Building Rest CRUD API example
- Spring Boot File upload example with Multipart File
- @RestControllerAdvice example in Spring Boot
- Spring Boot @ControllerAdvice & @ExceptionHandler example
- @DataJpaTest example for Spring Data Repository Unit Test
- Spring Boot Unit Test for Rest Controller
- Using MongoDB: Spring Boot JWT Auth with MongoDB
- The example that uses HttpOnly Cookies instead.
- Documentation: Spring Boot Swagger 3 example
- Caching: Spring Boot Redis Cache example
- Spring Boot custom Validation example
– Deployment:
Contents
- Overview of Spring Boot JWT Authentication example
- Spring Boot Signup & Login with JWT Authentication Flow
- Spring Boot Server Architecture with Spring Security
- Technology
- Project Structure
- Setup new Spring Boot project
- Configure Spring Datasource, JPA, App properties
- Create the models
- Implement Repositories
- Configure Spring Security
- Implement UserDetails & UserDetailsService
- Filter the Requests
- Create JWT Utility class
- Handle Authentication Exception
- Define payloads for Spring RestController
- Create Spring RestAPIs Controllers
- Run & Test
- Conclusion
- Source Code
- Further Reading
Overview of Spring Boot JWT Authentication example
We will build a Spring Boot application in that:
- User can signup new account, or login with username & password.
- By User’s role (admin, moderator, user), we authorize the User to access resources
These are APIs that we need to provide:
Methods | Urls | Actions |
---|---|---|
POST | /api/auth/signup | signup new account |
POST | /api/auth/signin | login an account |
GET | /api/test/all | retrieve public content |
GET | /api/test/user | access User’s content |
GET | /api/test/mod | access Moderator’s content |
GET | /api/test/admin | access Admin’s content |
The database we will use could be PostgreSQL or MySQL depending on the way we configure project dependency & datasource.
This is our Spring Boot application demo running with MySQL database and test Rest Apis with Postman.
For Fullstack, please visit:
- Spring Boot + Vuejs: JWT Authentication Example
- Spring Boot + Angular 8: JWT Authentication Example
- Spring Boot + Angular 10: JWT Authentication Example
- Spring Boot + Angular 11: JWT Authentication Example
- Spring Boot + Angular 12: JWT Authentication example
- Spring Boot + Angular 13: JWT Authentication example
- Spring Boot + Angular 14: JWT Authentication example
- Spring Boot + Angular 15: JWT Authentication example
- Spring Boot + Angular 16: JWT Authentication example
- Spring Boot + React.js: JWT Authentication example
Spring Boot Signup & Login with JWT Authentication Flow
The diagram shows flow of how we implement User Registration, User Login and Authorization process.
A legal JWT must be added to HTTP Authorization Header if Client accesses protected resources.
You will need to implement Refresh Token:
More details at: Spring Boot Refresh Token with JWT example
You can also visit The example that uses HttpOnly Cookies instead.
Spring Boot Server Architecture with Spring Security
You can have an overview of our Spring Boot Server with the diagram below:
Now I will explain it briefly.
Spring Security
– WebSecurityConfig
is the crux of our security implementation. It configures cors, csrf, session management, rules for protected resources. We can also extend and customize the default configuration that contains the elements below.
(WebSecurityConfigurerAdapter
is deprecated from Spring 2.7.0, you can check the source code for update. More details at:
WebSecurityConfigurerAdapter Deprecated in Spring Boot)
– UserDetailsService
interface has a method to load User by username and returns a UserDetails
object that Spring Security can use for authentication and validation.
– UserDetails
contains necessary information (such as: username, password, authorities) to build an Authentication object.
– UsernamePasswordAuthenticationToken
gets {username, password} from login Request, AuthenticationManager
will use it to authenticate a login account.
– AuthenticationManager
has a DaoAuthenticationProvider
(with help of UserDetailsService
& PasswordEncoder
) to validate UsernamePasswordAuthenticationToken
object. If successful, AuthenticationManager
returns a fully populated Authentication object (including granted authorities).
– OncePerRequestFilter
makes a single execution for each request to our API. It provides a doFilterInternal()
method that we will implement parsing & validating JWT, loading User details (using UserDetailsService
), checking Authorizaion (using UsernamePasswordAuthenticationToken
).
– AuthenticationEntryPoint
will catch authentication error.
Repository contains UserRepository
& RoleRepository
to work with Database, will be imported into Controller.
Controller receives and handles request after it was filtered by OncePerRequestFilter
.
– AuthController
handles signup/login requests
– TestController
has accessing protected resource methods with role based validations.
Understand the architecture deeply and grasp the overview more easier:
Spring Boot Architecture for JWT with Spring Security
Technology
- Java 17 / 11 / 8
- Spring Boot 3 / 2 (with Spring Security, Spring Web, Spring Data JPA)
- jjwt-api 0.11.5
- PostgreSQL/MySQL
- Maven
Project Structure
This is folders & files structure for our Spring Boot application:
security: we configure Spring Security & implement Security Objects here.
WebSecurityConfig
UserDetailsServiceImpl
implementsUserDetailsService
UserDetailsImpl
implementsUserDetails
AuthEntryPointJwt
implementsAuthenticationEntryPoint
AuthTokenFilter
extendsOncePerRequestFilter
JwtUtils
provides methods for generating, parsing, validating JWT
(WebSecurityConfigurerAdapter
is deprecated from Spring 2.7.0, you can check the source code for update. More details at:
WebSecurityConfigurerAdapter Deprecated in Spring Boot)
controllers handle signup/login requests & authorized requests.
AuthController
: @PostMapping(‘/signin’), @PostMapping(‘/signup’)TestController
: @GetMapping(‘/api/test/all’), @GetMapping(‘/api/test/[role]’)
repository has intefaces that extend Spring Data JPA JpaRepository
to interact with Database.
UserRepository
extendsJpaRepository<User, Long>
RoleRepository
extendsJpaRepository<Role, Long>
models defines two main models for Authentication (User
) & Authorization (Role
). They have many-to-many relationship.
User
: id, username, email, password, rolesRole
: id, name
payload defines classes for Request and Response objects
We also have application.properties for configuring Spring Datasource, Spring Data JPA and App properties (such as JWT Secret string or Token expiration time).
Setup new Spring Boot project
Use Spring web tool or your development tool (Spring Tool Suite, Eclipse, Intellij) to create a Spring Boot project.
Then open pom.xml and add these dependencies:
<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-web</artifactId>
</dependency>
<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>
We also need to add one more dependency.
– If you want to use PostgreSQL:
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
– or MySQL is your choice:
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
Configure Spring Datasource, JPA, App properties
Under src/main/resources folder, open application.properties, add some new lines.
For PostgreSQL
spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
spring.datasource.username=postgres
spring.datasource.password=123
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation= true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto=update
# App Properties
bezkoder.app.jwtSecret= ======================BezKoder=Spring===========================
bezkoder.app.jwtExpirationMs=86400000
For MySQL
spring.datasource.url=jdbc:mysql://localhost:3306/testdb?useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto=update
# App Properties
bezkoder.app.jwtSecret= ======================BezKoder=Spring===========================
bezkoder.app.jwtExpirationMs=86400000
Create the models
We’re gonna have 3 tables in database: users, roles and user_roles for many-to-many relationship.
Let’s define these models.
In models package, create 3 files:
– ERole
enum in ERole.java.
In this example, we have 3 roles corresponding to 3 enum.
package com.bezkoder.springjwt.models;
public enum ERole {
ROLE_USER,
ROLE_MODERATOR,
ROLE_ADMIN
}
– Role
model in Role.java
package com.bezkoder.springjwt.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;
public Role() {
}
public Role(ERole name) {
this.name = name;
}
// getters and setters
}
– User
model in User.java.
It has 5 fields: id, username, email, password, roles.
package com.bezkoder.springjwt.models;
import java.util.HashSet;
import java.util.Set;
import jakarta.persistence.*;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
@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<>();
public User() {
}
public User(String username, String email, String password) {
this.username = username;
this.email = email;
this.password = password;
}
// getters and setters
}
Implement Repositories
Now, each model above needs a repository for persisting and accessing data. In repository package, let’s create 2 repositories.
UserRepository
There are 3 necessary methods that JpaRepository
supports.
package com.bezkoder.springjwt.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.bezkoder.springjwt.models.User;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
Boolean existsByUsername(String username);
Boolean existsByEmail(String email);
}
RoleRepository
This repository also extends JpaRepository
and provides a finder method.
package com.bezkoder.springjwt.repository;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.bezkoder.springjwt.models.ERole;
import com.bezkoder.springjwt.models.Role;
@Repository
public interface RoleRepository extends JpaRepository<Role, Long> {
Optional<Role> findByName(ERole name);
}
Configure Spring Security
Without WebSecurityConfigurerAdapter
WebSecurityConfigurerAdapter
is deprecated from Spring 2.7.0. More details at:
WebSecurityConfigurerAdapter Deprecated in Spring Boot.
In security package, create WebSecurityConfig
class.
WebSecurityConfig.java
package com.bezkoder.springjwt.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.bezkoder.springjwt.security.jwt.AuthEntryPointJwt;
import com.bezkoder.springjwt.security.jwt.AuthTokenFilter;
import com.bezkoder.springjwt.security.services.UserDetailsServiceImpl;
@Configuration
@EnableMethodSecurity
// (securedEnabled = true,
// jsr250Enabled = true,
// prePostEnabled = true) // by default
public class WebSecurityConfig { // extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsService;
@Autowired
private AuthEntryPointJwt unauthorizedHandler;
@Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
return new AuthTokenFilter();
}
@Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
return authConfig.getAuthenticationManager();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable())
.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth ->
auth.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/api/test/**").permitAll()
.anyRequest().authenticated()
);
http.authenticationProvider(authenticationProvider());
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
With WebSecurityConfigurerAdapter
In security package, create WebSecurityConfig
class that extends WebSecurityConfigurerAdapter
.
WebSecurityConfig.java
package com.bezkoder.springjwt.security;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.bezkoder.springjwt.security.jwt.AuthEntryPointJwt;
import com.bezkoder.springjwt.security.jwt.AuthTokenFilter;
import com.bezkoder.springjwt.security.services.UserDetailsServiceImpl;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(
// securedEnabled = true,
// jsr250Enabled = true,
prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsService;
@Autowired
private AuthEntryPointJwt unauthorizedHandler;
@Bean
public AuthTokenFilter authenticationJwtTokenFilter() {
return new AuthTokenFilter();
}
@Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/test/**").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
Let me explain the code above.
– @EnableWebSecurity
allows Spring to find and automatically apply the class to the global Web Security.
*For Spring Boot 2: @EnableGlobalMethodSecurity
provides AOP security on methods. It enables @PreAuthorize
, @PostAuthorize
, it also supports JSR-250. You can find more parameters in configuration in Method Security Expressions.
– @EnableGlobalMethodSecurity
is deprecated in Spring Boot 3. You can use @EnableMethodSecurity
instead. For more details, please visit Method Security.
– We override the configure(HttpSecurity http)
method from WebSecurityConfigurerAdapter
interface. It tells Spring Security how we configure CORS and CSRF, when we want to require all users to be authenticated or not, which filter (AuthTokenFilter
) and when we want it to work (filter before UsernamePasswordAuthenticationFilter
), which Exception Handler is chosen (AuthEntryPointJwt
).
– Spring Security will load User details to perform authentication & authorization. So it has UserDetailsService
interface that we need to implement.
– The implementation of UserDetailsService
will be used for configuring DaoAuthenticationProvider
by AuthenticationManagerBuilder.userDetailsService()
method.
– We also need a PasswordEncoder
for the DaoAuthenticationProvider
. If we don’t specify, it will use plain text.
Implement UserDetails & UserDetailsService
If the authentication process is successful, we can get User’s information such as username, password, authorities from an Authentication
object.
Authentication authentication =
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(username, password)
);
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
// userDetails.getUsername()
// userDetails.getPassword()
// userDetails.getAuthorities()
If we want to get more data (id, email…), we can create an implementation of this UserDetails
interface.
security/services/UserDetailsImpl.java
package com.bezkoder.springjwt.security.services;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import com.bezkoder.springjwt.models.User;
import com.fasterxml.jackson.annotation.JsonIgnore;
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
public String getUsername() {
return username;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
UserDetailsImpl user = (UserDetailsImpl) o;
return Objects.equals(id, user.id);
}
}
Look at the code above, you can notice that we convert Set<Role>
into List<GrantedAuthority>
. It is important to work with Spring Security and Authentication
object later.
As I have said before, we need UserDetailsService
for getting UserDetails
object. You can look at UserDetailsService
interface that has only one method:
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
So we implement it and override loadUserByUsername()
method.
security/services/UserDetailsServiceImpl.java
package com.bezkoder.springjwt.security.services;
import org.springframework.beans.factory.annotation.Autowired;
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 org.springframework.transaction.annotation.Transactional;
import com.bezkoder.springjwt.models.User;
import com.bezkoder.springjwt.repository.UserRepository;
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
UserRepository userRepository;
@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));
return UserDetailsImpl.build(user);
}
}
In the code above, we get full custom User object using UserRepository
, then we build a UserDetails
object using static build()
method.
Filter the Requests
Let’s define a filter that executes once per request. So we create AuthTokenFilter
class that extends OncePerRequestFilter
and override doFilterInternal()
method.
security/jwt/AuthTokenFilter.java
package com.bezkoder.springjwt.security.jwt;
import java.io.IOException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import com.bezkoder.springjwt.security.services.UserDetailsServiceImpl;
public class AuthTokenFilter extends OncePerRequestFilter {
@Autowired
private JwtUtils jwtUtils;
@Autowired
private UserDetailsServiceImpl userDetailsService;
private static final Logger logger = LoggerFactory.getLogger(AuthTokenFilter.class);
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
String jwt = parseJwt(request);
if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
String username = jwtUtils.getUserNameFromJwtToken(jwt);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
} catch (Exception e) {
logger.error("Cannot set user authentication: {}", e);
}
filterChain.doFilter(request, response);
}
private String parseJwt(HttpServletRequest request) {
String headerAuth = request.getHeader("Authorization");
if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {
return headerAuth.substring(7);
}
return null;
}
}
What we do inside doFilterInternal()
:
– get JWT
from the Authorization header (by removing Bearer
prefix)
– if the request has JWT
, validate it, parse username
from it
– from username
, get UserDetails
to create an Authentication
object
– set the current UserDetails
in SecurityContext using setAuthentication(authentication)
method.
After this, everytime you want to get UserDetails
, just use SecurityContext
like this:
UserDetails userDetails =
(UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
// userDetails.getUsername()
// userDetails.getPassword()
// userDetails.getAuthorities()
Create JWT Utility class
This class has 3 funtions:
- generate a
JWT
from username, date, expiration, secret - get username from
JWT
- validate a
JWT
security/jwt/JwtUtils.java
package com.bezkoder.springjwt.security.jwt;
import java.security.Key;
import java.util.Date;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import com.bezkoder.springjwt.security.services.UserDetailsImpl;
import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
@Component
public class JwtUtils {
private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);
@Value("${bezkoder.app.jwtSecret}")
private String jwtSecret;
@Value("${bezkoder.app.jwtExpirationMs}")
private int jwtExpirationMs;
public String generateJwtToken(Authentication authentication) {
UserDetailsImpl userPrincipal = (UserDetailsImpl) authentication.getPrincipal();
return Jwts.builder()
.setSubject((userPrincipal.getUsername()))
.setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
.signWith(key(), SignatureAlgorithm.HS256)
.compact();
}
private Key key() {
return Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtSecret));
}
public String getUserNameFromJwtToken(String token) {
return Jwts.parserBuilder().setSigningKey(key()).build()
.parseClaimsJws(token).getBody().getSubject();
}
public boolean validateJwtToken(String authToken) {
try {
Jwts.parserBuilder().setSigningKey(key()).build().parse(authToken);
return true;
} catch (MalformedJwtException e) {
logger.error("Invalid JWT token: {}", e.getMessage());
} catch (ExpiredJwtException e) {
logger.error("JWT token is expired: {}", e.getMessage());
} catch (UnsupportedJwtException e) {
logger.error("JWT token is unsupported: {}", e.getMessage());
} catch (IllegalArgumentException e) {
logger.error("JWT claims string is empty: {}", e.getMessage());
}
return false;
}
}
Remember that we’ve added bezkoder.app.jwtSecret
and bezkoder.app.jwtExpirationMs
properties in application.properties
file, and jwtSecret
has 64 characters.
Handle Authentication Exception
Now we create AuthEntryPointJwt
class that implements AuthenticationEntryPoint
interface. Then we override the commence()
method. This method will be triggerd anytime unauthenticated User requests a secured HTTP resource and an AuthenticationException
is thrown.
security/jwt/AuthEntryPointJwt.java
package com.bezkoder.springjwt.security.jwt;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
@Component
public class AuthEntryPointJwt implements AuthenticationEntryPoint {
private static final Logger logger = LoggerFactory.getLogger(AuthEntryPointJwt.class);
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
logger.error("Unauthorized error: {}", authException.getMessage());
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Error: Unauthorized");
}
}
HttpServletResponse.SC_UNAUTHORIZED
is the 401 Status code. It indicates that the request requires HTTP authentication.
If you want to customize the response data, just use an ObjectMapper
like following code:
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
logger.error("Unauthorized error: {}", authException.getMessage());
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
final Map<String, Object> body = new HashMap<>();
body.put("status", HttpServletResponse.SC_UNAUTHORIZED);
body.put("error", "Unauthorized");
body.put("message", authException.getMessage());
body.put("path", request.getServletPath());
final ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(response.getOutputStream(), body);
}
We’ve already built all things for Spring Security. The next sections of this tutorial will show you how to implement Controllers for our RestAPIs.
Define payloads for Spring RestController
Let me summarize the payloads for our RestAPIs:
– Requests:
- LoginRequest: { username, password }
- SignupRequest: { username, email, password }
– Responses:
- JwtResponse: { token, type, id, username, email, roles }
- MessageResponse: { message }
To keep the tutorial not so long, I don’t show these POJOs here.
You can find details for payload classes in source code of the project on Github.
Create Spring RestAPIs Controllers
Controller for Authentication
This controller provides APIs for register and login actions.
– /api/auth/signup
- check existing
username
/email
- create new
User
(withROLE_USER
if not specifying role) - save
User
to database usingUserRepository
– /api/auth/signin
- authenticate { username, pasword }
- update
SecurityContext
usingAuthentication
object - generate
JWT
- get
UserDetails
fromAuthentication
object - response contains
JWT
andUserDetails
data
controllers/AuthController.java
package com.bezkoder.springjwt.controllers;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.bezkoder.springjwt.models.ERole;
import com.bezkoder.springjwt.models.Role;
import com.bezkoder.springjwt.models.User;
import com.bezkoder.springjwt.payload.request.LoginRequest;
import com.bezkoder.springjwt.payload.request.SignupRequest;
import com.bezkoder.springjwt.payload.response.JwtResponse;
import com.bezkoder.springjwt.payload.response.MessageResponse;
import com.bezkoder.springjwt.repository.RoleRepository;
import com.bezkoder.springjwt.repository.UserRepository;
import com.bezkoder.springjwt.security.jwt.JwtUtils;
import com.bezkoder.springjwt.security.services.UserDetailsImpl;
@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
UserRepository userRepository;
@Autowired
RoleRepository roleRepository;
@Autowired
PasswordEncoder encoder;
@Autowired
JwtUtils jwtUtils;
@PostMapping("/signin")
public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = jwtUtils.generateJwtToken(authentication);
UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
List<String> roles = userDetails.getAuthorities().stream()
.map(item -> item.getAuthority())
.collect(Collectors.toList());
return ResponseEntity.ok(new JwtResponse(jwt,
userDetails.getId(),
userDetails.getUsername(),
userDetails.getEmail(),
roles));
}
@PostMapping("/signup")
public ResponseEntity<?> registerUser(@Valid @RequestBody SignupRequest signUpRequest) {
if (userRepository.existsByUsername(signUpRequest.getUsername())) {
return ResponseEntity
.badRequest()
.body(new MessageResponse("Error: Username is already taken!"));
}
if (userRepository.existsByEmail(signUpRequest.getEmail())) {
return ResponseEntity
.badRequest()
.body(new MessageResponse("Error: Email is already in use!"));
}
// Create new user's account
User user = new User(signUpRequest.getUsername(),
signUpRequest.getEmail(),
encoder.encode(signUpRequest.getPassword()));
Set<String> strRoles = signUpRequest.getRole();
Set<Role> roles = new HashSet<>();
if (strRoles == null) {
Role userRole = roleRepository.findByName(ERole.ROLE_USER)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(userRole);
} else {
strRoles.forEach(role -> {
switch (role) {
case "admin":
Role adminRole = roleRepository.findByName(ERole.ROLE_ADMIN)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(adminRole);
break;
case "mod":
Role modRole = roleRepository.findByName(ERole.ROLE_MODERATOR)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(modRole);
break;
default:
Role userRole = roleRepository.findByName(ERole.ROLE_USER)
.orElseThrow(() -> new RuntimeException("Error: Role is not found."));
roles.add(userRole);
}
});
}
user.setRoles(roles);
userRepository.save(user);
return ResponseEntity.ok(new MessageResponse("User registered successfully!"));
}
}
Controller for testing Authorization
There are 4 APIs:
– /api/test/all
for public access
– /api/test/user
for users has ROLE_USER
or ROLE_MODERATOR
or ROLE_ADMIN
– /api/test/mod
for users has ROLE_MODERATOR
– /api/test/admin
for users has ROLE_ADMIN
Do you remember that we used @EnableGlobalMethodSecurity(prePostEnabled = true)
(or @EnableMethodSecurity
for Spring Boot 3) in WebSecurityConfig
class?
@Configuration
// @EnableWebSecurity
// @EnableGlobalMethodSecurity(prePostEnabled = true)
@EnableMethodSecurity // Spring Boot 3
public class WebSecurityConfig { ... }
Now we can secure methods in our Apis with @PreAuthorize
annotation easily.
controllers/TestController.java
package com.bezkoder.springjwt.controllers;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/api/test")
public class TestController {
@GetMapping("/all")
public String allAccess() {
return "Public Content.";
}
@GetMapping("/user")
@PreAuthorize("hasRole('USER') or hasRole('MODERATOR') or hasRole('ADMIN')")
public String userAccess() {
return "User Content.";
}
@GetMapping("/mod")
@PreAuthorize("hasRole('MODERATOR')")
public String moderatorAccess() {
return "Moderator Board.";
}
@GetMapping("/admin")
@PreAuthorize("hasRole('ADMIN')")
public String adminAccess() {
return "Admin Board.";
}
}
Run & Test
Run Spring Boot application with command: mvn spring-boot:run
Tables that we define in models package will be automatically generated in Database.
If you check MySQL database for example, you can see things like this:
mysql> describe users;
+----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| email | varchar(50) | YES | UNI | NULL | |
| password | varchar(120) | YES | | NULL | |
| username | varchar(20) | YES | UNI | NULL | |
+----------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)
mysql> describe roles;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> describe user_roles;
+---------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+------------+------+-----+---------+-------+
| user_id | bigint(20) | NO | PRI | NULL | |
| role_id | int(11) | NO | PRI | NULL | |
+---------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
We also need to add some rows into roles table before assigning any role to User.
Run following SQL insert statements:
INSERT INTO roles(name) VALUES('ROLE_USER');
INSERT INTO roles(name) VALUES('ROLE_MODERATOR');
INSERT INTO roles(name) VALUES('ROLE_ADMIN');
Then check the tables:
mysql> select * from roles;
+----+----------------+
| id | name |
+----+----------------+
| 1 | ROLE_USER |
| 2 | ROLE_MODERATOR |
| 3 | ROLE_ADMIN |
+----+----------------+
3 rows in set (0.00 sec)
Register some users with /signup
API:
- admin with
ROLE_ADMIN
- mod with
ROLE_MODERATOR
andROLE_USER
- zkoder with
ROLE_USER
Our tables after signup could look like this.
mysql> select * from users;
+----+--------------------+--------------------------------------------------------------+----------+
| id | email | password | username |
+----+--------------------+--------------------------------------------------------------+----------+
| 1 | [email protected] | $2a$10$mR4MU5esBbUd6JWuwWKTA.tRy.jo4d4XRkgnamcOJfw5pJ8Ao/RDS | admin |
| 2 | [email protected] | $2a$10$VcdzH8Q.o4KEo6df.XesdOmXdXQwT5ugNQvu1Pl0390rmfOeA1bhS | mod |
| 3 | [email protected] | $2a$10$c/cAdrKfiLLCDcnXvdI6MumFMthIxVCDcWjp2XcRqkRfdzba5P5.. | user |
+----+--------------------+--------------------------------------------------------------+----------+
3 rows in set (0.00 sec)
mysql> select * from roles;
+----+----------------+
| id | name |
+----+----------------+
| 1 | ROLE_USER |
| 2 | ROLE_MODERATOR |
| 3 | ROLE_ADMIN |
+----+----------------+
3 rows in set (0.00 sec)
mysql> select * from user_roles;
+---------+---------+
| user_id | role_id |
+---------+---------+
| 2 | 1 |
| 3 | 1 |
| 2 | 2 |
| 1 | 3 |
+---------+---------+
4 rows in set (0.00 sec)
Access public resource: GET /api/test/all
Access protected resource: GET /api/test/user
Login an account: POST /api/auth/signin
Access ROLE_USER
resource: GET /api/test/user
Access ROLE_MODERATOR
resource: GET /api/test/mod
Access ROLE_ADMIN
resource: GET /api/test/admin
Solve Problem: javax.validation cannot be resolved
For Spring Boot 2.3 and later, you can see the compile error:
The import javax.validation cannot be resolved
It is because Validation Starter no longer included in web starters. So you need to add the starter yourself.
– For Maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
– For Gradle:
dependencies {
...
implementation 'org.springframework.boot:spring-boot-starter-validation'
}
Solve Problem with JDK 14
If you run this Spring Boot App with JDK 14 and get following error when trying to authenticate:
FilterChain java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
Just add following dependency to pom.xml:
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>2.3.2</version>
</dependency>
Everything’s gonna work fine.
Conclusion
Congratulation!
Today we’ve learned so many interesting things about Spring Security and JWT Token based Authentication in just a Spring Boot example.
Despite we wrote a lot of code, I hope you will understand the overall architecture of the application, and apply it in your project at ease.
For understanding the architecture deeply and grasp the overview more easier:
Spring Boot Architecture for JWT with Spring Security
Validate the signup request (password, confirm password):
Spring Boot custom Validation example
You should continue to know how to implement Refresh Token:
Spring Boot Refresh Token with JWT example
Or visit The example that uses HttpOnly Cookies instead.
You can also know how to deploy Spring Boot App on AWS (for free) with this tutorial.
Happy learning! See you again.
Further Reading
- Spring Security Reference
- In-depth Introduction to JWT-JSON Web Token
- Spring Boot Pagination & Filter example | Spring JPA, Pageable
Related Posts:
- Spring Boot, Spring Data JPA – Building Rest CRUD API example
- CRUD GraphQL APIs example with Spring Boot, MySQL & Spring JPA
- Spring Boot Rest XML example – Web service with XML Response
- Spring Boot File upload example with Multipart File
- @RestControllerAdvice example in Spring Boot
- Spring Boot @ControllerAdvice & @ExceptionHandler example
- @DataJpaTest example for Spring Data Repository Unit Test
- Spring Boot Unit Test for Rest Controller
Deployment:
Fullstack CRUD App:
– Spring Boot + Vue.js example
– Angular 8 + Spring Boot example
– Angular 10 + Spring Boot example
– Angular 11 + Spring Boot example
– Angular 12 + Spring Boot example
– Angular 13 + Spring Boot example
– Angular 14 + Spring Boot example
– Angular 15 + Spring Boot example
– Angular 16 + Spring Boot example
– React + Spring Boot example
If you need a working front-end for this back-end, you can find Client App in the posts:
– Vue.js JWT Authentication with Vuex and Vue Router
– Angular 8 JWT Authentication example with Web Api
– Angular 10 JWT Authentication example with Web Api
– Angular 11 JWT Authentication example with Web Api
– Angular 12 JWT Authentication example with Web Api
– Angular 13 JWT Authentication example with Web Api
– React JWT Authentication (without Redux) example
– React Hooks: JWT Authentication (without Redux) example
– React Redux: JWT Authentication example
Associations:
– JPA One To One example with Hibernate in Spring Boot
– JPA One To Many example with Hibernate and Spring Boot
– JPA Many to Many example with Hibernate in Spring Boot
Documentation: Spring Boot + Swagger 3 example (with OpenAPI 3)
Caching: Spring Boot Redis Cache example
Source Code
You can find the complete source code for this tutorial on Github.
Thanks BezKoder for the tutorial, it was very helpful.
And for every one who has an error with getting some data, getting “Unauthorized” error, just change :
@PreAuthorize(“hasRole(‘Admin’)”)
to :
@PreAuthorize(“hasRole(‘ROLE_ADMIN’)”)
This is how i resolved the issue, and it may depend on how roles are saved in your database 🙂
hi bezkoder i really enjoy your content on spring jwt authentication. bless you bro.
Hi, thanks for this helpful tutorial, my question is about disabling csrf (….csrf().disable ).
By using spring boot security with JWT, do we need to disable csrf? isn’t my application vulnerable to csrf attacks by doing so? If not is it vulnerable to Xss attacks and how can I protect it ?
hello and thx for this tuto.
After signin up and signing in (as admin) i’ve got this token “eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImlhdCI6MTY0NjEzOTg2NywiZXhwIjoxNjQ2MjI2MjY3fQ.Yc14R2gDZWlPQmxmRQ4TnPPJ73eI8pv–QTovuHZVEFf_-otD8Wkeso6OVn6xYm5LgIhiqtNp_RTExCZmCp_UA”
when i tried to access to “localhost:8080/api/test/admin” with value “Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImlhdCI6MTY0NjEzOTg2NywiZXhwIjoxNjQ2MjI2MjY3fQ.Yc14R2gDZWlPQmxmRQ4TnPPJ73eI8pv–QTovuHZVEFf_-otD8Wkeso6OVn6xYm5LgIhiqtNp_RTExCZmCp_UA” i’ve got 403 Forbidden error
Any help please
Hi, you need to add “Bearer [token]” on your HTTP request Authorization header.
(My English is not very well.)
I got the token = “undefined” issue too.
And I compared all the code between my code and this example code.
I found this.
I use lombok in my project.
In the “public class JwtResponse” .
It use different name of the
“private String token;”
but constructor use below:
///
public JwtResponse(String accessToken, Long id, String username, String email, List roles) {
this.token = accessToken;
this.id = id;
this.username = username;
this.email = email;
this.roles = roles;
}
///
I remove the lombok and use the same code with the example.
or I keep my lombok and change my field name form “private String token;” to “private String accessToken;”.
Both can resolve my problem.
Hope it will help.
Hi!
Thank you for your tutorial it helped me a lot!nWould it be possible from your side to guide me with some additional case related to this tutorial? I want to create put request – editing username. I was trying to do something like this:
but i have issues. I added usernameUpdateRequest class and added findById in userrepo. Problem is, that findbyId returns User instead of user and it complicates the whole thing. Best regards!
thank you so much so nicely instructed.
Thank you for great example, but i can’t find, where the configuration for “Forbidden” error handling class?
I have the same question!
Hi, bezkoder, useful tut!
What about adding next entities to this REST API?
For example, adding that https://www.bezkoder.com/spring-boot-file-upload/ to this auth app
1. We should add “token: xxxxxxxxxxxxxx” to request body, and that`s enough?
2. What kind of checking process we should follow for token confirmation in Controller before any endpoint getting handled?
Thanks a lot?
Hi,
I have implemented the above for my project . I need to write test cases but am getting “Error :unauthorised” ,which I think is coming security/jwt/AuthEntryPointJwt.java.
I have annotated other end points with @PreAuthorize(“hasRole(‘XYZ’)”) .
What should I mock to avoid this error ?
Hello Guys, Hope that y’re fine!!
Firstly, I want to inform that my english isn’t good, but Plz I will try to explain my problem like that:
After sigin success, I have this Response
But when I want to access to the mod or user content, I’m not able to see it!!
Response of access:
I also note that on my logger console, i have this message “Unauthorized error: Full authentication is required”
Plz, I have done the tutorial several times, but I don’t see where is the problem
Regards,
Hi, you can check your HTTP
Authorization
Headers with Bearer Token. IT should be:Bearer eyJhbGciOiJ...
Thanks for your answer!
It works now..
where exactly must we see this http authorization header please
Hi I’d like to know where dispatcherservlet fits in in that picture
Hi, very good article.
Can the roles get from database?
@PreAuthorize(“hasRole(‘USER’) or hasRole(‘MODERATOR’) or hasRole(‘ADMIN’)”)
Thank you
what is “Bearer token” in header
when i call “localhost:8080/api/auth/signin” i am getting error;
“timestamp”: “2021-11-15T06:07:11.934+00:00”,
“status”: 500,
“error”: “Internal Server Error”,
“path”: “/api/auth/signin”
AuthTokenFilter->request: org.springframework.security.web.header.HeaderWriterFilter$HeaderWriterRequest@22a6d
AuthTokenFilter->headerAuth: null
AuthTokenFilter->jwt: null
can we use email instead of username to login using current method?
Great tutorial(s)!
Question around best practices. For the signup, could you also return a token or is it better to keep them separate and have the client app (angular in this case) call login after a successful signup?
Thanks!
Hi, thank you for the excelent tutorial!
I have a problem, when i signup/signin with postman all work well, but when i do a GET request api/test/…, I receive UNEXPECTED ERROR, access denied, the error is on the line filterChain.doFilter(request, response); in AuthTokenFilter class, can you help me?
thank you
Hi, you can check the Authorization header with Bearer token.
Thank you.
Thanks for the tutorial. I had no problem at all!!
Hello bezkoder,
Thanks for the tutorial ! I have followed it, and application starts well, test data entered. When I try to sing up, I am getting a 401. Not sure what’s wrong in my request, should be something small, someone reading this could also help to solve the issue, TIA !
URL – http://localhost:8080/api/auth/signup
Req – POST
Payload
{
“username”:”testadmin”,
“email”:”[email protected]”,
“password”:”*****”,
“role”:[“admin”]
}
Hello, please how did you resolve this. Thanks
I have a classCastException when I use the UserDetailsImpl class for sign in request.
It is saying can not cast String to UserDetails interface.
hi i have a problem!
all the requests that I make after my authentication do not go through in fact I do not have access to resources. all my API requests other than those from the Auth package do not pass authorization default.
Hi, check your Authorization Header with Bearer prefix first.
I solved it and to all my fellows peers looking for Full authentication is required to access this resource, i change the url to “/signup”. You have to add this “url” to WebSecurityConfig class as well. Cheers
HI bezkoder ,
Can you please help ? I received : Unauthorized error: Full authentication is required to access this resource for the signup API call to spring boot. This is the first initial sign up call. There should be no token available for the bearer during sign up right? Can please advise please?
.security.AuthEntryPointJwt
Unauthorized error: Full authentication is required to access this resource
Awesome tut. Extremely comprehensive and easy to understand. Thanks!!!
Hello, thank you for your tutorial, it helps me a lot.
I want to ask, why you use Set instead of List for Roles mapping on user object? meanwhile, you convert it to list too…
Thank you so much.
I must have to say that this is a great tutorial and nicely explained.
{
“username”:”user”,
“password”:”%&67#&46″
}
I am sending encoded password how can we decode and validate and successfully login?
Hell, my IDEA ia angry about this: Field Injection is not Recommended
Can i ignore this, or please give example of Constructor injection
@Autowired
UserDetailsServiceImpl userDetailsService;
@Autowired
@rivate AuthEntryPointJwt unauthorizedHandler;
Hey fellow tutorial followers,
I was also encountering this error:
o.s.s.c.bcrypt.BCryptPasswordEncoder : Encoded password does not look like BCrypt
I fixed it by changing the passwordEncoder method in the WebSecurityConfig from this:
to this:
Hope this helps some people.
I am getting this error after changing like you suggested
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id “null”
That is probably because you directly inserted your user data into the database. Therefore, the password is not encrypted. Use the signup API to create your user data.
Hi Bezkoder,
Thank you for you tutorial!
I have an issue when I tried to register a new user into my database after a restart of the application.
On the first launch I registered 3 account : admin, mod and user. Then I restarted the app and i tried to register the user temp wich gived me the following error : “query did not return a unique result: 2; nested exception is javax.persistence.NonUniqueResultException: query did not return a unique result: 2”.
I can’t figure how to solve this problem…
Thank you!
Hi bezkoder, I have implemented the application and everything works fine in oracle DB 12c but there is a problem. I can successfully register user from postman and if I check my DB I can see the data saved including hashed password, when I try to login with the same credentials I get the error below:
o.s.s.c.bcrypt.BCryptPasswordEncoder : Empty encoded password
v.i.crm.security.jwt.AuthEntryPointJwt : Unauthorized error: Bad credentials.
Please help thanks.
Hello, check my most recent comment below!
Hi Bezkoder,
First of all, thank you for you tutorial, it’s very clear !
Do you plan to do a tutorial on the back and/or front side which present how to manage the users table ?
From a production perspective, to my mind, it would complete this series of tutorials (The superuser would be admin which can manage moderators and users)
Thank you!
hello man why are the data not saved on the my db? I use the oracle 19c! after registration, no data is saved
Hi, the source code configuration works with MySQL database, not Oracle. So you need to use Oracle dependency in pom.xml and configure data source and hibernate in application.properties file 🙂
Hello, when I create a constructor in the sign in section return
JwtResponse
, what will the String correspond to jwt?Hello…,
For sign in purpose….,
Instead of UserName can we use email ID for sign in………….
It has been best guide I have ever seen in my entire life! Great staff. Clearly explained.
very Brilliant !!!!!
Hello,
I always get 401 Full Authentication required when trying to get any protected resource. I have the Authorization Header and the Token on all requests, also the aplication-type JSON headers I still always get the error, both from Angular and from Postman.
Please help me I need to implement this for a university project and your tutorial is the best I’ve found, but it just doesn’t work properly
Hi, please make sure that you have
'Bearer '
string as prefix of the token.I have it, still have the same error.
I think it’s a problem with creating the authentication, maybe there’s something that needs to be changed with the security config. The authentication seems to never be created and sending the token does nothing unfortunately.
UPDATE:
I found the problem. For anyone else having this problem:
Make sure you DON’t add @Order(Ordered.HIGHEST_PRECEDENCE) to the security config or any of the jwt classes. I added it to avoid some error from csrf, but it ended up ruining the authentication.
I got that error after sending
{
“username”: “mod”,
“email”: “[email protected]”,
“password”: “12345”,
“role”:[“mod”,”user”]
}
to POST http://localhost:8080/api/auth/signup by Postman
and im getting this kind of error
{
“timestamp”: “2021-04-19T08:47:32.067+00:00”,
“status”: 415,
“error”: “Unsupported Media Type”,
“message”: “”,
“path”: “/api/auth/signup”
}
Hi, you should set
Content-Type: application/json
in your HTTP request Header.Hi M8!
Great tutorial!
just one thing my spring runs fine and finds my database and all.
It just does not add any tables to it at all.
Any idea why?
I get no error messages.
Kind regards
You should set hibernate ddl to create, or update. See the code below
spring.jpa.hibernate.ddl-auto = update
Hi man thanks , it was realy a nice tutorial ,but i need help i tested the /signup post request it did worked and i checked my data Base it was implemented with a user but when i try /signin with the same user that i just did i got {
“timestamp”: “2021-04-17T05:12:02.331+00:00”,
“status”: 401,
“error”: “Unauthorized”,
“message”: “”,
“path”: “/pcd/auth/signin”
}
ps: i changed the path to (“/pcd/auth/**”).permitAll() in the webConfig the Jwt token is not generating its directly rendering into Authentication Entry point and displaying the message pleaase help
hi i resolved it thanks :DDD
Hello, please how did you resolve this. Thanks
Hello, please how did you resolve this. Thanks
Howdy! This post could not be written mᥙch better!
Reading through this tutorial helps me alot about Spring Security with JWT!
Thanks f᧐r sharing!
I did everything the same but I get this error when I try to login
2021-04-13 14:56:47.174 WARN 105872 — [nio-8080-exec-2] o.s.s.c.bcrypt.BCryptPasswordEncoder : Encoded password does not look like BCrypt
2021-04-13 14:56:47.187 ERROR 105872 — [nio-8080-exec-2] c.a.A.security.jwt.AuthEntryPointJwt : Unauthorized error: Bad credentials
Hi Sir,
I am getting below issue while signup user:
{
“timestamp”: “2021-04-13T08:33:24.035+00:00”,
“status”: 401,
“error”: “Unauthorized”,
“path”: “/app/auth/signup”
}
can you please help…
My user not have enabled column and when i try to login, server said that can not authorization cause no enabled column, so how to get over it
Hello, I have a questioned why you picked relatively old lib jjwt from Jul, 2018 ?
Any reason behind that?
I see as I assume continuation of this lib but nobody uses it: https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-root
Any thoughts?
Hi! Thanks for this awesome tutorial!
I have an issue with the http://localhost:8080/api/auth/signin. I have created the roles in the role table and I was able to create some users from http://localhost:8080/api/auth/signup. The problem comes when I want to sign in.
I create an user with the following parameter -> {“username”: “admin”, “email”: “[email protected]”, “password”: “admin”, “role”: [“admin”, “mod, “user”]} and then when I tried to sigin with “username”: “admin” and “password”: “admin” I have a 415 Unsoported Media Type.
I’m sure I am using the POST method, and I tried to change from application/json to application/x-www-form-urlencoded with no success.
If you can help me I will be very thankful!
Thanks anyway for this great tutorial. Your GitHub was very helpful
Thank you so much. I have got so much to learn.
Hi.
I’m having this issue like when I try to fetch details roles are not coming. I’m getting an empty array. kindly help if someone knows how to resolve this issue.
Thanks in advance
Hi, you should use SQL to create 3 records in
roles
table first.Resolved [org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation]
Hallo Bezkoder …
It greats tutorial, thanks a lot for your sharing.
I have a silly questions but it make me confuse. User have 1 role, Moderator have 2 roles , and Admin have only 1 roles. Where I must set it? How do I set Admin with 3 roles ?
Thank you in advance
hello , thank you for these great tutorial .
I changed in application.properties file :
spring.datasource.url=jdbc:mysql://localhost:3306/testdb?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name= com.mysql.cj.jdbc.Driver
spring.jpa.database= MYSQL
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL55Dialect
spring.jpa.open-in-view=false
# App Properties
bezkoder.app.jwtSecret= bezKoderSecretKey
bezkoder.app.jwtExpirationMs= 86400000
so the tables were generated automaticly and i can open my database with phpMyAdmin ,but when i tried to send this request http://localhost:8080/api/auth/signup in Postman, i have this error :
POST http://localhost:8080/api/auth/signup
Error: connect ECONNREFUSED 127.0.0.1:8080
Request Headers
Content-Type: application/json
User-Agent: PostmanRuntime/7.26.8
Accept: */*
Cache-Control: no-cache
Postman-Token: bd8240e4-e192-41bb-9b10-477b324d7e0e
Host: localhost:8080
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Request Body
{
“username”: “mod”,
“email”: “[email protected]”,
“password” :”1234″,
“role”: [“mod”, “user”]
}
can you help me please ?
Great tutorial, thanks so much!
Wondering what’s the difference between the following types of exports:
export default new AuthService() vs export default App?
what about payload package. i am beginer and dont know what will request and what response. please provide me
Hi, just think payload as the content (or data) of http request/response 🙂
Signup: http://localhost:8080/signup
body:- {
“username”: “kapil”,
“email”: “[email protected]”,
“password”: “12345”,
“role”: [
“ROLE_ADMIN”
]
}
Response:-
{
“timestamp”: “2021-01-30T21:15:37.537+00:00”,
“status”: 401,
“error”: “Unauthorized”,
“message”: “Error: Unauthorized”,
“path”: “/signup”
}
Hi, it should be:
"role" : ["admin"]
🙂Hi, I have the following error when trying POST signup request:
2021-01-24 16:32:42.688 ERROR 1136 — [nio-9095-exec-9] c.e.s.security.jwt.AuthEntryPointJwt : Unauthorized error: Full authentication is required to access this resource
2021-01-24 16:33:24.495 ERROR 1136 — [nio-9095-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
org.springframework.security.web.firewall.RequestRejectedException: The request was rejected because the URL contained a potentially malicious String “//”
at org.springframework.security.web.firewall.StrictHttpFirewall.rejectedBlocklistedUrls(StrictHttpFirewall.java:456) ~[spring-security-web-5.4.2.jar:5.4.2]
at org.springframework.security.web.firewall.StrictHttpFirewall.getFirewalledRequest(StrictHttpFirewall.java:429) ~[spring-security-web-5.4.2.jar:5.4.2]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:196) ~[spring-security-web-5.4.2.jar:5.4.2]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:183) ~[spring-security-web-5.4.2.jar:5.4.2]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358) ~[spring-web-5.3.3.jar:5.3.3]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271) ~[spring-web-5.3.3.jar:5.3.3]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.3.jar:5.3.3]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.3.jar:5.3.3]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.3.jar:5.3.3] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.3.3.jar:5.3.3]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:888) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1597) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) ~[na:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
2021-01-24 16:33:24.547 ERROR 1136 — [nio-9095-exec-2] c.e.s.security.jwt.AuthEntryPointJwt : Unauthorized error: Full authentication is required to access this resource
Would you please tell me what am I missing?
Thanks!
No worry, I figure it out. The issue is I am having // (instead of /) from my Post end-point url. After correcting, everything is working.
This was Very Helpful! Thank You So Much!!!!
Thanks a lot for the detailed explanation.
Please if I want to use this as an auth server micro service, how do I go about that? Thanks
Jսst desire to say your Spring Boot tutorial is amazing!
Thank you for this tutorial. It was really easy to understand it.
Can you upload a video or code on forgetting password in this code?
Hi, This tutorial was very helpful to me. Thank you!
Hi, I am wondering why your signin response is different compared mine, here is my signin response result:
My type is always returns null “type”: null, (where did you define tokenType and accessToken? )
Hi, you can find
type = "Bearer"
inpayload/response/JwtResponse.java
:good evening, i did exactly the same as you but when i run my application i get the following error:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093)
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
2020-12-28 20:20:04.631 WARN 44708 — [ main] o.a.c.loader.WebappClassLoaderBase : The web application [ROOT] appears to have started a thread named [HikariPool-1 connection adder] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467)
java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1066)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
java.lang.Thread.run(Thread.java:745)
2020-12-28 20:20:04.633 WARN 44708 — [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization – cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
2020-12-28 20:20:04.634 INFO 44708 — [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 – Shutdown initiated…
2020-12-28 20:20:04.642 INFO 44708 — [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 – Shutdown completed.
2020-12-28 20:20:04.666 INFO 44708 — [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with ‘debug’ enabled.
2020-12-28 20:20:04.694 ERROR 44708 — [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
An attempt was made to call a method that does not exist. The attempt was made from the following location:
org.hibernate.validator.internal.engine.ValidatorFactoryImpl.(ValidatorFactoryImpl.java:153)
The following method did not exist:
javax.validation.spi.ConfigurationState.getParameterNameProvider()Ljavax/validation/ParameterNameProvider;
The method’s class, javax.validation.spi.ConfigurationState, is available from the following locations:
jar:file:/C:/Users/hp/.m2/repository/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar!/javax/validation/spi/ConfigurationState.class
jar:file:/C:/Users/hp/.m2/repository/jakarta/validation/jakarta.validation-api/2.0.2/jakarta.validation-api-2.0.2.jar!/javax/validation/spi/ConfigurationState.class
The class hierarchy was loaded from the following locations:
javax.validation.spi.ConfigurationState: file:/C:/Users/hp/.m2/repository/javax/validation/validation-api/1.0.0.GA/validation-api-1.0.0.GA.jar
Action:
Correct the classpath of your application so that it contains a single, compatible version of javax.validation.spi.ConfigurationState
can someone help me please ?
Hi, first remove in your repository maven the directory hibernate and then make a
maven clean install
to reimport correctly your dependencies.You can’t even imagine how grateful I am to you! Great tutorial!
I’m thoroughly enjoying your tutorial. I’m still new to the whole thing about Spring Boot and you made my day.
Thanks a lot!
Thanks for this amazing tutorial. It was really easy to understand it.
I have a question, If I have a case that some users (from the database) require password from the database or some user required password from Ldap. Can you give me a hint?
Thank you for this excellent tutorial! I was getting lost with other more complex tutorials and having trouble understanding how everything connected, but when I followed this one my authentication worked.
Hi, Aliza, did you tested
http://localhost:8080/api/auth/signup
with
{
“username”: “mod”,
“email”: “[email protected]”,
“password”: “12345678”,
“role”: [“mod”, “user”]
}
with postman I am getting 401 unautorized, this happend to you ?
Hi, thank you for the very detailed tutorial!
Have a question:
Why you user ‘parseClaimsJws’ in function validateJwtToken of JwtUtils class
instead of ‘parseClaimsJwt’?
Hi, I followed the tutorial, it runs but the tables are not being created.
I already tested the connection to postgres, checkt in the browser for the login. Everithing looks good but the tables are not being created, I changed the spring.jpa.hibernate.ddl-auto to create but still nothing.
I apreciate any guidance, thanks.
Hi,
I cloned your code and the frontend too
it works fine
I added a user made him an admin and mod and user
and was added successfully but when I sign in and click on user or admin board they both say UNAUTHORIZED
although im signed in
why is that?
Hi, please make sure that you used Bearer token on Authorization header.
Hello BezKoder, how can i update (put) user_role table in postman?
hello bezcoder ,thank you for this amazing tutorial !! but if i want to add new class (Employee) and make this class as a User .. what i have to do ..should i use inheritance or relationship between them ?
Looks like to fix the issue I posted previously:
Description: A component required a bean named ‘entityManagerFactory’ that could not be found. Action: Consider defining a bean named ‘entityManagerFactory’ in your configuration. [INFO]
I needed to delete the org.hibernate directory from my local maven repository (.m2)
https://stackoverflow.com/questions/54825926/spring-boot-2-1-entitymanagerfactory-bean-could-not-be-found
I’m getting the following error when running mvn spring-boot:run -debug
WARN 8120 — [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization – cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘userReposi tory’ defined in com.bezkoder.springjwt.repository.UserRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Cannot create inner bean ‘(inner bean)#6b2e46af’ of type [org.springframework.orm.jpa.SharedEntityManagerCr eator] while setting bean property ‘entityManager’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creat ing bean with name ‘(inner bean)#6b2e46af’: Cannot resolve reference to bean ‘entityManagerFactory’ while setting constructor argument; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named ‘entityManagerFactory’ available
2020-11-26 07:14:03.393 INFO 8120 — [ main] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService ‘applicationTaskExecutor’
2020-11-26 07:14:03.527 INFO 8120 — [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
2020-11-26 07:14:03.580 INFO 8120 — [ main] ConditionEvaluationReportLoggingListener :
Error starting ApplicationContext. To display the conditions report re-run your application with ‘debug’ enabled.
2020-11-26 07:14:03.595 ERROR 8120 — [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
A component required a bean named ‘entityManagerFactory’ that could not be found.
Action:
Consider defining a bean named ‘entityManagerFactory’ in your configuration.
[INFO] ————————————————————————
[INFO] BUILD FAILURE
Hi, first of all I would like to say its great article, thank you for your effort.
I have one question: how to change login field to another field from User entity? E.g. I want to use email and password for login. How to force UsernamePasswordAuthenticationToken to get as principal email instead of username ?
Hi, I have registered a new user with role “mod”. When I sign in with it and calling a GET http://localhost:8080/api/test/mod URL, I am getting an error in “postman”
{
“timestamp”: “2020-11-23T17:58:29.065+0000”,
“status”: 401,
“error”: “Unauthorized”,
“message”: “Error: Unauthorized”,
“path”: “/api/test/mod”
}
Can you help me? I have taken this tutorial with git clone and I was doing everything step by step. Some people got into the same trouble above in comments but didn’t get the answer.
Also, thanks for this tutorial. 10/10!
Hi, first you need to signin the user. Then you must use Bearer Token from the response data of the signin resquest 🙂
Hi Bezkoder,
So that means that I need to login, but because there is no usere created yet, I need to create the first one to login and to be able to get a token ?
If I do that, by curl it would be something like this ? (I think the confussion is because following the tutorial some of us assume that we can use the signup with no need for credentials…that make sence?, thank you.)
TOKEN=$(curl -s -X POST -H ‘Accept: application/json’ -H ‘Content-Type: application/json’ –data ‘{“username”:”{username}”,”password”:”{password}”,”rememberMe”:false}’ https://{hostname}/api/authenticate | jq -r ‘.id_token’)
curl -H ‘Accept: application/json’ -H “Authorization: Bearer ${TOKEN}” -d ‘name=the_name’ -d ’em[email protected]’https://{hostname}/api/myresource
Hello, thank you for your great tutorial.
I have one question. This part of code shouldn’t return error code when validation is false?
This code does nothing even if validation fails.
Hi, you can look at the next line after this block of code:
filterChain.doFilter(request, response);
Spring Security filter chain will validate and return error code automatically.
Hello bezkoder, i dont want signup page only i need is signin page so what should i change ithe source code
Hola bezcoder , amazing tutorial. Applying your tutorial i did try to implement the process in my app , but keep, but trying to access the user data i got a anonymous user, thus i dont know what to do!
Any sugerence?
Hi, if you use Postman for HTTP Client, make sure that it sent data in Application/JSON.
the point is the user get logged and all works fine .. if i check my login method service implementation all data is there .
When the user logs in the app works .
But when trying to access that logged user from other method in other class through SecurityContextHolder i got an anonymous user
Please help….a better idea i set here:
https://stackoverflow.com/questions/64927997/how-to-receive-the-authenticated-user-from-springsecurity-in-other-service-imple
Thanks in advance
And by the way really thanks for your tutorials.Amazing !!!!!
Man you are those people with god level explanation, I was struggling with implementation in React at the auth states, i love you.
With this guide, there is no need of CSRF protection?
I suggest you all noobs to avoid ask low level questions since this man did not develop a low level API, just learn by yourselves all low level questions could be solved by google, trust me
I am sure that this quite polite gentleman developer want to help all of us, but it is annoying explaining all questions, he did a lot just sharing his code <3
I do have same questions. Do I need to have CSRF protection enabled? Any additional checks required for CSRF?
Hi,
I’m a beginner on spring security and JWT. I am so glad that I found your tutorial and I am following it now. It’s really well explained with great structure. However, I am having a small problem with the post method for /signup.
When I ran the application in local and made a post request on endpoint /api/auth/signup, it returned a successful message. But when I checked the database, it shows empty cells on other columns of the table users apart from the id column.
id | email | password | username
—-+——-+———-+———-
6 | | |
7 | | |
(2 rows)
Do you think what could be the possible causes for this problem?
Many thanks in advance.
Hi, you can check the body data with JSON format is correct or not.
Here is a sample of my body data with JSON format. Should be fine I think ?
{
“username”: “eduard”,
“email”: “[email protected]”,
“password”: “12356547567”,
“role”: [“user”, “mod”]
}
Excellent guide! Bravo!
I have got the problem at the signup. All things seems good but not working. Please help.
{
“timestamp”: “2020-11-05T06:04:19.643+00:00”,
“status”: 404,
“error”: “Not Found”,
“message”: “No message available”,
“path”: “/api/auth/signup”
}
Doing silly mistake that i cannot keep @RequestMapping(“/api/auth”).
Thank you for the great tutorial.
Hi bezkoder !
Thanks a lot for this very good tutorial ! I am a beginner and this helped me a lot !
Now, I would like to add swagger-ui to my project and I have this error when I want to access to url localhost:8080/swagger-ui.html :
c.m.d.a.m.s.jwt.AuthEntryPointJwt : Unauthorized error: Full authentication is required to access this resource
I tried to add .antMatchers(“/swagger-ui.html”).permitAll() to WebSecurityConfig but it’s the same… I know it’s outside of this tutorial but maybe you can help me and tell me what do I need to edit to make it work ?
Thanks !
Hi ,very good tutorial! But i’m having trouble when I call “signup”. Inside “doFilterInternal”, after verify if “jwt != null && jwtUtils.validateJwtToken(jwt)”, this line is called: “filterChain.doFilter(request, response)” and bring me back an Unauthorized error.
I don’t understand what exactly do this line, can any one help me?
I think is important to say that I’m not passing any value on my header(besides the postman defaults). I see in the example above that the header has 9 fields, but mine has 8. Do I need to send something in my header when I’m siningUp?
here I have a better error description:InsuficientAuthenticationException, messageDetails:”Full authentication is required to access this resource”
Hello there,
First of all thank you so much for your tutorial, it is very clear and it helped me a lot !
The only question that remains for me is where are stored the tokens in this configuration ? Are they stored inMemory and if so, how could we change this aspect of your code ?
+1
Does someone has the answer to that question ? I am trying to had an api logout
Wonderful tutorial indeed
Thank you
Hello, thank you very much for sharing, excellent tutorial.
I did my project guiding me around here and it works fine for me except when I use the @PreAuthorize notation, it throws me the error:
Postman
{
“date”: “2020-10-21T18:22:06.284+0000”,
“code”: 500,
“message”: “Internal server error”,
“description”: “Access is denied”,
“details”: []
}
Console
2020-10-21 15:22:06.273 WARN 19507 — [nio-9091-exec-9] n.u.e.r.AEresponseEntityExceptionHandler : Exception.class -> (uri=/api/v1/users/4): Access is denied.
2020-10-21 15:22:06.372 WARN 19507 — [nio-9091-exec-9] .m.m.a.ExceptionHandlerExceptionResolver : Resolved [org.springframework.security.access.AccessDeniedException: Access is denied]
Any ideas? Thanks
Hi, it didn’t work for me with @PreAuthorize (“hasRole (‘ADMIN’)”) but it work for me with @PreAuthorize (“hasAuthority (‘ADMIN’)”)
Would you mind showing your @PreAuthorize code?
Hello, thanks for this tutorial it was very helpful !
but i wanted to do a Reset password with sending email using ur code but i had many problems
Can u take a look thanks
https://stackoverflow.com/questions/64403483/how-can-i-change-modelandview-to-responseentity-in-controller-spring-security
When i invoke the api(protected by jwt) through browser can i have a login form if yes please help on how?
If Admin has to access database, should I create in TestController several ‘access’ methods?
For example, if Admin has to access users and orders, should I create GetMapping for users and GetMapping for orders by two different methods? Thank you.
Hi, thanks for this tutorial.
I’m in trouble, java throws an exception of 401:
08:41:37,931 ERROR [co.com.activacredito.AuthEntryPointJwt] (default task-2) Unauthorized error: Bad credentials
I’m working with a simple login form with Thymeleaf and Spring Boot
What could it be?
Thank you!
Hi, please check if the HTTP request header has the correct Bearer Token.
Hello. Why I can’t reach localhost:8080/register nor any other link? It says: log shows: “Unauthorized error: Full authentication is required to access this resource”. Hope you could help me. Thanks.
Hi, you should check if http header is correct or not (Bearer for Spring Server and x-access-token for Node.js server)
Hi,
Excellent tutorial, easy to understand the concept.
I tried to implement the same, except that I do not want the signup page/utility. i.e. assume the user table will be populated bu some other means. So I implemented everything as the tutorial except signup utility. When I try to login (signin) it fails even though record is fetched correctly.
2020-10-05 15:51:54.346 INFO 17544 — [nio-8071-exec-3] com.example.controller.AuthController : Login….
2020-10-05 15:51:54.346 INFO 17544 — [nio-8071-exec-3] com.example.controller.AuthController : User: mihir
..hibernate logs from user table fetched the row correctly.
..hibernate logs from role table to get the role correctly.
2020-10-05 15:51:54.750 WARN 17544 — [nio-8071-exec-3] o.s.s.c.bcrypt.BCryptPasswordEncoder : Encoded password does not look like BCrypt
2020-10-05 15:51:54.759 ERROR 17544 — [nio-8071-exec-3] c.b.iris.security.jwt.AuthEntryPointJwt : Unauthorized error: Bad credentials
Basically, I have simple text put it DB table for password column.
In Postman the body is as below:
{
“username”: “mihir”,
“password”: “test”
}
“test” is also saved (and returned in logs) from database.
What am I missing here?
Excellent tutorial!
***************************
APPLICATION FAILED TO START
***************************
Description:
Field userRepository in com.bezkoder.springjwt.security.services.UserDetailsServiceImpl required a bean of type ‘com.bezkoder.springjwt.repository.UserRepository’ that could not be found.
The injection point has the following annotations:
– @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type ‘com.bezkoder.springjwt.repository.UserRepository’ in your configuration.
Hi,
private String parseJwt(HttpServletRequest request) {
String headerAuth = request.getHeader(“Authorization”);
System.out.println(request.getHeaderNames());
if (StringUtils.hasText(headerAuth) && headerAuth.startsWith(“Bearer “)) {
return headerAuth.substring(7, headerAuth.length());
}
logger.error(“Something went wrong! headerAuth = null: “, headerAuth);
return null;
headerAuth is null, that is my problem.. Any idea?
Hi bezkoker
yeah, i got it, thanks for your reply, wish you all the best and success
hi bezkoder
– this is great tutorial, it’s worked for me,. But can i ask:
+ Why do you have to create and use “SignupRequest” and “LoginRequest” for Signing Up and Login request, is it OK if use User entity for this purpose?
Many thanks for your help!
Hi, User entity is highly related to database model, while “SignupRequest” and “LoginRequest” stand for Http request data. That means, you can add or change data of the request body by changing “SignupRequest” and “LoginRequest” class, but the persistence of table in database (corresponding to User entity) should not be changed regularly.
Unauthorized error: Full authentication is required to access this resource . I got this error when try to accès to
this url : http://localhost:8080/api/test/user
Hi, please check the HTTP request Authorization Header. Also don’t forget to login a user account to get the Token.
Hi, did you succeed?
Hi, Thank you a lot for this tutorial. But I have a problems when I run your project and it still ok. But I found on my eclipse log that:
io.jsonwebtoken.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.
It has this error. Can you help me fix this
the actual JWT implementation code, thanks a lot.
Hi Bezkoder, Your codes really helped me alot .It is such a awesome code. I just loved it.
It was working fine earlier but recently i got this error while trying to login and i am stuck for a while :
“The signing key’s size is 104 bits which is not secure enough for the HS512 algorithm. The JWT JWA Specification (RFC 7518, Section 3.2) states that keys used with HS512 MUST have a size >= 512 bits (the key size must be greater than or equal to the hash output size). Consider using the io.jsonwebtoken.security.Keys class’s ‘secretKeyFor(SignatureAlgorithm.HS512)’ method to create a key guaranteed to be secure enough for HS512. See https://tools.ietf.org/html/rfc7518#section-3.2 for more information.”
What may be the solution for this? Please help!
The secret key i was giving was short length , i changed the secret key and it worked.Thanks!!!!!
Good Morning
The tutorial is very cool, but I have a problem registering
Give me error 500
I downloaded your code, changed the database and still give me the same error
follow a code
I hope I can help
http://localhost:8080/api/auth/signup
{
“username”:”mod”,
“email”:”[email protected]”,
“password”:”123456789″,
“role”:[“mod”,”user”]
}
{
“timestamp”: “2020-09-04T10:20:52.561+0000”,
“status”: 500,
“error”: “Internal Server Error”,
“message”: “Error: Role is not found.”,
“path”: “/api/auth/signup”
}
Hi, you should insert 3 rows into roles table first.
thanks
Thank you for your tutorial, bez.
Such Helpful article explained very well and it is saying “it took lot of effort to make it understandable” .
I’ve given time to understand article and able to relate the terminologies regarding spring security – authentication, authorization, principal and grant authorities. also leveraged jwt token-based-authentication mechanism with difference of session-based authentication.
After that i able to create custom project with no difficulties and that because of this article reference.
Thank You
God Bless bezkoder 🙂
Hi, thank you for your comment. I am so happy to know that my effort helps you! 🙂
There is a problem in many to many part.
Values cannot be inserted to USER_ROLES table.
How can I fix it?
Hi, you can drop all the tables and follow step by step in the video demo from the beginning:
https://youtu.be/o8DEk4XGcZw
It’s an amazing tutorial for me. I wanted to try it but there is a problem.
In signup method of AuthController, roles cannot be defined. It assigns a message “Error: Role is not found.”
Here is my ROLES_JWT Table
ID ROLE
1 ROLE_USER
2 ROLE_ADMIN
3 ROLE_MODERATOR
When I wrote a json object for signing up, it throws 505 internal error message because of this reason.
{
“username” : “user1”,
“password” : “user123456789”,
“email” : “[email protected]”,
“role” : [“user”,”mod”]
}
Where is the problem ? How can I fix it?
I use Oracle 11g Database
I hope you can reply my question
Thank you
Hi, you can follow the step in video demo:
https://youtu.be/o8DEk4XGcZw
Although I added 3 rows (ROLE_USER,ROLE_MODERATOR and ROLE_ADMIN) in roles table , it still throws an error . (java.lang.RuntimeException: Error: Role is not found.). I use Oracle Database
any help ?
Hi bezkoder,
Thanks for tutorial , I am able to call all APIs through Postman, But in browser i am unable to access this application. I am getting below error page. i used the # App Properties
bezkoder.app.jwtSecret= bezKoderSecretKey
bezkoder.app.jwtExpirationMs= 86400000
Can you please help on this. did i missed any thing.
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sat Aug 15 23:40:56 IST 2020
There was an unexpected error (type=Method Not Allowed, status=405).
Request method ‘GET’ not supported
Amazing tutorial bezkoder! My only issue is the fact that it appears too low in Google Search.
I tried DZone’s tutorial for Bootiful App but yours is much more understandable and well-written.
Thanks for the effort!
Thank you, I’m so happy to know that my work helps other people like you 🙂
public class AuthTokenFilter extends OncePerRequestFilter {
// …
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// …
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// …
}
Well, it will hit the database everytime when a request comes in, basically every click on the UI, every incoming api call, etc triggers a select query against the DB in order to fetch the user data again and again and again…
I know, I know security is important, but don’t you think it is a little resource consuming way to maintain security? I imagine, the user logs in, the backend checks that everything is OK, returns the token, and that’s it. No more DB harassment for finding out that the user and its roles are still existing and intact… in the same session… in every couple of seconds. If the user holds the token (and it is not expired) the backend should accept that tokenas a valid one – without checking the user data in the db.
What are the good ways to keep it still secured but skip the unnecessary resource consuming calls?
Storing the Authentication object in the session? Why not? Spring must have some tools to manage this.
Storing every user detail (password included) in the encoded jwt? Ok, it seems not so secure. 🙂
AuthProvider with caching functionality? And with cache invalidation ofc.
Other solutions?
Cheers!
I have the same question. It seems to me that the logic behind JWT would be to store the user authorisation in the token (hence the name “claims”). They are as secure (or as insecure) as the token itself. Obviously,
it makes changing user rights somehow difficult, but you could use the expiration date to set a limit.
Dude, great tutorial.. I’ve tested it out and worked perfectly on postman… However, if I create an account using the interface on the browser and I log in with user role, when I try accessing “User content” it shows me an error message with “Unauthorized”, even though I’m logged in with user role… Same it is for mod/admin. Any idea what that might be? Thanks!
hey , great job but am sorry where did you specify the roles that can access a specific url for exp (the user can access the /user and cannot access the /admin )
How to test such a configuration, namely the controller methods from @PreAuthorize ?
I got this error: ‘Can’t find the request for http://localhost:9000/api/auth/signup's Observer’ when attempting to signup a new user. This error is thrown inside doFilter method in SecurityContextHolderAwareRequestFilter class
Thanks in advance
Hello!!Very nice tutorial you open my mind!!
I have 1 question for you if i want to add more than one restcontroller just to get some data from database , i added @PreAuthorize annotation and configured security config properly but i am getting 401 error???
My question is do i need every time that i make a post request to sent header so i can get authorized ??? or when i log in automaticly from sesion storage server knows that i am authenticated…????
Thank you… great help me.. now…. thank you
Hi Thanks for this tutorial, I have just one easy query on how to get current user object here in backend
Hello,
thanks for your tutorial. I have a question: why does the statement “filterChain.doFilter(httpServletRequest, httpServletResponse)” call the authentication process again? Actually, in the method “doFilterInternal”, it has already authenticated the token.
In my log, there are SQL of authentication process called twice, so I debug the programme, and find the doFilter method call the UserDetailsImpl once again. How do I avoid this? or is it normal?
I hope my question is clear.
thanks
ps: my log like this:
Hibernate: select * from user where username=?
Hibernate: select * from user where username=?
Hello,
for logout it is really usefull to create it or just remove cookies from front is enough ?
because i did not see a great implementation of logout….
is there ip verification in your code (i dit not analyzed all code)
thank you!
Hi,
Can i use h2 database for this?
If it’s possible, can someone tell me what do i need to change for h2?
I tried to change it but i can’t open h2 and insert roles.
you just have to change the driver in pom.xml and in application.properties, then change jdbc url in application properties
IT workkkks !! Thank U so Much !!
Great tutorial, just having issue with one bit…AuthEntryPointJwt class.
I’m building a multi-module project using Gradle. When I build the application and attempt to run it it fails saying “WebSecurity required a bean of type “AuthEntryPointJwt” that could not be found.”
Wondering if you had seen such an issue before?
Works perfectly, Thank you! That was one of the best tutorials I have seen about this subject
Hi thank you for your post, it really helps me.
I’m stuck at creating a new user, The user table is created but user_role is null.
Can you help me with it?
Thank a lot man. That’s the cleanest example.
Hi, thank you for this great tutorial;
I have one question about UsernamePasswordAuthenticationFilter, Do we only use it in the http.addFilterBefore()
I thought that we will use it for each request (Endpoint of the Test Controller for exampl).
Thank you so much.
Hello and thank you for this great tutorial!
I tried to get it running with openjdk 14 and get following error when trying to authenticate:
FilterChain java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverter
Could found help here:
https://stackoverflow.com/questions/43574426/how-to-resolve-java-lang-noclassdeffounderror-javax-xml-bind-jaxbexception-in-j
So by adding following dependency to pom.xml:
jakarta.xml.bind
jakarta.xml.bind-api
2.3.2
everything works fine.
Thank you so much, I will update the tutorial 🙂
Hi,
when i try to run the app i get this error Consider defining a bean of type ‘org.springframework.security.authentication.AuthenticationManager’ in your configuration.
This happens in authController
I know you defined a bean and wired it in the controller, but i dont get it.
Can you explain please?
Hi,
I want to host some static content from the application build, but i am not able to allow publicly accessible content from static directory.
can you suggest something.
Thanks
pavan
Thank you so much, have been trying to create tokens for so long.
What can be the reason why I’m not receiving ANY response from server?
I’ve made everything as in tutorial step by step…It’s very weird.
Hello, I have the same problem that you, ¿you got any solution for that?
Hey again,
I want to sign up and sign in using also the email address. Any help please?
(Spring boot / Angular)
Sir How To Add The Data i DataBase using Postman Will You Please Explain The Example
one of the best tutorials i’ve ever seen!
especially according to spring security
its very useful this code…thanks you so much
Hi, I’ve downloaded this repo from github and upgraded it to use spring boot 2.3.0 but now whenever i try to login using wrong credentials the message property on the response is empty.
This is what I get, it happens with every unauthorized response:
{
“timestamp”: “2020-06-13T16:12:23.219+00:00”,
“status”: 401,
“error”: “Unauthorized”,
“message”: “”,
“path”: “/api/auth/signin”
}
The logger by the way display the correct message in the console (“Unauthorized error: Bad credentials”).
Do you happen to know the reason?
Hey,
thank you for this great tutorial.
I got the following error:
Field jwtUtils in com.ingokoepp.xsamples.security.jwt.AuthTokenFilter required a bean of type ‘com.ingokoepp.xsamples.security.jwt.JwtUtils’ that could not be found.
Nevermind.. i forgot to add @Component to the JwtUtils.java class 🙂
Hey thanks for this tutorial. But I added course model(id,name,description) and controller doing crud operations. But when i authorize and then add values to the course using postman , its getting added but the name and description fields are displaying null. May i know whats the problem
Hi, I have problem with application, because app throw “Unauthorized error: Bad credentials”. And above is “Empty encoded password”.
o.s.s.c.bcrypt.BCryptPasswordEncoder : Empty encoded password
p.z.l.security.jwt.AuthEntryPointJwt : Unauthorized error: Bad credentials
check UserDetailsImple.java Constructor
Request
{
“username” : “mod”,
“email”: “[email protected]”,
“password” : “123456”,
“role” : [“mod”, “user”]
}
Response
{
“timestamp”: “2020-06-04T03:31:19.290+0000”,
“status”: 500,
“error”: “Internal Server Error”,
“message”: “Error: Role is not found.”,
“path”: “/api/auth/signup”
}
PS : I’m running the code you have provided in github.
Hi, you should use SQL script to insert 3 rows in
roles
table first.Thank you very much for the effort to create such a jewel.
I’ve been looking for something like this for a long time.
There are many who have dealt with this subject, but most of the time they have left it half, incomplete or not refreshed.
Man, you found a niche that is highly sought after and appreciated by boot-spring developers.
The secret is the richness of details and the fact that it works!
I recommend adding Lombok and keeping it updated.
Success!
thank you very much for your work! Great Tuto
i want source code of this tutorial.
can you please share the github link?
Hi, it is in the Source Code section.
Hi! This is an amazing article, thank you for your job.
I’ve written all the same. But I have one problem. If I want to get properties of the current user in my own method, I write this:
In headers from Postman I send my bearer token after login.
But in authentication I get anonymousUser.
Why is this happening?
Solved, my mistake 🙂
how did you do it?
Hi @Enrique Gordon, My solution was:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UserDetailsImpl currentUser = (UserDetailsImpl) authentication.getPrincipal();
This way you can get data current user in any class or method.
Regards.
You’re the best teacher that I’ve ever come across in my coding journey who can explain in detail what spring security and jwt are all about. I don’t know how I can describe you but you’re genius. This is an inspirational tutorial and I look forward to see more powerful tutorial of this type. Once again, I will say big thank you
Hi, how can I add a cascading dropdown in the signup page , and the data’s in the dropdown from the database. How it is possible in the backend and frontend?
Hi, please take a look at following tutorial (also related fullstack tutorials insides) , I think it contains some idea to implement your requirement:
Spring Boot, Spring Data JPA – Rest CRUD API example
I’ve implemented jwt with spring security and work’s fine, but when I’m trying to access the API those have @preAuthorize it’s giving me unauthorized when hitting from angular(v9) but it’s working fine in postman!
I have ensured that the login role and preAuthorize api roles are same.
Why is this happening? I have no idea…
Please help…
Hi, you can follow this Angular 8 JWT Auth tutorial. 🙂
Hello, Thank you so much for this great tutorial !
I have implemented this tutorial, but I have a problem.
when i call:
POST: http://localhost:8080/api/auth/signin
I filled out :
{
“username”:”user”,
“password”:”123456″
}
and postman response:
{
“timestamp”: “2020-05-14T13:30:02.827+0000”,
“status”: 401,
“error”: “Unauthorized”,
“message”: “Error: Unauthorized”,
“path”: “/api/auth/signin”
}
and eclipse response: “Unauthorized error:User account is locked”
Although I have filled in the correct information.
How can I fix it? thanks
Hi, “User account is locked” happens after a number of failed authentication events. So you need to check the issue why you couldn’t login with this account.
In UserDetailsImpl.java:
Switch from false to true by the following methods:
public boolean isAccountNonExpired()
public boolean isAccountNonLocked()
public boolean isCredentialsNonExpired()
public boolean isEnabled()
Because if you automatically generated them by default they are false.
PD: Sorry, I’m really not very good at English
how can i implement the same in oracle database, i have some issues with this. if you can help me, i’ll be very greatful. i hear that the versions are the most current issue.
Hey. Thank for the tutorial but I think there might be one problem or it’s only happening for me. But maybe you can reproduce it. I’m using the full tutorial of Angular and Spring Boot and if I register and directly login with this account I get 2020-05-12 23:20:09.452 ERROR 13476 — [nio-8080-exec-7] d.example.project.security.jwt.JwtUtil : Invalid JWT token: JWT strings must contain exactly 2 period characters. Found: 0
The JWT token is undefined. So the typical Angular behaviour if something is not loaded. Is that a special case and should somehow be validated in Spring Boot? Or is anything wrong in Angular? The method doFilterInternal() in AuthTokenFilter.java is causing this.
Okay I could fix it in a not very acceptable manner. In the authInterceptor in Angular you are using the line const token = this.token.getToken(); and this is giving me undefined and is not null and gives it to the Spring Boot backend. The only way to handle it is if (token != null && token != “undefined”) {
If I clone your repo, the app is working fine. If I try to build the app after your’s, I got Invalid JWT token: JWT strings must contain exactly 2 period characters. Found: 0. I look forword to hear from you with a solution. Thank you
I could not understand why token value is undefined as everything is running fine in postman
Hello! Were you able to resolve the error caused by Invalid JWT token? I have the same problem and I couldn’t solve it with (token != null && token != “undefined”). Thank you
Hello, Thank you so much for this great tutorial !
I have implemented this tutorial, but I have a problem.
When localhost:8080/api/expense/all called, it’s successfully as expected. But when localhost:8080/api/expense/76 (76 is ID for an expense), the expenseService always returns null (500 server error).
What could be the cause? and how to fix it?
Hello, thank you for the tutorial. I keep getting “Error: Unauthorized” when I go to /user , /mod, or /admin and /all. Everything else seems to work okay. Do you have any idea as to why I might be getting this error?
Hi, please make sure that you use correct Token in HTTP request.
Hey there can u please help me with error ….
“internal server error”
when i m passing the jason body it is showing error as: Internal server Error
and error message as : “Role not found”
Hi, maybe you forgot to insert 3 records into
roles
table 🙂Hello!
Amazing work, I used this implementation and everything works fine. Thanks for sharing.
However, I have a question because I want to add the option remember me to login and I am not sure how to implement it in this case.
I have API in spring boot and frontend in react. I tried to add rememberMe() function at configure(HttpSecurity http) function at WebSecurityConfig class, but after that i don’t see a remember-me cookie in the browser.
Do you have any advice?
Greetings
Adrian
main] o.s.b.web.embedded.tomcat.TomcatStarter : Error starting Tomcat context. Exception: org.springframework.beans.factory.UnsatisfiedDependencyException.
M I the only one ?
Apart from component scanning , if you missed web-starter dependency , it could cause a ripple , that is what i’ve done and failed me many times.
Oh ok let me check. thanks for the response!
Hello Sir
Thank you so much for such a detailed tutorial. You made life very easy for more in learning spring authentication.
However, I am facing two challenges; 1. I cant add more than one users because the in the user_roles table the ids for both user and the role are unique. I get an exception: java.sql.SQLIntegrityConstraintViolationException: Duplicate entry ‘1’ for key ‘UK_5q4rc4fh1on6567qk69uesvyf’
2. After registering a user I get another exception on trying to login: 2020-05-07 13:05:36.007 WARN 12224 — [nio-8080-exec-7] o.s.s.c.bcrypt.BCryptPasswordEncoder : Encoded password does not look like BCrypt
2020-05-07 13:05:36.008 ERROR 12224 — [nio-8080-exec-7] z.o.m.security.jwt.AuthEntryPointJwt : Unauthorized error: Bad credentials
How best can I avoid roles column in the user_roles table to be non unique or is there a different approach.
Hi, I don’t really understand your question.
“I cant add more than one users because the in the user_roles table the ids for both user and the role are unique.”
You can add user by sending HTTP request to
/api/auth/signup
endpoint (withrole
array in the payload).its about the relationship table. the one that has two columns for either ids (role_id and user_id). Since we created a table with 3 roles that have ids 1,2, and 3 in the table the ids are unique say if my first user has id=1 and role is ROLE_USER which has id=1 then if i wish to add another user with id=2 and role ROLE_USER again when added to the relationship table where role_id = 1 already exists. this will create a scenario like:
user_id |role_id
1 | 1
2 | 1
which then complains of constraint violation issues since role_id must be unique. well i had to create new roles with new ids.
my question number 2
After registering a user I get another exception on trying to login: 2020-05-07 13:05:36.007 WARN 12224 — [nio-8080-exec-7] o.s.s.c.bcrypt.BCryptPasswordEncoder : Encoded password does not look like BCrypt
2020-05-07 13:05:36.008 ERROR 12224 — [nio-8080-exec-7] z.o.m.security.jwt.AuthEntryPointJwt : Unauthorized error: Bad credentials
What could be the cause?
1. The relationship between User entity and Role entity is Many to Many.
We don’t add any record to
user_roles
table directly. Please look at how we signup user inAuthController
.I will write a tutorial for Spring JPA Many to Many Association when having time.
2. I don’t really know what was wrong. You can debug yourself and notice these lines:
Thanks very much I will do that and check whats causing the exception
Hey Bezkoder,
i am not able to understand what might be the root of Empty coded password, i searched it everywhere,user has already been registered,but i am facing the above issue and error is coming as Bad credenetials
Hello,
I’m trying to follow your tutorial but I’d like to have a connexion without username (just email/password), what is the workaround for this? I’m in trouble when I need to implement the UserDetailsService because there is no loadByEmail method or something like this.
Hi, you can treat ‘username’ as ’email’. That means, when saving user information to the database, the username column stores email.
Best Tutorial!
I have learned lot of new things.
Can you explain to me the functionality of every role?
Hi, it depends on your use cases. The roles in this tutorial is used for illustrating authority 🙂
Really great tutorial, it helped me a lot, thank you very much! 🙂
But one question:
Why can you write @PreAuthorize(“hasRole(‘ADMIN’)”)
and not @PreAuthorize(“hasRole(‘ROLE_ADMIN’)”)
We neved used the string ADMIN anywhere, only ROLE_ADMIN as part of the enum.
Hi, the ‘ROLE_’ prefix gets added automatically for
hasRole
. If you want to work withROLE_ADMIN
, just usehasAuthority('ROLE_ADMIN')
.ah, thank you so much, very simple explanation and it makes sense! I didn’t take a course on Spring Security yet, so I didn’t know that.
Thanks for this amazing course. It was really easy to understand it.
I have one question, given this example code, how could I implement an oauth2 login as well?
E.g. : when the user visits /signin , I would like to provide the options of logging in either with jwt or oauth2 (github/google). Can you give me a hint?
Hi, you can read this article.
Thx for this tutorial, I looked through a lot of tutorials and couldn’t understand any of them until I found yours.
Thank you so much
Great tutorial!
I have a question, How can I modify it to authenticate a user using its email and password instead of username and password ?
Hi, you can see the email as username in the signup process.
Thank you for This Awesome Gift Tutorial 😉
I have many other Application that use the same Table and there is no possible way to change table structure as it’s in production.
We have email,password Field so can you please show me How to force UsernamePasswordAuthenticationToken to attempt auth using email instead of username please.
Hello,
I’m getting the following error, whenever I try to create a signup POST request:
ERROR: insert or update on table “user_roles” violates foreign key constraint “fkrhfovtciq1l558cw6udg0h0d3”
Detail: Key (role_id)=(2) is not present in table “role”.
I’ve already inserted the 3 roles you mentioned.
Do you know why I’m getting this error? Thank you for your help! 🙂
Hi, I think you can drop
user_roles
table, then dropusers
androles
table.Just do everything from the beginning. Maybe you miss or make mistake in a certain step.
Thanks a lot for this nice and clear tutorial
Can you post here your headers in the request? I got i problem and i think the header is the cause.
Hi, you need to set
content-type: application/json
for HTTP request header.It has been set. Still facing the issue with same error.
{
“username”:”alphabank”,
“password”:”alphabank”,
“role”:[“mod”, “user”]
}
this is the request i am sending, and the header is content-type-
application/json
You should have ’email’ in the payload.
For admin while signing up i have given the role as user and for sigin it s coming good but for http://localhost:8080/api/test/admin it is coming as 403 Forbidden
Hi, please make sure that you set the correct Authorization Header in HTTP request.
very good and detailed tutorial; thanks a lot
Hello!
it’s giving me this: “message”: “Error: Role is not found.” to refer to this one: case “admin”:
Role adminRole = roleRepository.findByName(ERole.ROLE_ADMIN)
.orElseThrow(() -> new RuntimeException(“Error: Role is not found.”));
roles.add(adminRole);
break;
Can you tell me what’s the problem please? Thanks.
Hi, maybe you forgot to run SQL insert 3 rows of Role table. 🙂
I run SQL script but the issue still remains
Please follow step by step in the video demo:
https://youtu.be/o8DEk4XGcZw
I loved this Spring Boot Auth tutorial! I actually read your blog fairly often, and you’re constantly coming out with some great tutorials here.
Very helpful post. Could you add how to revoke tokens?
Hi, I will write the tutorial for revoke tokens when having time 🙂
Excellent! It worked perfectly. That’s not the first time I found here exactly just what I looking for. Thanks for the good work.
Awesome job, thanks for sharing.
Hi BezKoder,
Thank you so much for you posting such superb tutorial. And could you explain a little how this JWT token has secured in this api.
Hi, JWT does not hide, obscure, secure data at all.
You can see that the process of generating JWT (Header, Payload, Signature) only encode & hash data, not encrypt data.
The purpose of JWT is to prove that the data is generated by an authentic source.
If you want to know more details about JWT, you can visit:
In-depth Introduction to JWT-JSON Web Token
Ok, now I’ve got it. Testing this endpoint I tried to send token from Headers tab, instead using Authorisation tab. Everything is ok 🙂
Hi bezkoder, thank you very much, you’ve done a great job!
I have one problem with Postman.
After signing in as “mod” I try to access resource: GET http://localhost:8080/api/test/user.
I send value: Bearer {my token} with key Authorization (in section Header) and I receive this error:
{
“timestamp”: “2020-04-04T23:51:06.706+0000”,
“status”: 401,
“error”: “Unauthorized”,
“message”: “Error: Unauthorized”,
“path”: “/api/test/user”
}
What am I doing wrong?
Hi, I’ve checked GET
http://localhost:8080/api/test/user
with ‘mod’ role and it works.Please make sure that you use the token correctly.
Can you post me your PostMan requests? I still get the unauthorized error
Thank you!
Hello, i have the some problem, did you solve it? can u help me plz
Hello, Can anyone solve this problem please !
Hi, you should check the
Authorization
header.Hi bezkoder i have a problem when i create a user and give him some roles on angular when i’m back in springBoot the role array is empty can you help please!!!
Best regards !!
Hi, please show me the HTTP request payload.
Thank you for that great tutorial soooooooooooo usefull !
Great piece of work!
Hi, im new with java language and this helped me a lot. Are there any way to support and
appreciate your work?
Thanks so much !!
Hi Alberto,
I’m so happy to know that this tutorial helps many people like you.
If you want to donate, I have a Paypal account: [email protected] 🙂
Best Regards,
bezkoder.
Hello Bezkoder thank you , you did a great job , but
hasRole(..)
it should be changed tohasAuthority
right? because at firsthasRole
doesn’t work after that i tried withhasAuthority
and it works..Hi, Roles and Authorities are similar in Spring.
The difference is that the
'ROLE_'
prefix gets added automatically forhasRole
. That means,hasAuthority('ROLE_USER')
is similar tohasRole('USER')
. 🙂thank you bezkoder , i have a question i didn’t add the prefix ROLE_ when i added my roles (because i didn’t use enumarted strings ), so i think that’s why she doesn’t work in the first time with hasRole so did you think if that will causes a problems??
You must add the prefix
ROLE_
to make it work 🙂 Please follow step by step in the tutorial.ok thank you , what about the logout endpoint
the method should have parametres?
//tokenStore.removeAccessToken(accessToken);
//tokenStore.removeRefreshToken(refreshToken);
We’re gonna implement logout on frontend side (by removing token from localStorage/sessionStorage for example). So we don’t need logout endpoint here.
where are payload classes, i didn’t find them com.bezkoder.springjwt.payload.*
i find it, thanks
Hi, thanks for the tutorial I have this error that the postman shows me what do you know?
“error”: “Bad Request”,
“message”: “Invalid JSON input: Cannot deserialize instance of `java.util.HashSet` out of VALUE_STRING token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.HashSet` out of VALUE_STRING token\n at [Source: (PushbackInputStream); line: 5, column: 10] (through reference chain: com.ramajudicial.Solicitud.de.Informacion.payload.requet.SignupRequest[\”role\”])”
Hi, please show me your POST request 🙂
Hi, thanks for answering if I had something wrong with the POST, now this error is generating, I am working with a sql server database
Error: Cannot insert the value NULL into column ‘userId’, table ‘lramajudicialpru.dbo.user’; column does not allow nulls. INSERT fails.
Do you know why you are sending me null?
Hi, this Spring Boot Application is configured to work with MySQL or PostgreSQL database, so you need to modify
application.properties
file for SQL Server Database.Do you have any idea how to configure it? I have this configuration connected to the database but I don’t know why it gives the previous error
spring.datasource.url=
spring.datasource.username=
spring.datasource.password=
spring.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.jpa.show-sql=true
spring.jpa.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.hibernate.ddl-auto = validate
spring.jpa.hibernate.naming_strategy = org.hibernate.cfg.EJB3NamingStrategy
thanks.
You should fill
url
,username
andpassword
.If you did it but the error still occurs, I’m so sorry because I’ve not worked with SQL Server now.
I will check it and write another tutorial when having time 🙂
Amazing tutorial.
Amazing Tutorial,
Thank you!
Hello,
Thanks for the great tutorial, but i have one problem. When sending a request to the API with the roles “mod”, “user” it always throws an exception that it could not find a role.
This even happens when using your source code.
Nevermind, as I was writing this comment I found the problem. Forgot to put the roles in the postgres database
Yeah, we should do it first 🙂
i have the same error.
Hi, you must insert 3 rows in
roles
table as tutorial instruction first.sir,can’t we do that within the code itself.
{
“username”: “henk”,
“email”: “[email protected]”,
“password”: “keukentafel”,
“role”: [“henk”, “user”]
}
please use above one. (insted of mod —-> henk)
Hello, I am a beginner in the code do you create the fields of the database tables? or do you do manual in mysql?
Hi, Spring Data will do it automatically 🙂
Thank you for your response, and if I have a database already created with the same data, should your code work well? Or do I have to skip somewhere?
If you have the same database table, you don’t need to run SQL queries for inserting records to roles table 🙂
Thanks a lot for this tutorials. Been looking for this for a long time!
The JwtResponse.type Bearer what is this? what does it mean? can it be changed to a custom one? can it be omitted?
Hi, I think that you can find the answer here 🙂
Hello, many thanks for these great tutorials!
I think I’ll go this way to implement a simple app, but I have some questions.
Is there a way to encrypt password in the POST request? I can see it is encrypted in database but requests can be intercepted and I’m new to angular.
Do you plan to make a tutorial on deployment of a Spring boot app? I heard of solutions like heroku, azure, amazon.. but it’s still a bit confusing, I’d really like a guide made by you on this (you make things look really simple!).
Hi, I will write the tutorials when having time 🙂
Definitely look into Heroku, which is part of Salesforce Inc apparently. They are by far the easiest and most user friendly hosting platform for Spring boot applications that I know of.
You encrypt POST requests by using HTTPS with a valid certificate. If you do that, the whole POST request body will be encrypted. In order for your requests to not be intercepted, you should never send them over HTTP. This tutorial is good for setting it up in development, but when you go into live environment, it’s necessary to look into HTTPS as well.
Hello, how can we do that easily ? Is there some simple tutorials like that ?
Hello. Which version of Java uses this tutorial? Is it completely Java 8?
Yeah, Java 8 🙂
Hi Bezkoden,
Thank you for the great tutorial. I do have a question, though. The AuthenticationManager in the AuthController is not able to be autowired as there is no bean found for the AuthenticationManager. Do you have any idea as how to solve it?
Thanks in advance!
Hi, we have a bean in
WebSecurityConfig
:Hi bezkoder, maybe you have any resources, where I can will read about refresh token?
Hi, here you are: Spring Boot Refresh Token with JWT example
Hi, great Tutorial. But if I want to register a user i get this Error:
“timestamp”: “2020-02-06T15:14:41.823+0000”,
“status”: 405,
“error”: “Method Not Allowed”,
“message”: “Request method ‘GET’ not supported”,
“path”: “/api/auth/signup”
The same for “path”: “/api/auth/signin”.
Could you pls help me. Thank you very much
Hi, please make sure you make a POST HTTP request (with payload) instead of GET request to
/api/auth/signin
endpoint.Hi bezkoder,
Thank you for the tutorial!
I have followed your instructions. However, for some reason in my WebSecurityConfig.java, I get an error on the following code block:
which underlines the userDetailsService in the brackets and says:
userDetailsService (T) in AuthenticationManagerBuilder cannot be applied to
(com.globomatics.portalproject.services.UserDetailsServiceImpl)
reason: no instance(s) of type variable(s) exist so that UserDetailsServiceImpl conforms to UserDetailsService
Do you have an idea why I might be getting this one and how could I fix it?
Thank you in advance!
Nvm, please ignore me. I managed to fix it.
Great! 🙂
How did you fix it?? Please in future comment the fix as well (for other people who have the same problem, like me)
I have the same issue. Whats this error?
Hi, make sure that you’ve add
@Service
annotation forUserDetailsServiceImpl
class.How did you fix this,am getting the same annoying ERROR
I have the same issue. Could you help me to fix it?
bonjour comment avez-vous résolu se probleme ??
How did you fixed it let me know
Make sure that you implemented UserDetailsService from org.springframework.security.core.userdetails.UserDetailsService.
That worked for me.
Thank you!
here is an overview of its code application.properties:
spring.datasource.url= jdbc:mysql://localhost:3306/testdb?useSSL=false
spring.datasource.username= root
spring.datasource.password=
spring.jpa.hibernate.ddl-auto= update
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
# App Properties
example.app.jwtSecret= secretkey
example.app.jwtExpirationMs= 123456789
Have you created MySQL
testdb
database manually?How to create database automatically?
But it doesn’t generate the table.
Please make sure that you’ve configured datasource in
application.properties
correctly.If the issue still exists, please show me your console log error.
Great tutorial but i did not understand what my database table was not generated at startup
Hi, you must create
testdb
database with username & password first.Our Hibernate configuration only generates tables.
Simplesmente fantástico, o seu tutorial. Parabéns
Hi bezkoder! thank you very much for this awesome tutorial! I have a little question though.. It all worked perfectly, but when i create an user with 2 roles (as input I wrote: ‘ “role”: [“ROLE_MODERATOR”, “ROLE_USER]’ the app only associates the user with user role, but not with moderator role. I tried with my own code (following ur instructions) but when it didnt work, i cloned your repo, but i still have the same problem.. do u know what it could be?
Thanks again for this amazing tutorial!
Nevermind my question, I saw what my mistake was.. thank you again!
Yeah, you should use: [“mod”, “user”].
Hello, can you help me to resorlve this problem, i can’t assign ROLE_ADMIN or ROLE_MODERATOR to user.when i add a user even i specify admin or role in dataBase it’s user role !!
Hi, you need to add
role:["admin", "mod"]
in the payload 🙂i did but i have the some problem :'( .in user_roles table i have:
user_id role_id
1 1
2 1
3 1
4 1
5 1
THX U for your answer (f)
We have 3 tables, and each row in
user_roles
was generated automatically 🙂So you should create user by sending HTTP request with payload containing
role
array.big thx ,it’s works (y)
Pls can you tell me where to add role : [“admin” , “mod”] in payload . because even I am facing the same problem only one role is getting assign to user.
Can you tell me how did you resolved the mistake
Great tutorial but my database table was not generated at startup
and any pointer on how to generate refresh token. thanks
Hi, you must create testdb database with username & password first.
Our Hibernate configuration only generates tables.
For refresh token, I will write a tutorial when having time. 🙂
Insane tuto, exactly what i needed. thx.
Thank you for this tutorial. It really helped a lot! Great job.
Hello,
Thank you very much for your step by step tutorial.
I got the following error: “cannot resolve method getName()” in the following method:
Initially, I thought it happened maybe I did some mistake during my typing. But I copy-paste your code for ERole, User, Role Model and also the UserDetailsImpl.java but it still shows that error.
How can I fix that?
Hi, I’m sorry, syntax highlight plugin causes the Typo.
You can check
Role
andUser
class again to make sure that all the fields are correct.Another way is to download the source code.
WOW, easy to understand your Tutorial. You make complicated things like Spring Security simple.
Hello, I would like to ask you something.
The spring security oauth 2.0 resource serve has been deprecated.
Is this tutorial the way that it should be done now that the
EnableResourceServer
is deprecated?I would like to migrate my project that is using it, but in their migration guide there are not explanation about the resource server since they say that is out of the scope in the migration guide.
Is this the new way or can you write a tutorial with the new way about implementing oauth 2.0 ?
thanks
Hi, I think that
EnableResourceServer
will not affect the code in this tutorial.For Spring Security OAuth 2.0, I will write the tutorial in near future.
Excellent, I have tried this tutorial and it worked!, I’m really thankful for you, I hope you are going to be successful because sharing useful knowledge for many people.
Thank you for your comment. Hope you to be successful too!
I have a question, how to keep the tokens from expiring (token does not expire)?
Thanks for your post. I’m also waiting for your Spring Boot JWT with Refresh Token tutorial.
Hi, here you are: Spring Boot Refresh Token with JWT example
Hi, you can implement Refresh Token.
Hello, I’m a beginner, so I have a lot of questions. I hope you will answer this question. I’m so frustrated because I don’t understand.
In the repository, we divided the user and the role. What function does the user and the role ? For example, if you type id/pass and then go to the repository, I don’t understand why you use id/email in the user. I know the reason why I want to use the role in the repository for automation, but I don’t know why I use the repository user.
Hi, I don’t really understand your question.
But if you want to know why we use the repository user, you can find where we call its methods:
userRepository.existsByUsername()
userRepository.existsByEmail
userRepository.save()
userRepository.findByUsername()
Thank you for good writing. But I don’t understand what’s the difference between database and repository. I don’t know exactly the difference between the two, so I’m asking you a question.
Hi,
A Repository is a database that stores the metadata for Designer objects. In other words, the data associated with objects like Entities, Modules, Table Definitions, etc. is stored as rows in tables that are part of the Repository.
The Repository also includes a PL/SQL Application Programming Interface (API) for maintaining this data.
A Repository would essentially be linked to at least one database, but in general, it is linked to many databases.
A Database is just a place to store data, or an application database is a place to store the data for a particular computer application.
The Repository is itself an application database, but it also stores data about (ie. metadata – data about data) other application databases. These other databases might be co-located with the Repository, but normally are stored somewhere else.
A Repository is a central common point of file storage of a related nature, a Database is a structured file or set of files that store and organize data.
I found this great answer here: https://qr.ae/TeQcol.
I am regular reader of your site. All of Spring tutorials are really good. This Spring Boot Authentication with JWT tutorial is the best.
Amazing article! It really helped me with a school project.
Only one question, how can I add a server side logout feature? So the token is immediately invalid
Hi, you can implement a
/logout
endpoint (or logout functionality) where you only have to get the token and remove it fromTokenStore
.The detail is decribed at: https://stackoverflow.com/a/42907381.
# App Properties
bezkoder.app.jwtSecret= bezKoderSecretKey
bezkoder.app.jwtExpirationMs= 86400000
by defaults?
It’s custom properties.
where can i get that? like custom properties according to your design?
These custom properties are what you set, personally, and should not be the same as other places.
This is a great example. Thanks so much for this code and explanation. You have your timeout set to 10 days (if I did the math right). I assume that normally, you would want the timeout to be some much lower value, such as 10-15 minutes. How do you handle the timeout? You only want the user’s login to timeout if he has been inactive. So do you get a new token with every transaction? Or if it has been 10 minutes since the last token?
Hello, im a french dev student, thank you very much for your work! I have a probleme with this method in UserDetailsImpl.
Im not very strong with stream map etc, can you explain me this block a bit more?
Thank you for your attention and continue to display this wonderful content.
Mathieu
Hi Mathieu,
–
user.getRoles()
returns aSet<Role>
, we convert this Set to aStream
ofRole
. Imagine that the stream is a collection ofRole
that releases items in turn.–
map()
changes everyRole
item above to aSimpleGrantedAuthority
object, the parameter for the constructor could be one of these Strings: ‘ROLE_USER’, ‘ROLE_MODERATOR’, ‘ROLE_ADMIN’.So, what does
role.getName().name()
do?–
role.getName()
returnsERole
enum object, let’s call iterole_object
. Look back to this:–
erole_object.name()
returns the String corresponding to the enum (‘ROLE_MODERATOR’ for example).Please make sure that you define
Role
model in Role.java correctly.Regards,
bezkoder.
Thank you a lot for your explanation! I will follow your site and youtube channel studiously and recommend it to others students!
Thank you so much! Wish you all the best 🙂
Hi @Mathieu LC,
I think you miss getter/setter for Name field on Role.java class
Role has a method called getName() which returns the Enum constant & name method returns the name of this enum constant.
Great tutorial series. Congratulations for the detail and the good explanation.
Hi, thank you!
Thank you, this is the best article on Spring Security & JWT I have ever seen!
Can you please tell me how to delete a user from postman directly?
What if we wanted to update the role for a user on the website ? Like remove Role_Moderator and upgrade him to Role_Admin ? How to do that ?