├── README.md ├── php-jwt-generation-validation ├── jwt.php ├── jwt_utils.php ├── jwt_valid.php └── readme.rst ├── php-jwt-rest-authentication ├── db.php ├── jwt_utils.php ├── login.php ├── readme.rst ├── register.php ├── user.sql └── users.php ├── python-flask-rest-api-jwt-auth ├── app.py ├── db_conf.py ├── readme.rst ├── rest.py └── user.sql └── spring-security-api-auth-jwt ├── build.gradle ├── pom.xml ├── readme.rst ├── spring-jwt.sql └── src └── main ├── java └── com │ └── roytuts │ └── spring │ └── security │ └── api │ └── auth │ └── jwt │ ├── SpringSecurityApiAuthJwtApp.java │ ├── config │ ├── ApiAuthenticationEntryPoint.java │ ├── ApiAuthenticationEntryPoint.java_3 │ ├── ApiSecurityConfig.java │ ├── ApiSecurityConfig.java_3 │ ├── DatabaseConfig.java │ └── EncoderConfig.java │ ├── dao │ ├── UserDao.java │ └── UserDao.java_3 │ ├── exception │ ├── DisabledUserException.java │ ├── InvalidUserCredentialsException.java │ ├── JwtTokenMalformedException.java │ └── JwtTokenMissingException.java │ ├── filter │ ├── JwtAuthenticationFilter.java │ └── JwtAuthenticationFilter.java_3 │ ├── model │ ├── Role.java │ ├── User.java │ └── UserRole.java │ ├── rest │ └── controller │ │ ├── ApiRestController.java │ │ └── JwtRestController.java │ ├── rowmapper │ └── UserRowMapper.java │ ├── service │ └── UserAuthService.java │ ├── util │ ├── JwtUtil.java │ └── JwtUtil.java_3 │ └── vo │ ├── JwtRequest.java │ ├── JwtResponse.java │ └── UserVo.java └── resources ├── application.properties ├── application.properties_3 ├── user-role.sql └── user.sql /README.md: -------------------------------------------------------------------------------- 1 | # jwt 2 | JWT related programs 3 | -------------------------------------------------------------------------------- /php-jwt-generation-validation/jwt.php: -------------------------------------------------------------------------------- 1 | 'HS256','typ'=>'JWT'); 6 | $payload = array('sub'=>'1234567890','name'=>'John Doe', 'admin'=>true, 'exp'=>(time() + 60)); 7 | 8 | $jwt = generate_jwt($headers, $payload); 9 | 10 | echo $jwt; -------------------------------------------------------------------------------- /php-jwt-generation-validation/jwt_utils.php: -------------------------------------------------------------------------------- 1 | exp; 25 | $is_token_expired = ($expiration - time()) < 0; 26 | 27 | // build a signature based on the header and payload using the secret 28 | $base64_url_header = base64url_encode($header); 29 | $base64_url_payload = base64url_encode($payload); 30 | $signature = hash_hmac('SHA256', $base64_url_header . "." . $base64_url_payload, $secret, true); 31 | $base64_url_signature = base64url_encode($signature); 32 | 33 | // verify it matches the signature provided in the jwt 34 | $is_signature_valid = ($base64_url_signature === $signature_provided); 35 | 36 | if ($is_token_expired || !$is_signature_valid) { 37 | return FALSE; 38 | } else { 39 | return TRUE; 40 | } 41 | } 42 | 43 | function base64url_encode($str) { 44 | return rtrim(strtr(base64_encode($str), '+/', '-_'), '='); 45 | } -------------------------------------------------------------------------------- /php-jwt-generation-validation/jwt_valid.php: -------------------------------------------------------------------------------- 1 | exp; 25 | $is_token_expired = ($expiration - time()) < 0; 26 | 27 | // build a signature based on the header and payload using the secret 28 | $base64_url_header = base64url_encode($header); 29 | $base64_url_payload = base64url_encode($payload); 30 | $signature = hash_hmac('SHA256', $base64_url_header . "." . $base64_url_payload, $secret, true); 31 | $base64_url_signature = base64url_encode($signature); 32 | 33 | // verify it matches the signature provided in the jwt 34 | $is_signature_valid = ($base64_url_signature === $signature_provided); 35 | 36 | if ($is_token_expired || !$is_signature_valid) { 37 | return FALSE; 38 | } else { 39 | return TRUE; 40 | } 41 | } 42 | 43 | function base64url_encode($data) { 44 | return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); 45 | } 46 | 47 | function get_authorization_header(){ 48 | $headers = null; 49 | 50 | if (isset($_SERVER['Authorization'])) { 51 | $headers = trim($_SERVER["Authorization"]); 52 | } else if (isset($_SERVER['HTTP_AUTHORIZATION'])) { //Nginx or fast CGI 53 | $headers = trim($_SERVER["HTTP_AUTHORIZATION"]); 54 | } else if (function_exists('apache_request_headers')) { 55 | $requestHeaders = apache_request_headers(); 56 | // Server-side fix for bug in old Android versions (a nice side-effect of this fix means we don't care about capitalization for Authorization) 57 | $requestHeaders = array_combine(array_map('ucwords', array_keys($requestHeaders)), array_values($requestHeaders)); 58 | //print_r($requestHeaders); 59 | if (isset($requestHeaders['Authorization'])) { 60 | $headers = trim($requestHeaders['Authorization']); 61 | } 62 | } 63 | 64 | return $headers; 65 | } 66 | 67 | function get_bearer_token() { 68 | $headers = get_authorization_header(); 69 | 70 | // HEADER: Get the access token from the header 71 | if (!empty($headers)) { 72 | if (preg_match('/Bearer\s(\S+)/', $headers, $matches)) { 73 | return $matches[1]; 74 | } 75 | } 76 | return null; 77 | } -------------------------------------------------------------------------------- /php-jwt-rest-authentication/login.php: -------------------------------------------------------------------------------- 1 | username) . "' AND password = '" . mysqli_real_escape_string($dbConn, $data->password) . "' LIMIT 1"; 18 | 19 | $result = dbQuery($sql); 20 | 21 | if(dbNumRows($result) < 1) { 22 | echo json_encode(array('error' => 'Invalid User')); 23 | } else { 24 | $row = dbFetchAssoc($result); 25 | 26 | $username = $row['username']; 27 | 28 | $headers = array('alg'=>'HS256','typ'=>'JWT'); 29 | $payload = array('username'=>$username, 'exp'=>(time() + 60)); 30 | 31 | $jwt = generate_jwt($headers, $payload); 32 | 33 | echo json_encode(array('token' => $jwt)); 34 | } 35 | } 36 | 37 | //End of file -------------------------------------------------------------------------------- /php-jwt-rest-authentication/readme.rst: -------------------------------------------------------------------------------- 1 | You can go through the tutorial https://roytuts.com/php-rest-api-authentication-using-jwt/ 2 | -------------------------------------------------------------------------------- /php-jwt-rest-authentication/register.php: -------------------------------------------------------------------------------- 1 | username) . "', '" . mysqli_real_escape_string($dbConn, $data->password) . "')"; 17 | 18 | $result = dbQuery($sql); 19 | 20 | if($result) { 21 | echo json_encode(array('success' => 'You registered successfully')); 22 | } else { 23 | echo json_encode(array('error' => 'Something went wrong, please contact administrator')); 24 | } 25 | } 26 | 27 | //End of file -------------------------------------------------------------------------------- /php-jwt-rest-authentication/user.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `user` ( 2 | `id` int NOT NULL AUTO_INCREMENT, 3 | `username` varchar(45) DEFAULT NULL, 4 | `password` varchar(255) DEFAULT NULL, 5 | PRIMARY KEY (`id`) 6 | ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 7 | 8 | insert into `user`(`username`, `password`) 9 | values (1, 'roy', 'roy'), (2, 'soumitra', 'roy'); -------------------------------------------------------------------------------- /php-jwt-rest-authentication/users.php: -------------------------------------------------------------------------------- 1 | 'Access denied')); 32 | } 33 | 34 | //End of file -------------------------------------------------------------------------------- /python-flask-rest-api-jwt-auth/app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | 3 | app = Flask(__name__) 4 | app.config['SECRET_KEY'] = 'secret-key' -------------------------------------------------------------------------------- /python-flask-rest-api-jwt-auth/db_conf.py: -------------------------------------------------------------------------------- 1 | from app import app 2 | from flaskext.mysql import MySQL 3 | 4 | mysql = MySQL() 5 | 6 | # MySQL configurations 7 | app.config['MYSQL_DATABASE_USER'] = 'root' 8 | app.config['MYSQL_DATABASE_PASSWORD'] = 'root' 9 | app.config['MYSQL_DATABASE_DB'] = 'roytuts' 10 | app.config['MYSQL_DATABASE_HOST'] = 'localhost' 11 | mysql.init_app(app) -------------------------------------------------------------------------------- /python-flask-rest-api-jwt-auth/readme.rst: -------------------------------------------------------------------------------- 1 | Please follow the tutorial https://roytuts.com/jwt-authentication-using-python-flask/ 2 | -------------------------------------------------------------------------------- /python-flask-rest-api-jwt-auth/rest.py: -------------------------------------------------------------------------------- 1 | import pymysql 2 | from app import app 3 | from db_conf import mysql 4 | from flask import jsonify 5 | from flask_jwt import JWT, jwt_required, current_identity 6 | from werkzeug.security import generate_password_hash, check_password_hash 7 | 8 | class User(object): 9 | def __init__(self, id, username): 10 | self.id = id 11 | self.username = username 12 | 13 | def __str__(self): 14 | return "User(id='%s')" % self.id 15 | 16 | @app.route('/rest-auth') 17 | @jwt_required() 18 | def get_response(): 19 | return jsonify('You are an authenticate person to see this message') 20 | 21 | def authenticate(username, password): 22 | if username and password: 23 | conn = None; 24 | cursor = None; 25 | try: 26 | conn = mysql.connect() 27 | cursor = conn.cursor(pymysql.cursors.DictCursor) 28 | cursor.execute("SELECT id, username, password FROM user WHERE username=%s", username) 29 | row = cursor.fetchone() 30 | 31 | if row: 32 | if check_password_hash(row['password'], password): 33 | return User(row['id'], row['username']) 34 | else: 35 | return None 36 | except Exception as e: 37 | print(e) 38 | finally: 39 | cursor.close() 40 | conn.close() 41 | return None 42 | 43 | def identity(payload): 44 | if payload['identity']: 45 | conn = None; 46 | cursor = None; 47 | try: 48 | conn = mysql.connect() 49 | cursor = conn.cursor(pymysql.cursors.DictCursor) 50 | cursor.execute("SELECT id, username FROM user WHERE id=%s", payload['identity']) 51 | row = cursor.fetchone() 52 | 53 | if row: 54 | return (row['id'], row['username']) 55 | else: 56 | return None 57 | except Exception as e: 58 | print(e) 59 | finally: 60 | cursor.close() 61 | conn.close() 62 | else: 63 | return None 64 | 65 | jwt = JWT(app, authenticate, identity) 66 | 67 | if __name__ == "__main__": 68 | app.run() -------------------------------------------------------------------------------- /python-flask-rest-api-jwt-auth/user.sql: -------------------------------------------------------------------------------- 1 | -- -------------------------------------------------------- 2 | -- Host: 127.0.0.1 3 | -- Server version: 8.0.17 - MySQL Community Server - GPL 4 | -- Server OS: Win64 5 | -- HeidiSQL Version: 10.2.0.5599 6 | -- -------------------------------------------------------- 7 | 8 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 9 | /*!40101 SET NAMES utf8 */; 10 | /*!50503 SET NAMES utf8mb4 */; 11 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 12 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 13 | 14 | 15 | -- Dumping database structure for roytuts 16 | CREATE DATABASE IF NOT EXISTS `roytuts` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci */ /*!80016 DEFAULT ENCRYPTION='N' */; 17 | USE `roytuts`; 18 | 19 | -- Dumping structure for table roytuts.user 20 | CREATE TABLE IF NOT EXISTS `user` ( 21 | `id` int(11) NOT NULL AUTO_INCREMENT, 22 | `username` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 23 | `password` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, 24 | PRIMARY KEY (`id`) 25 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 26 | 27 | -- Dumping data for table roytuts.user: ~0 rows (approximately) 28 | /*!40000 ALTER TABLE `user` DISABLE KEYS */; 29 | INSERT INTO `user` (`id`, `username`, `password`) VALUES 30 | (1, 'roy', 'pbkdf2:sha256:150000$k1Ud5dzh$d0347f416e89ea486b33c988c9be65730329b2dd6d712f73c9920103a006a82e'); 31 | /*!40000 ALTER TABLE `user` ENABLE KEYS */; 32 | 33 | /*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */; 34 | /*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */; 35 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 36 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | springBootVersion = '2.2.4.RELEASE' 4 | } 5 | repositories { 6 | mavenCentral() 7 | } 8 | dependencies { 9 | classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 10 | } 11 | } 12 | 13 | plugins { 14 | id 'java-library' 15 | id 'org.springframework.boot' version '2.2.4.RELEASE' 16 | } 17 | 18 | sourceCompatibility = 12 19 | targetCompatibility = 12 20 | 21 | repositories { 22 | mavenCentral() 23 | } 24 | 25 | dependencies { 26 | implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}") 27 | implementation("org.springframework.boot:spring-boot-starter-security:${springBootVersion}") 28 | implementation("org.springframework.boot:spring-boot-starter-data-jpa:${springBootVersion}") 29 | implementation("io.jsonwebtoken:jjwt:0.9.1") 30 | implementation('javax.servlet:jstl:1.2') 31 | implementation('mysql:mysql-connector-java:8.0.17') 32 | //required only if jdk 9 or higher version is used 33 | runtimeOnly('javax.xml.bind:jaxb-api:2.4.0-b180830.0359') 34 | //runtime("com.h2database:h2:1.4.196") 35 | } -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 4.0.0 7 | 8 | com.roytuts 9 | spring-security-api-auth-jwt 10 | 0.0.1-SNAPSHOT 11 | 12 | 13 | UTF-8 14 | 19 15 | 19 16 | 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-parent 21 | 3.1.4 22 | 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-web 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-security 33 | 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-starter-jdbc 38 | 39 | 40 | 41 | io.jsonwebtoken 42 | jjwt-api 43 | 0.11.5 44 | 45 | 46 | 47 | io.jsonwebtoken 48 | jjwt-jackson 49 | 0.11.5 50 | runtime 51 | 52 | 53 | 54 | io.jsonwebtoken 55 | jjwt-impl 56 | 0.11.5 57 | runtime 58 | 59 | 60 | 61 | com.mysql 62 | mysql-connector-j 63 | 64 | 65 | 66 | 67 | 68 | 69 | org.springframework.boot 70 | spring-boot-maven-plugin 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/readme.rst: -------------------------------------------------------------------------------- 1 | Please follow the tutorial https://roytuts.com/spring-security-authentication-and-role-based-authorization-using-jwt/ 2 | 3 | For spring boot 3 mainly files which are having same names with other version of spring boot will be appended with _3. 4 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/spring-jwt.sql: -------------------------------------------------------------------------------- 1 | CREATE DATABASE IF NOT EXISTS `roytuts`; 2 | USE `roytuts`; 3 | 4 | CREATE TABLE IF NOT EXISTS `user` ( 5 | `user_name` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL, 6 | `user_pass` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, 7 | `enable` tinyint(1) NOT NULL DEFAULT '1', 8 | PRIMARY KEY (`user_name`) 9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 10 | 11 | INSERT INTO `user` (`user_name`, `user_pass`, `enable`) VALUES 12 | ('admin', '$2a$10$okLy2UqGmzjecYK.8zzOrOlYv7fd6/wx7/.MwanKyn9RupY7SCtum', 1); 13 | 14 | CREATE TABLE IF NOT EXISTS `user_role` ( 15 | `user_name` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL, 16 | `user_role` varchar(15) COLLATE utf8mb4_unicode_ci NOT NULL, 17 | KEY `user_name` (`user_name`), 18 | CONSTRAINT `user_role_ibfk_1` FOREIGN KEY (`user_name`) REFERENCES `user` (`user_name`) 19 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; 20 | 21 | INSERT INTO `user_role` (`user_name`, `user_role`) VALUES 22 | ('admin', 'ROLE_USER'), 23 | ('admin', 'ROLE_ADMIN'); 24 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/SpringSecurityApiAuthJwtApp.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class SpringSecurityApiAuthJwtApp { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(SpringSecurityApiAuthJwtApp.class, args); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/config/ApiAuthenticationEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.config; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.ServletException; 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | 9 | import org.springframework.security.core.AuthenticationException; 10 | import org.springframework.security.web.AuthenticationEntryPoint; 11 | import org.springframework.stereotype.Component; 12 | 13 | @Component 14 | public class ApiAuthenticationEntryPoint implements AuthenticationEntryPoint { 15 | 16 | @Override 17 | public void commence(HttpServletRequest request, HttpServletResponse response, 18 | AuthenticationException authException) throws IOException, ServletException { 19 | response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/config/ApiAuthenticationEntryPoint.java_3: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.config; 2 | 3 | import java.io.IOException; 4 | 5 | import org.springframework.security.core.AuthenticationException; 6 | import org.springframework.security.web.AuthenticationEntryPoint; 7 | import org.springframework.stereotype.Component; 8 | 9 | import jakarta.servlet.ServletException; 10 | import jakarta.servlet.http.HttpServletRequest; 11 | import jakarta.servlet.http.HttpServletResponse; 12 | 13 | @Component 14 | public class ApiAuthenticationEntryPoint implements AuthenticationEntryPoint { 15 | 16 | @Override 17 | public void commence(HttpServletRequest request, HttpServletResponse response, 18 | AuthenticationException authException) throws IOException, ServletException { 19 | response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException.getMessage()); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/config/ApiSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 5 | import org.springframework.boot.web.servlet.RegistrationBean; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.security.authentication.AuthenticationManager; 9 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 10 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 11 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 12 | import org.springframework.security.config.annotation.web.builders.WebSecurity; 13 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 14 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 15 | import org.springframework.security.config.http.SessionCreationPolicy; 16 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 17 | import org.springframework.security.crypto.password.PasswordEncoder; 18 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 19 | 20 | import com.roytuts.spring.security.api.auth.jwt.filter.JwtAuthenticationFilter; 21 | import com.roytuts.spring.security.api.auth.jwt.service.UserAuthService; 22 | 23 | @Configuration 24 | @EnableWebSecurity 25 | @EnableGlobalMethodSecurity(prePostEnabled = true) 26 | public class ApiSecurityConfig extends WebSecurityConfigurerAdapter { 27 | 28 | @Autowired 29 | private UserAuthService userAuthService; 30 | 31 | @Autowired 32 | private JwtAuthenticationFilter jwtAuthenticationFilter; 33 | 34 | @Autowired 35 | private ApiAuthenticationEntryPoint authenticationEntryPoint; 36 | 37 | @Override 38 | public void configure(WebSecurity web) throws Exception { 39 | web.ignoring().antMatchers("/signin", "/signup"); 40 | } 41 | 42 | @Autowired 43 | public void configure(AuthenticationManagerBuilder auth) throws Exception { 44 | auth.userDetailsService(userAuthService).passwordEncoder(passwordEncoder()); 45 | } 46 | 47 | @Override 48 | protected void configure(HttpSecurity http) throws Exception { 49 | http.csrf().disable().authorizeRequests().antMatchers("/signin", "/signup").permitAll().anyRequest() 50 | .authenticated().and().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and() 51 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); 52 | http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); 53 | } 54 | 55 | @Bean 56 | public RegistrationBean jwtAuthFilterRegister(JwtAuthenticationFilter filter) { 57 | FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(filter); 58 | registrationBean.setEnabled(false); 59 | return registrationBean; 60 | } 61 | 62 | @Bean 63 | @Override 64 | public AuthenticationManager authenticationManagerBean() throws Exception { 65 | return super.authenticationManagerBean(); 66 | } 67 | 68 | @Bean 69 | public PasswordEncoder passwordEncoder() { 70 | return new BCryptPasswordEncoder(); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/config/ApiSecurityConfig.java_3: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.config; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.security.authentication.AuthenticationManager; 7 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 8 | import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 | import org.springframework.security.config.http.SessionCreationPolicy; 11 | import org.springframework.security.crypto.password.PasswordEncoder; 12 | import org.springframework.security.web.SecurityFilterChain; 13 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; 14 | 15 | import com.roytuts.spring.security.api.auth.jwt.filter.JwtAuthenticationFilter; 16 | import com.roytuts.spring.security.api.auth.jwt.service.UserAuthService; 17 | 18 | @Configuration 19 | public class ApiSecurityConfig { 20 | 21 | @Autowired 22 | private PasswordEncoder passwordEncoder; 23 | 24 | @Autowired 25 | private UserAuthService userAuthService; 26 | 27 | @Autowired 28 | private JwtAuthenticationFilter jwtAuthenticationFilter; 29 | 30 | @Autowired 31 | private ApiAuthenticationEntryPoint authenticationEntryPoint; 32 | 33 | @Autowired 34 | public void configure(AuthenticationManagerBuilder auth) throws Exception { 35 | auth.userDetailsService(userAuthService).passwordEncoder(passwordEncoder); 36 | } 37 | 38 | @Bean 39 | public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { 40 | http.csrf(csrf -> csrf.disable()); 41 | 42 | http.authorizeHttpRequests( 43 | auth -> auth.requestMatchers("/signin", "/signup").permitAll().anyRequest().authenticated()); 44 | 45 | http.exceptionHandling(ex -> ex.authenticationEntryPoint(authenticationEntryPoint)); 46 | 47 | http.sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); 48 | 49 | http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); 50 | 51 | return http.build(); 52 | } 53 | 54 | @Bean 55 | public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) 56 | throws Exception { 57 | return authenticationConfiguration.getAuthenticationManager(); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/config/DatabaseConfig.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.config; 2 | 3 | import javax.sql.DataSource; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.core.env.Environment; 9 | import org.springframework.jdbc.core.JdbcTemplate; 10 | import org.springframework.jdbc.datasource.DriverManagerDataSource; 11 | 12 | @Configuration 13 | public class DatabaseConfig { 14 | 15 | @Autowired 16 | private Environment environment; 17 | 18 | /*@Bean 19 | public DataSource dataSource() { 20 | EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); 21 | EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.H2) // .H2 or .DERBY, etc. 22 | .addScript("user.sql").addScript("user-role.sql").build(); 23 | return db; 24 | }*/ 25 | 26 | @Bean 27 | public DataSource dataSource() { 28 | DriverManagerDataSource dataSource = new DriverManagerDataSource(); 29 | 30 | dataSource.setDriverClassName(environment.getProperty("jdbc.driverClassName")); 31 | dataSource.setUrl(environment.getProperty("jdbc.url")); 32 | dataSource.setUsername(environment.getProperty("jdbc.username")); 33 | dataSource.setPassword(environment.getProperty("jdbc.password")); 34 | 35 | return dataSource; 36 | } 37 | 38 | @Bean 39 | public JdbcTemplate getJdbcTemplate() throws ClassNotFoundException { 40 | JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource()); 41 | return jdbcTemplate; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/config/EncoderConfig.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 6 | import org.springframework.security.crypto.password.PasswordEncoder; 7 | 8 | @Configuration 9 | public class EncoderConfig { 10 | 11 | @Bean 12 | public PasswordEncoder passwordEncoder() { 13 | return new BCryptPasswordEncoder(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/dao/UserDao.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.dao; 2 | 3 | import java.sql.Connection; 4 | import java.sql.PreparedStatement; 5 | import java.sql.SQLException; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.stream.Collectors; 9 | 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.jdbc.core.JdbcTemplate; 12 | import org.springframework.jdbc.core.PreparedStatementCreator; 13 | import org.springframework.stereotype.Repository; 14 | 15 | import com.roytuts.spring.security.api.auth.jwt.model.Role; 16 | import com.roytuts.spring.security.api.auth.jwt.model.User; 17 | import com.roytuts.spring.security.api.auth.jwt.model.UserRole; 18 | import com.roytuts.spring.security.api.auth.jwt.rowmapper.UserRowMapper; 19 | 20 | @Repository 21 | public class UserDao { 22 | 23 | @Autowired 24 | private JdbcTemplate jdbcTemplate; 25 | 26 | public User getUser(String username) { 27 | return jdbcTemplate.queryForObject("select user_name, user_pass from user where user_name = ?", 28 | new Object[] { username }, new UserRowMapper()); 29 | } 30 | 31 | public List getRoles(String username) { 32 | List> results = jdbcTemplate 33 | .queryForList("select user_role from user_role where user_name = ?", new Object[] { username }); 34 | List roles = results.stream().map(m -> { 35 | Role role = new Role(); 36 | role.setRole(String.valueOf(m.get("user_role"))); 37 | return role; 38 | }).collect(Collectors.toList()); 39 | return roles; 40 | } 41 | 42 | public void saveUser(UserRole user) { 43 | jdbcTemplate.update("insert into user(user_name, user_pass) values(?, ?)", 44 | new Object[] { user.getUsername(), user.getUserpwd() }); 45 | user.getRoles().forEach(r -> jdbcTemplate.update(new PreparedStatementCreator() { 46 | public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { 47 | PreparedStatement ps = connection.prepareStatement( 48 | "insert into user_role(user_name, user_role) values(?, ?)", 49 | new String[] { "user_name", "user_role" }); 50 | ps.setString(1, user.getUsername()); 51 | ps.setString(2, r); 52 | return ps; 53 | } 54 | })); 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/dao/UserDao.java_3: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.dao; 2 | 3 | import java.sql.Connection; 4 | import java.sql.PreparedStatement; 5 | import java.sql.SQLException; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.stream.Collectors; 9 | 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.jdbc.core.JdbcTemplate; 12 | import org.springframework.jdbc.core.PreparedStatementCreator; 13 | import org.springframework.stereotype.Repository; 14 | 15 | import com.roytuts.spring.security.api.auth.jwt.model.Role; 16 | import com.roytuts.spring.security.api.auth.jwt.model.User; 17 | import com.roytuts.spring.security.api.auth.jwt.model.UserRole; 18 | import com.roytuts.spring.security.api.auth.jwt.rowmapper.UserRowMapper; 19 | 20 | @Repository 21 | public class UserDao { 22 | 23 | @Autowired 24 | private JdbcTemplate jdbcTemplate; 25 | 26 | public User getUser(String username) { 27 | List users = jdbcTemplate.query("select user_name, user_pass from user where user_name = ?", 28 | new UserRowMapper(), new Object[] { username }); 29 | 30 | if (users.isEmpty()) { 31 | return null; 32 | } 33 | 34 | return users.get(0); 35 | } 36 | 37 | public List getRoles(String username) { 38 | List> results = jdbcTemplate 39 | .queryForList("select user_role from user_role where user_name = ?", new Object[] { username }); 40 | 41 | List roles = results.stream().map(m -> { 42 | Role role = new Role(); 43 | role.setRole(String.valueOf(m.get("user_role"))); 44 | return role; 45 | }).collect(Collectors.toList()); 46 | 47 | return roles; 48 | } 49 | 50 | public void saveUser(UserRole user) { 51 | jdbcTemplate.update("insert into user(user_name, user_pass) values(?, ?)", 52 | new Object[] { user.getUsername(), user.getUserpwd() }); 53 | 54 | user.getRoles().forEach(r -> jdbcTemplate.update(new PreparedStatementCreator() { 55 | public PreparedStatement createPreparedStatement(Connection connection) throws SQLException { 56 | PreparedStatement ps = connection.prepareStatement( 57 | "insert into user_role(user_name, user_role) values(?, ?)", 58 | new String[] { "user_name", "user_role" }); 59 | ps.setString(1, user.getUsername()); 60 | ps.setString(2, r); 61 | return ps; 62 | } 63 | })); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/exception/DisabledUserException.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.exception; 2 | 3 | public class DisabledUserException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 1L; 6 | 7 | public DisabledUserException(String msg) { 8 | super(msg); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/exception/InvalidUserCredentialsException.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.exception; 2 | 3 | public class InvalidUserCredentialsException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 1L; 6 | 7 | public InvalidUserCredentialsException(String msg) { 8 | super(msg); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/exception/JwtTokenMalformedException.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.exception; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | 5 | public class JwtTokenMalformedException extends AuthenticationException { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | public JwtTokenMalformedException(String msg) { 10 | super(msg); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/exception/JwtTokenMissingException.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.exception; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | 5 | public class JwtTokenMissingException extends AuthenticationException { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | public JwtTokenMissingException(String msg) { 10 | super(msg); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/filter/JwtAuthenticationFilter.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.filter; 2 | 3 | import java.io.IOException; 4 | 5 | import javax.servlet.FilterChain; 6 | import javax.servlet.ServletException; 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 12 | import org.springframework.security.core.context.SecurityContextHolder; 13 | import org.springframework.security.core.userdetails.UserDetails; 14 | import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; 15 | import org.springframework.stereotype.Component; 16 | import org.springframework.web.filter.OncePerRequestFilter; 17 | 18 | import com.roytuts.spring.security.api.auth.jwt.exception.JwtTokenMissingException; 19 | import com.roytuts.spring.security.api.auth.jwt.service.UserAuthService; 20 | import com.roytuts.spring.security.api.auth.jwt.util.JwtUtil; 21 | import com.roytuts.spring.security.api.auth.jwt.vo.UserVo; 22 | 23 | @Component 24 | public class JwtAuthenticationFilter extends OncePerRequestFilter { 25 | 26 | @Autowired 27 | private JwtUtil jwtUtil; 28 | 29 | @Autowired 30 | private UserAuthService userAuthService; 31 | 32 | @Override 33 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 34 | throws ServletException, IOException { 35 | 36 | String header = request.getHeader("Authorization"); 37 | 38 | if (header == null || !header.startsWith("Bearer")) { 39 | throw new JwtTokenMissingException("No JWT token found in the request headers"); 40 | } 41 | 42 | String token = header.substring(7); 43 | 44 | // Optional - verification 45 | jwtUtil.validateToken(token); 46 | 47 | UserVo userVo = jwtUtil.getUser(token); 48 | 49 | UserDetails userDetails = userAuthService.loadUserByUsername(userVo.getUsername()); 50 | 51 | UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken( 52 | userDetails, null, userDetails.getAuthorities()); 53 | 54 | usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); 55 | 56 | if (SecurityContextHolder.getContext().getAuthentication() == null) { 57 | SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); 58 | } 59 | 60 | filterChain.doFilter(request, response); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/filter/JwtAuthenticationFilter.java_3: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.filter; 2 | 3 | import java.io.IOException; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.http.HttpHeaders; 7 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 8 | import org.springframework.security.core.context.SecurityContextHolder; 9 | import org.springframework.security.core.userdetails.UserDetails; 10 | import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; 11 | import org.springframework.stereotype.Component; 12 | import org.springframework.web.filter.OncePerRequestFilter; 13 | 14 | import com.roytuts.spring.security.api.auth.jwt.service.UserAuthService; 15 | import com.roytuts.spring.security.api.auth.jwt.util.JwtUtil; 16 | import com.roytuts.spring.security.api.auth.jwt.vo.UserVo; 17 | 18 | import jakarta.servlet.FilterChain; 19 | import jakarta.servlet.ServletException; 20 | import jakarta.servlet.http.HttpServletRequest; 21 | import jakarta.servlet.http.HttpServletResponse; 22 | 23 | @Component 24 | public class JwtAuthenticationFilter extends OncePerRequestFilter { 25 | 26 | @Autowired 27 | private JwtUtil jwtUtil; 28 | 29 | @Autowired 30 | private UserAuthService userAuthService; 31 | 32 | @Override 33 | protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 34 | throws ServletException, IOException { 35 | String header = request.getHeader(HttpHeaders.AUTHORIZATION); 36 | 37 | if (header == null || !header.startsWith("Bearer")) { 38 | filterChain.doFilter(request, response); 39 | return; 40 | } 41 | 42 | final String token = header.split(" ")[1].trim();// header.substring(7); 43 | 44 | if (!jwtUtil.validateToken(token)) { 45 | filterChain.doFilter(request, response); 46 | return; 47 | } 48 | 49 | UserVo userVo = jwtUtil.getUser(token); 50 | 51 | UserDetails userDetails = userAuthService.loadUserByUsername(userVo.getUsername()); 52 | 53 | UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken( 54 | userDetails, null, userDetails.getAuthorities()); 55 | 56 | usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); 57 | 58 | SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); 59 | 60 | filterChain.doFilter(request, response); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/model/Role.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.model; 2 | 3 | public class Role { 4 | 5 | private String role; 6 | 7 | public String getRole() { 8 | return role; 9 | } 10 | 11 | public void setRole(String role) { 12 | this.role = role; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/model/User.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.model; 2 | 3 | public class User { 4 | 5 | private String username; 6 | private String userpwd; 7 | 8 | public String getUsername() { 9 | return username; 10 | } 11 | 12 | public void setUsername(String username) { 13 | this.username = username; 14 | } 15 | 16 | public String getUserpwd() { 17 | return userpwd; 18 | } 19 | 20 | public void setUserpwd(String userpwd) { 21 | this.userpwd = userpwd; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/model/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.model; 2 | 3 | import java.util.Set; 4 | 5 | public class UserRole { 6 | 7 | private String username; 8 | private String userpwd; 9 | private Set roles; 10 | 11 | public String getUsername() { 12 | return username; 13 | } 14 | 15 | public void setUsername(String username) { 16 | this.username = username; 17 | } 18 | 19 | public String getUserpwd() { 20 | return userpwd; 21 | } 22 | 23 | public void setUserpwd(String userpwd) { 24 | this.userpwd = userpwd; 25 | } 26 | 27 | public Set getRoles() { 28 | return roles; 29 | } 30 | 31 | public void setRoles(Set roles) { 32 | this.roles = roles; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/rest/controller/ApiRestController.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.rest.controller; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.http.ResponseEntity; 5 | import org.springframework.security.access.prepost.PreAuthorize; 6 | import org.springframework.web.bind.annotation.GetMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | @RestController 10 | public class ApiRestController { 11 | 12 | @PreAuthorize("hasRole('USER')") 13 | @GetMapping("/greet/user") 14 | public ResponseEntity greetingUser() { 15 | return new ResponseEntity("Welcome, you have USER role", HttpStatus.OK); 16 | } 17 | 18 | @PreAuthorize("hasRole('ADMIN')") 19 | @GetMapping("/greet/admin") 20 | public ResponseEntity greetingAdmin() { 21 | return new ResponseEntity("Welcome, you have ADMIN role", HttpStatus.OK); 22 | } 23 | 24 | @PreAuthorize("hasRole('USER') or hasRole('ADMIN')") 25 | @GetMapping("/greet/userOrAdmin") 26 | public ResponseEntity greetingUserOrAdmin() { 27 | return new ResponseEntity("Welcome, you have USER and ADMIN role", HttpStatus.OK); 28 | } 29 | 30 | @PreAuthorize("hasRole('ANONYMOUS')") 31 | @GetMapping("/greet/anonymous") 32 | public ResponseEntity greetingAnonymous() { 33 | return new ResponseEntity("Welcome, you have USER and ADMIN role", HttpStatus.OK); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/rest/controller/JwtRestController.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.rest.controller; 2 | 3 | import java.util.Set; 4 | import java.util.stream.Collectors; 5 | 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.http.ResponseEntity; 9 | import org.springframework.security.authentication.AuthenticationManager; 10 | import org.springframework.security.authentication.BadCredentialsException; 11 | import org.springframework.security.authentication.DisabledException; 12 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 13 | import org.springframework.security.core.userdetails.UserDetails; 14 | import org.springframework.web.bind.annotation.PostMapping; 15 | import org.springframework.web.bind.annotation.RequestBody; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | import com.roytuts.spring.security.api.auth.jwt.exception.DisabledUserException; 19 | import com.roytuts.spring.security.api.auth.jwt.exception.InvalidUserCredentialsException; 20 | import com.roytuts.spring.security.api.auth.jwt.service.UserAuthService; 21 | import com.roytuts.spring.security.api.auth.jwt.util.JwtUtil; 22 | import com.roytuts.spring.security.api.auth.jwt.vo.JwtRequest; 23 | import com.roytuts.spring.security.api.auth.jwt.vo.JwtResponse; 24 | import com.roytuts.spring.security.api.auth.jwt.vo.UserVo; 25 | 26 | @RestController 27 | public class JwtRestController { 28 | 29 | @Autowired 30 | private JwtUtil jwtUtil; 31 | 32 | @Autowired 33 | private UserAuthService userAuthService; 34 | 35 | @Autowired 36 | private AuthenticationManager authenticationManager; 37 | 38 | @PostMapping("/signin") 39 | public ResponseEntity generateJwtToken(@RequestBody JwtRequest jwtRequest) { 40 | try { 41 | authenticationManager.authenticate( 42 | new UsernamePasswordAuthenticationToken(jwtRequest.getUsername(), jwtRequest.getUserpwd())); 43 | } catch (DisabledException e) { 44 | throw new DisabledUserException("User Inactive"); 45 | } catch (BadCredentialsException e) { 46 | throw new InvalidUserCredentialsException("Invalid Credentials"); 47 | } 48 | UserDetails userDetails = userAuthService.loadUserByUsername(jwtRequest.getUsername()); 49 | String username = userDetails.getUsername(); 50 | String userpwd = userDetails.getPassword(); 51 | Set roles = userDetails.getAuthorities().stream().map(r -> r.getAuthority()) 52 | .collect(Collectors.toSet()); 53 | UserVo user = new UserVo(); 54 | user.setUsername(username); 55 | user.setUserpwd(userpwd); 56 | user.setRoles(roles); 57 | String token = jwtUtil.generateToken(user); 58 | return new ResponseEntity(new JwtResponse(token), HttpStatus.OK); 59 | } 60 | 61 | @PostMapping("/signup") 62 | public ResponseEntity signup(@RequestBody UserVo userVo) { 63 | UserVo u = userAuthService.getUserByUsername(userVo.getUsername()); 64 | 65 | if (u == null) { 66 | userAuthService.saveUser(userVo); 67 | return new ResponseEntity("User successfully registered", HttpStatus.OK); 68 | } else { 69 | return new ResponseEntity("User already exists", HttpStatus.CONFLICT); 70 | } 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/rowmapper/UserRowMapper.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.rowmapper; 2 | 3 | import java.sql.ResultSet; 4 | import java.sql.SQLException; 5 | 6 | import org.springframework.jdbc.core.RowMapper; 7 | 8 | import com.roytuts.spring.security.api.auth.jwt.model.User; 9 | 10 | public class UserRowMapper implements RowMapper { 11 | 12 | @Override 13 | public User mapRow(ResultSet rs, int rowNum) throws SQLException { 14 | User user = new User(); 15 | user.setUsername(rs.getString("user_name")); 16 | user.setUserpwd(rs.getString("user_pass")); 17 | return user; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/service/UserAuthService.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.service; 2 | 3 | import java.util.List; 4 | import java.util.Set; 5 | import java.util.stream.Collectors; 6 | 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.security.core.GrantedAuthority; 9 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 10 | import org.springframework.security.core.userdetails.UserDetails; 11 | import org.springframework.security.core.userdetails.UserDetailsService; 12 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 13 | import org.springframework.security.crypto.password.PasswordEncoder; 14 | import org.springframework.stereotype.Service; 15 | 16 | import com.roytuts.spring.security.api.auth.jwt.dao.UserDao; 17 | import com.roytuts.spring.security.api.auth.jwt.model.Role; 18 | import com.roytuts.spring.security.api.auth.jwt.model.User; 19 | import com.roytuts.spring.security.api.auth.jwt.model.UserRole; 20 | import com.roytuts.spring.security.api.auth.jwt.vo.UserVo; 21 | 22 | @Service 23 | public class UserAuthService implements UserDetailsService { 24 | 25 | @Autowired 26 | private UserDao userDao; 27 | 28 | @Autowired 29 | private PasswordEncoder passwordEncoder; 30 | 31 | @Override 32 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 33 | User user = userDao.getUser(username); 34 | if (user == null) { 35 | throw new UsernameNotFoundException("User '" + username + "' not found."); 36 | } 37 | List roles = userDao.getRoles(username); 38 | List grantedAuthorities = roles.stream().map(r -> { 39 | return new SimpleGrantedAuthority(r.getRole()); 40 | }).collect(Collectors.toList()); 41 | return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getUserpwd(), 42 | grantedAuthorities); 43 | } 44 | 45 | public UserVo getUserByUsername(String username) { 46 | User user = userDao.getUser(username); 47 | 48 | if (user != null) { 49 | 50 | List roles = userDao.getRoles(username); 51 | 52 | Set rls = roles.stream().map(r -> r.getRole()).collect(Collectors.toSet()); 53 | 54 | UserVo userVo = new UserVo(); 55 | userVo.setUsername(user.getUsername()); 56 | userVo.setUserpwd(user.getUserpwd()); 57 | userVo.setRoles(rls); 58 | 59 | return userVo; 60 | } 61 | 62 | return null; 63 | } 64 | 65 | public void saveUser(UserVo userVo) { 66 | UserRole user = new UserRole(); 67 | user.setUsername(userVo.getUsername()); 68 | user.setUserpwd(passwordEncoder.encode(userVo.getUserpwd())); 69 | user.setRoles(userVo.getRoles()); 70 | userDao.saveUser(user); 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/util/JwtUtil.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.util; 2 | 3 | import java.util.Arrays; 4 | import java.util.Date; 5 | import java.util.Set; 6 | import java.util.stream.Collectors; 7 | 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.stereotype.Component; 10 | 11 | import com.roytuts.spring.security.api.auth.jwt.exception.JwtTokenMalformedException; 12 | import com.roytuts.spring.security.api.auth.jwt.exception.JwtTokenMissingException; 13 | import com.roytuts.spring.security.api.auth.jwt.vo.UserVo; 14 | 15 | import io.jsonwebtoken.Claims; 16 | import io.jsonwebtoken.ExpiredJwtException; 17 | import io.jsonwebtoken.Jwts; 18 | import io.jsonwebtoken.MalformedJwtException; 19 | import io.jsonwebtoken.SignatureAlgorithm; 20 | import io.jsonwebtoken.SignatureException; 21 | import io.jsonwebtoken.UnsupportedJwtException; 22 | 23 | @Component 24 | public class JwtUtil { 25 | 26 | @Value("${jwt.secret}") 27 | private String jwtSecret; 28 | 29 | @Value("${jwt.token.validity}") 30 | private long tokenValidity; 31 | 32 | public UserVo getUser(final String token) { 33 | try { 34 | Claims body = Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody(); 35 | UserVo user = new UserVo(); 36 | user.setUsername(body.getSubject()); 37 | Set roles = Arrays.asList(body.get("roles").toString().split(",")).stream().map(r -> new String(r)) 38 | .collect(Collectors.toSet()); 39 | user.setRoles(roles); 40 | return user; 41 | } catch (Exception e) { 42 | System.out.println(e.getMessage() + " => " + e); 43 | } 44 | return null; 45 | } 46 | 47 | public String generateToken(UserVo u) { 48 | Claims claims = Jwts.claims().setSubject(u.getUsername()); 49 | claims.put("roles", u.getRoles()); 50 | long nowMillis = System.currentTimeMillis(); 51 | long expMillis = nowMillis + tokenValidity; 52 | Date exp = new Date(expMillis); 53 | return Jwts.builder().setClaims(claims).setIssuedAt(new Date(nowMillis)).setExpiration(exp) 54 | .signWith(SignatureAlgorithm.HS512, jwtSecret).compact(); 55 | } 56 | 57 | public void validateToken(final String token) { 58 | try { 59 | Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token); 60 | } catch (SignatureException ex) { 61 | throw new JwtTokenMalformedException("Invalid JWT signature"); 62 | } catch (MalformedJwtException ex) { 63 | throw new JwtTokenMalformedException("Invalid JWT token"); 64 | } catch (ExpiredJwtException ex) { 65 | throw new JwtTokenMalformedException("Expired JWT token"); 66 | } catch (UnsupportedJwtException ex) { 67 | throw new JwtTokenMalformedException("Unsupported JWT token"); 68 | } catch (IllegalArgumentException ex) { 69 | throw new JwtTokenMissingException("JWT claims string is empty."); 70 | } 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/util/JwtUtil.java_3: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.util; 2 | 3 | import java.security.Key; 4 | import java.util.Arrays; 5 | import java.util.Date; 6 | import java.util.Set; 7 | import java.util.stream.Collectors; 8 | 9 | import org.springframework.stereotype.Component; 10 | 11 | import com.roytuts.spring.security.api.auth.jwt.vo.UserVo; 12 | 13 | import io.jsonwebtoken.Claims; 14 | import io.jsonwebtoken.Jwts; 15 | import io.jsonwebtoken.SignatureAlgorithm; 16 | import io.jsonwebtoken.io.Decoders; 17 | import io.jsonwebtoken.security.Keys; 18 | import io.jsonwebtoken.security.SignatureException; 19 | 20 | @Component 21 | public class JwtUtil { 22 | 23 | public UserVo getUser(final String token) { 24 | try { 25 | Claims body = Jwts.parserBuilder().setSigningKey(key()).build().parseClaimsJws(token).getBody(); 26 | 27 | UserVo user = new UserVo(); 28 | user.setUsername(body.getSubject()); 29 | 30 | Set roles = Arrays.asList(body.get("roles").toString().split(",")).stream().map(r -> new String(r)) 31 | .collect(Collectors.toSet()); 32 | user.setRoles(roles); 33 | 34 | return user; 35 | } catch (Exception e) { 36 | System.out.println(e.getMessage() + " => " + e); 37 | } 38 | return null; 39 | } 40 | 41 | public String generateToken(UserVo u) { 42 | Claims claims = Jwts.claims().setSubject(u.getUsername()); 43 | claims.put("roles", u.getRoles()); 44 | long nowMillis = System.currentTimeMillis(); 45 | long expMillis = nowMillis + 180000; 46 | Date exp = new Date(expMillis); 47 | return Jwts.builder().setClaims(claims).setIssuedAt(new Date(nowMillis)).setExpiration(exp) 48 | .signWith(key(), SignatureAlgorithm.HS256).compact(); 49 | } 50 | 51 | public boolean validateToken(final String token) { 52 | try { 53 | Jwts.parserBuilder().setSigningKey(key()).build().parse(token); 54 | } catch (SignatureException ex) { 55 | return false; 56 | } 57 | 58 | return true; 59 | } 60 | 61 | private Key key() { 62 | return Keys.hmacShaKeyFor(Decoders.BASE64.decode("jwtsecretkeyshouldbelongenoughatleast256bits")); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/vo/JwtRequest.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.vo; 2 | 3 | public class JwtRequest { 4 | 5 | private String username; 6 | private String userpwd; 7 | 8 | public String getUsername() { 9 | return username; 10 | } 11 | 12 | public void setUsername(String username) { 13 | this.username = username; 14 | } 15 | 16 | public String getUserpwd() { 17 | return userpwd; 18 | } 19 | 20 | public void setUserpwd(String userpwd) { 21 | this.userpwd = userpwd; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/vo/JwtResponse.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.vo; 2 | 3 | public class JwtResponse { 4 | 5 | private String token; 6 | 7 | public JwtResponse(String token) { 8 | this.token = token; 9 | } 10 | 11 | public String getToken() { 12 | return token; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/java/com/roytuts/spring/security/api/auth/jwt/vo/UserVo.java: -------------------------------------------------------------------------------- 1 | package com.roytuts.spring.security.api.auth.jwt.vo; 2 | 3 | import java.util.Set; 4 | 5 | public class UserVo { 6 | 7 | private String username; 8 | private String userpwd; 9 | private Set roles; 10 | 11 | public String getUsername() { 12 | return username; 13 | } 14 | 15 | public void setUsername(String username) { 16 | this.username = username; 17 | } 18 | 19 | public String getUserpwd() { 20 | return userpwd; 21 | } 22 | 23 | public void setUserpwd(String userpwd) { 24 | this.userpwd = userpwd; 25 | } 26 | 27 | public Set getRoles() { 28 | return roles; 29 | } 30 | 31 | public void setRoles(Set roles) { 32 | this.roles = roles; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | #datasource 2 | jdbc.driverClassName=com.mysql.cj.jdbc.Driver 3 | jdbc.url=jdbc:mysql://localhost:3306/roytuts 4 | jdbc.username=root 5 | jdbc.password=root 6 | 7 | #secret key - should be encrypted 8 | jwt.secret=secretkey 9 | #3 minutes validity 10 | jwt.token.validity=180000 11 | #ignore null fields in json 12 | spring.jackson.default-property-inclusion=NON_NULL -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/resources/application.properties_3: -------------------------------------------------------------------------------- 1 | spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver 2 | spring.datasource.url=jdbc:mysql://localhost:3306/roytuts 3 | spring.datasource.username=root 4 | spring.datasource.password=root 5 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/resources/user-role.sql: -------------------------------------------------------------------------------- 1 | /*Table structure for table `user_role` */ 2 | 3 | DROP TABLE IF EXISTS `user_role`; 4 | 5 | CREATE TABLE `user_role` ( 6 | `user_name` varchar(30) NOT NULL, 7 | `user_role` varchar(15) NOT NULL, 8 | FOREIGN KEY (`user_name`) REFERENCES `user` (`user_name`) 9 | ); 10 | -------------------------------------------------------------------------------- /spring-security-api-auth-jwt/src/main/resources/user.sql: -------------------------------------------------------------------------------- 1 | /*Table structure for table `user` */ 2 | 3 | DROP TABLE IF EXISTS `user`; 4 | 5 | CREATE TABLE `user` ( 6 | `user_name` varchar(30) NOT NULL, 7 | `user_pass` varchar(255) NOT NULL, 8 | `enable` tinyint(1) NOT NULL DEFAULT '1', 9 | PRIMARY KEY (`user_name`) 10 | ); 11 | --------------------------------------------------------------------------------