diff --git a/README.md b/README.md
index f2ab7a4..8af568a 100644
--- a/README.md
+++ b/README.md
@@ -23,11 +23,11 @@ You can have an overview of our Spring Boot Server with the diagram below:
Open `src/main/resources/application.properties`
```properties
-spring.datasource.url= jdbc:mysql://localhost:3306/testdb?useSSL=false
+spring.datasource.url= jdbc:mysql://localhost:3306/testdb_spring?useSSL=false
spring.datasource.username= root
spring.datasource.password= 123456
-spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect
+spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto= update
# App Properties
@@ -35,6 +35,10 @@ bezkoder.app.jwtSecret= bezKoderSecretKey
bezkoder.app.jwtExpirationMs= 3600000
bezkoder.app.jwtRefreshExpirationMs= 86400000
```
+## Run MySQL 8
+```
+docker run --name some-mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:latest
+```
## Run Spring Boot application
```
@@ -43,6 +47,9 @@ mvn spring-boot:run
## Run following SQL insert statements
```
+create database testdb_spring;
+use testdb_spring;
+
INSERT INTO roles(name) VALUES('ROLE_USER');
INSERT INTO roles(name) VALUES('ROLE_MODERATOR');
INSERT INTO roles(name) VALUES('ROLE_ADMIN');
diff --git a/notes/JWT.postman_collection.json b/notes/JWT.postman_collection.json
new file mode 100644
index 0000000..2b16e2e
--- /dev/null
+++ b/notes/JWT.postman_collection.json
@@ -0,0 +1,100 @@
+{
+ "info": {
+ "_postman_id": "d7edbb04-bb72-4a58-aa3a-8539ea5c8bac",
+ "name": "JWT",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+ "_exporter_id": "16859724"
+ },
+ "item": [
+ {
+ "name": "sign_up",
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n \"username\": \"donhuvy\",\r\n \"email\": \"donhuvy@hotmail.com\",\r\n \"password\": \"123456\",\r\n \"role\": [\"ROLE_USER\", \"ROLE_ADMIN\"]\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://localhost:8080/api/auth/signup",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "api",
+ "auth",
+ "signup"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "sign_in",
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n \"username\": \"donhuvy\",\r\n \"password\": \"123456\"\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://localhost:8080/api/auth/signin",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "api",
+ "auth",
+ "signin"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "refresh_token",
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "raw",
+ "raw": "{\r\n \"refreshToken\": \"89132309-d900-4ab0-8162-f083d4893793\"\r\n}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "http://localhost:8080/api/auth/refreshtoken",
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8080",
+ "path": [
+ "api",
+ "auth",
+ "refreshtoken"
+ ]
+ }
+ },
+ "response": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 1c03de6..1fab892 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,76 +1,83 @@
- 4.0.0
-
- org.springframework.boot
- spring-boot-starter-parent
- 2.7.3
-
-
- com.bezkoder
- spring-boot-security-jwt
- 0.0.1-SNAPSHOT
- spring-boot-security-jwt
- Spring Boot, Spring Security: JWT Authentication & Authorization with Refresh Token example
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 3.0.0
+
+
+ com.bezkoder
+ spring-boot-security-jwt
+ 0.0.1-SNAPSHOT
+ spring-boot-security-jwt
+ Spring Boot, Spring Security: JWT Authentication & Authorization with Refresh Token example
+
-
- 1.8
-
+
+ 17
+
-
-
- org.springframework.boot
- spring-boot-starter-data-jpa
-
-
-
- org.springframework.boot
- spring-boot-starter-security
-
-
-
- org.springframework.boot
- spring-boot-starter-web
-
-
-
- org.springframework.boot
- spring-boot-starter-validation
-
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
-
- mysql
- mysql-connector-java
- runtime
-
-
-
- io.jsonwebtoken
- jjwt
- 0.9.1
-
-
-
- org.springframework.boot
- spring-boot-starter-test
- test
-
-
-
- org.springframework.security
- spring-security-test
- test
-
-
+
+ org.springframework.boot
+ spring-boot-starter-security
+
-
-
-
- org.springframework.boot
- spring-boot-maven-plugin
-
-
-
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+
+ javax.xml.bind
+ jaxb-api
+ 2.3.1
+
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+
+ io.jsonwebtoken
+ jjwt
+ 0.9.1
+
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+
+ org.springframework.security
+ spring-security-test
+ test
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
diff --git a/src/main/java/com/bezkoder/spring/security/jwt/controllers/AuthController.java b/src/main/java/com/bezkoder/spring/security/jwt/controllers/AuthController.java
index 62f70aa..dbfa8d3 100644
--- a/src/main/java/com/bezkoder/spring/security/jwt/controllers/AuthController.java
+++ b/src/main/java/com/bezkoder/spring/security/jwt/controllers/AuthController.java
@@ -5,8 +5,8 @@
import java.util.Set;
import java.util.stream.Collectors;
-import javax.validation.Valid;
+import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
diff --git a/src/main/java/com/bezkoder/spring/security/jwt/models/RefreshToken.java b/src/main/java/com/bezkoder/spring/security/jwt/models/RefreshToken.java
index 1f89bac..1c5c316 100644
--- a/src/main/java/com/bezkoder/spring/security/jwt/models/RefreshToken.java
+++ b/src/main/java/com/bezkoder/spring/security/jwt/models/RefreshToken.java
@@ -1,8 +1,16 @@
package com.bezkoder.spring.security.jwt.models;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.OneToOne;
+
import java.time.Instant;
-import javax.persistence.*;
+
@Entity(name = "refreshtoken")
public class RefreshToken {
diff --git a/src/main/java/com/bezkoder/spring/security/jwt/models/Role.java b/src/main/java/com/bezkoder/spring/security/jwt/models/Role.java
index dca406f..cc030a6 100644
--- a/src/main/java/com/bezkoder/spring/security/jwt/models/Role.java
+++ b/src/main/java/com/bezkoder/spring/security/jwt/models/Role.java
@@ -1,6 +1,14 @@
package com.bezkoder.spring.security.jwt.models;
-import javax.persistence.*;
+
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
@Entity
@Table(name = "roles")
diff --git a/src/main/java/com/bezkoder/spring/security/jwt/models/User.java b/src/main/java/com/bezkoder/spring/security/jwt/models/User.java
index 0a977b7..003533a 100644
--- a/src/main/java/com/bezkoder/spring/security/jwt/models/User.java
+++ b/src/main/java/com/bezkoder/spring/security/jwt/models/User.java
@@ -1,15 +1,26 @@
package com.bezkoder.spring.security.jwt.models;
+import jakarta.persistence.Entity;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.JoinTable;
+import jakarta.persistence.ManyToMany;
+import jakarta.persistence.Table;
+import jakarta.persistence.UniqueConstraint;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
+
import java.util.HashSet;
import java.util.Set;
-import javax.persistence.*;
-import javax.validation.constraints.Email;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.Size;
+
@Entity
-@Table( name = "users",
+@Table( name = "users",
uniqueConstraints = {
@UniqueConstraint(columnNames = "username"),
@UniqueConstraint(columnNames = "email")
@@ -33,8 +44,8 @@ public class User {
private String password;
@ManyToMany(fetch = FetchType.LAZY)
- @JoinTable( name = "user_roles",
- joinColumns = @JoinColumn(name = "user_id"),
+ @JoinTable( name = "user_roles",
+ joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id"))
private Set roles = new HashSet<>();
diff --git a/src/main/java/com/bezkoder/spring/security/jwt/payload/request/LoginRequest.java b/src/main/java/com/bezkoder/spring/security/jwt/payload/request/LoginRequest.java
index 76bdd03..68e0df1 100644
--- a/src/main/java/com/bezkoder/spring/security/jwt/payload/request/LoginRequest.java
+++ b/src/main/java/com/bezkoder/spring/security/jwt/payload/request/LoginRequest.java
@@ -1,6 +1,6 @@
package com.bezkoder.spring.security.jwt.payload.request;
-import javax.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotBlank;
public class LoginRequest {
@NotBlank
diff --git a/src/main/java/com/bezkoder/spring/security/jwt/payload/request/SignupRequest.java b/src/main/java/com/bezkoder/spring/security/jwt/payload/request/SignupRequest.java
index 6436415..7c80062 100644
--- a/src/main/java/com/bezkoder/spring/security/jwt/payload/request/SignupRequest.java
+++ b/src/main/java/com/bezkoder/spring/security/jwt/payload/request/SignupRequest.java
@@ -1,8 +1,10 @@
package com.bezkoder.spring.security.jwt.payload.request;
-import java.util.Set;
+import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.Size;
-import javax.validation.constraints.*;
+import java.util.Set;
public class SignupRequest {
@NotBlank
diff --git a/src/main/java/com/bezkoder/spring/security/jwt/payload/request/TokenRefreshRequest.java b/src/main/java/com/bezkoder/spring/security/jwt/payload/request/TokenRefreshRequest.java
index 1bdc867..b293f86 100644
--- a/src/main/java/com/bezkoder/spring/security/jwt/payload/request/TokenRefreshRequest.java
+++ b/src/main/java/com/bezkoder/spring/security/jwt/payload/request/TokenRefreshRequest.java
@@ -1,6 +1,7 @@
package com.bezkoder.spring.security.jwt.payload.request;
-import javax.validation.constraints.NotBlank;
+
+import jakarta.validation.constraints.NotBlank;
public class TokenRefreshRequest {
@NotBlank
diff --git a/src/main/java/com/bezkoder/spring/security/jwt/security/WebSecurityConfig.java b/src/main/java/com/bezkoder/spring/security/jwt/security/WebSecurityConfig.java
index 513093c..2ee1271 100644
--- a/src/main/java/com/bezkoder/spring/security/jwt/security/WebSecurityConfig.java
+++ b/src/main/java/com/bezkoder/spring/security/jwt/security/WebSecurityConfig.java
@@ -87,8 +87,8 @@ public SecurityFilterChain filterChain(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()
+ .authorizeRequests().requestMatchers("/api/auth/**").permitAll()
+ .requestMatchers("/api/test/**").permitAll()
.anyRequest().authenticated();
http.authenticationProvider(authenticationProvider());
diff --git a/src/main/java/com/bezkoder/spring/security/jwt/security/jwt/AuthEntryPointJwt.java b/src/main/java/com/bezkoder/spring/security/jwt/security/jwt/AuthEntryPointJwt.java
index f929736..6ec252c 100644
--- a/src/main/java/com/bezkoder/spring/security/jwt/security/jwt/AuthEntryPointJwt.java
+++ b/src/main/java/com/bezkoder/spring/security/jwt/security/jwt/AuthEntryPointJwt.java
@@ -4,10 +4,9 @@
import java.util.HashMap;
import java.util.Map;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
+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;
diff --git a/src/main/java/com/bezkoder/spring/security/jwt/security/jwt/AuthTokenFilter.java b/src/main/java/com/bezkoder/spring/security/jwt/security/jwt/AuthTokenFilter.java
index c484414..b305c43 100644
--- a/src/main/java/com/bezkoder/spring/security/jwt/security/jwt/AuthTokenFilter.java
+++ b/src/main/java/com/bezkoder/spring/security/jwt/security/jwt/AuthTokenFilter.java
@@ -2,11 +2,10 @@
import java.io.IOException;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
+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;
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index aa2cfad..09e61c2 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -2,7 +2,7 @@ spring.datasource.url= jdbc:mysql://localhost:3306/testdb_spring?useSSL=false
spring.datasource.username= root
spring.datasource.password= 123456
-spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQL5InnoDBDialect
+spring.jpa.properties.hibernate.dialect= org.hibernate.dialect.MySQLDialect
spring.jpa.hibernate.ddl-auto= update
# App Properties