diff --git a/MySQL_conf_pbx/test1/Rest-API-Postman/CezenPBX_API.postman_collection_Security.json b/MySQL_conf_pbx/test1/Rest-API-Postman/CezenPBX_API.postman_collection_Security.json new file mode 100644 index 0000000..934f22d --- /dev/null +++ b/MySQL_conf_pbx/test1/Rest-API-Postman/CezenPBX_API.postman_collection_Security.json @@ -0,0 +1,204 @@ +{ + "info": { + "_postman_id": "721d5504-301f-488d-a25b-5e78769eac5a", + "name": "CezenPBX_API", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "29498098" + }, + "item": [ + { + "name": "create a new endpoint", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"id\": \"1005\",\n// \"transport\": \"transport-udp\",\n// \"context\": \"default\",\n// \"disallow\": \"all\",\n// \"allow\": \"ulaw,alaw\",\n// \"directMedia\": \"no\",\n \"connectedLineMethod\": null,\n \"callerid\": null,\n \"dtmfMode\": null,\n// \"mohsuggest\": \"default\",\n \"mailboxes\": null\n}\n\n// {\n// \"id\": \"1004\",\n// \"transport\": \"transport-udp\",\n// \"aors\": \"1004\",\n// \"auth\": \"1004\",\n// \"context\": \"default\",\n// \"disallow\": \"all\",\n// \"allow\": \"ulaw,alaw\",\n// \"directMedia\": \"no\",\n// \"connectedLineMethod\": null,\n// \"callerid\": \"User <1004>\",\n// \"dtmfMode\": null,\n// \"mohsuggest\": \"default\",\n// \"mailboxes\": \"1004@default\"\n// }", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8081/cezen/add_user", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8081", + "path": [ + "cezen", + "add_user" + ] + } + }, + "response": [] + }, + { + "name": "create a new extension", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"context\": \"default\",\n \"extension\": \"1005\",\n \"priority\": 1,\n \"app\": \"Dial\",\n \"appdata\": \"PJSIP/1005,20,m(default)\"\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8081/cezen/add_extension", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8081", + "path": [ + "cezen", + "add_extension" + ] + } + }, + "response": [] + }, + { + "name": "set_password", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"id\": \"1005\",\n \"authType\": \"userpass\",\n \"userName\": \"1005\",\n \"password\": \"12345\",\n \"md5Cred\": null,\n \"realm\": null\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8081/cezen/set_password", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8081", + "path": [ + "cezen", + "set_password" + ] + } + }, + "response": [] + }, + { + "name": "SetAORS", + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"id\": \"1005\",\n \"maxContacts\": 1\n}", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8081/cezen/set_aors", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8081", + "path": [ + "cezen", + "set_aors" + ] + } + }, + "response": [] + }, + { + "name": "DeleteExtension", + "request": { + "method": "DELETE", + "header": [], + "url": { + "raw": "http://localhost:8081/cezen/delete_extension?sipNumber=testEndPoint", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8081", + "path": [ + "cezen", + "delete_extension" + ], + "query": [ + { + "key": "sipNumber", + "value": "testEndPoint" + } + ] + } + }, + "response": [] + }, + { + "name": "Add_a_global_extension_feature", + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"context\": \"default\",\n \"extension\": \"w\",\n \"priority\": 5,\n \"app\": \"Dial\",\n \"appdata\": \"W conf\"\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "http://localhost:8081/cezen/add_feature", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8081", + "path": [ + "cezen", + "add_feature" + ] + } + }, + "response": [] + }, + { + "name": "login", + "request": { + "auth": { + "type": "noauth" + }, + "method": "POST", + "header": [], + "url": { + "raw": "http://localhost:8081/open/signup", + "protocol": "http", + "host": [ + "localhost" + ], + "port": "8081", + "path": [ + "open", + "signup" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/MySQL_conf_pbx/test1/mariadb_data/aria_log.00000001 b/MySQL_conf_pbx/test1/mariadb_data/aria_log.00000001 index 8b58be4..8cd7a25 100644 Binary files a/MySQL_conf_pbx/test1/mariadb_data/aria_log.00000001 and b/MySQL_conf_pbx/test1/mariadb_data/aria_log.00000001 differ diff --git a/MySQL_conf_pbx/test1/mariadb_data/aria_log_control b/MySQL_conf_pbx/test1/mariadb_data/aria_log_control index e0a15ce..9ceb1c7 100644 Binary files a/MySQL_conf_pbx/test1/mariadb_data/aria_log_control and b/MySQL_conf_pbx/test1/mariadb_data/aria_log_control differ diff --git a/MySQL_conf_pbx/test1/mariadb_data/asterisk_db/roles.ibd b/MySQL_conf_pbx/test1/mariadb_data/asterisk_db/roles.ibd index 8b3f545..aebdf9d 100644 Binary files a/MySQL_conf_pbx/test1/mariadb_data/asterisk_db/roles.ibd and b/MySQL_conf_pbx/test1/mariadb_data/asterisk_db/roles.ibd differ diff --git a/MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user.ibd b/MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user.ibd index 8b3f545..176e67e 100644 Binary files a/MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user.ibd and b/MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user.ibd differ diff --git a/MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user_roles.ibd b/MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user_roles.ibd index 8b3f545..9de9c88 100644 Binary files a/MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user_roles.ibd and b/MySQL_conf_pbx/test1/mariadb_data/asterisk_db/user_roles.ibd differ diff --git a/MySQL_conf_pbx/test1/mariadb_data/ddl_recovery.log b/MySQL_conf_pbx/test1/mariadb_data/ddl_recovery.log index 434b85c..5e30b6d 100644 Binary files a/MySQL_conf_pbx/test1/mariadb_data/ddl_recovery.log and b/MySQL_conf_pbx/test1/mariadb_data/ddl_recovery.log differ diff --git a/MySQL_conf_pbx/test1/mariadb_data/ib_buffer_pool b/MySQL_conf_pbx/test1/mariadb_data/ib_buffer_pool index 18bd109..018cf43 100644 --- a/MySQL_conf_pbx/test1/mariadb_data/ib_buffer_pool +++ b/MySQL_conf_pbx/test1/mariadb_data/ib_buffer_pool @@ -1,11 +1,30 @@ -1,50 +18,4 +18,3 +18,2 +18,1 +18,0 +17,3 +17,2 +17,1 +17,0 +16,4 +16,3 +16,2 +16,1 +16,0 +15,3 +15,2 +15,1 +15,0 +14,4 +14,3 +14,2 +14,1 +14,0 13,3 13,2 13,1 13,0 -11,5 -11,4 -11,3 11,2 11,1 11,0 @@ -25,11 +44,6 @@ 8,1 8,0 7,3 -5,3 -4,3 -3,2 -2,2 -1,2 0,9 1,45 3,44 @@ -153,23 +167,15 @@ 2,8 1,8 3,7 -2,7 -1,7 3,6 -2,6 -1,6 -3,5 2,5 1,5 3,4 2,4 1,4 3,3 -3,0 2,3 -2,0 1,3 -1,0 0,6 0,0 0,47 @@ -181,6 +187,22 @@ 0,10 0,8 0,11 +11,5 +11,4 +11,3 +5,3 +4,3 +3,5 +3,2 +3,0 +2,7 +2,6 +2,2 +2,0 +1,7 +1,6 +1,2 +1,0 0,5 0,7 0,4 diff --git a/MySQL_conf_pbx/test1/mariadb_data/ib_logfile0 b/MySQL_conf_pbx/test1/mariadb_data/ib_logfile0 index a33bd14..febfc33 100644 Binary files a/MySQL_conf_pbx/test1/mariadb_data/ib_logfile0 and b/MySQL_conf_pbx/test1/mariadb_data/ib_logfile0 differ diff --git a/MySQL_conf_pbx/test1/mariadb_data/ibdata1 b/MySQL_conf_pbx/test1/mariadb_data/ibdata1 index b60b4ea..f5aa957 100644 Binary files a/MySQL_conf_pbx/test1/mariadb_data/ibdata1 and b/MySQL_conf_pbx/test1/mariadb_data/ibdata1 differ diff --git a/MySQL_conf_pbx/test1/mariadb_data/mysql/innodb_index_stats.ibd b/MySQL_conf_pbx/test1/mariadb_data/mysql/innodb_index_stats.ibd index c16ad8f..c994ab3 100644 Binary files a/MySQL_conf_pbx/test1/mariadb_data/mysql/innodb_index_stats.ibd and b/MySQL_conf_pbx/test1/mariadb_data/mysql/innodb_index_stats.ibd differ diff --git a/MySQL_conf_pbx/test1/mariadb_data/mysql/innodb_table_stats.ibd b/MySQL_conf_pbx/test1/mariadb_data/mysql/innodb_table_stats.ibd index fa236b2..9c6ac75 100644 Binary files a/MySQL_conf_pbx/test1/mariadb_data/mysql/innodb_table_stats.ibd and b/MySQL_conf_pbx/test1/mariadb_data/mysql/innodb_table_stats.ibd differ diff --git a/MySQL_conf_pbx/test1/mariadb_data/undo001 b/MySQL_conf_pbx/test1/mariadb_data/undo001 index 8c6fc55..0833be4 100644 Binary files a/MySQL_conf_pbx/test1/mariadb_data/undo001 and b/MySQL_conf_pbx/test1/mariadb_data/undo001 differ diff --git a/MySQL_conf_pbx/test1/mariadb_data/undo002 b/MySQL_conf_pbx/test1/mariadb_data/undo002 index 3386d3c..4fd7f5e 100644 Binary files a/MySQL_conf_pbx/test1/mariadb_data/undo002 and b/MySQL_conf_pbx/test1/mariadb_data/undo002 differ diff --git a/MySQL_conf_pbx/test1/mariadb_data/undo003 b/MySQL_conf_pbx/test1/mariadb_data/undo003 index 5312b28..9f1f38c 100644 Binary files a/MySQL_conf_pbx/test1/mariadb_data/undo003 and b/MySQL_conf_pbx/test1/mariadb_data/undo003 differ diff --git a/MySQL_conf_pbx/test1/springCezenPBX/pom.xml b/MySQL_conf_pbx/test1/springCezenPBX/pom.xml index f738044..4b0f43d 100644 --- a/MySQL_conf_pbx/test1/springCezenPBX/pom.xml +++ b/MySQL_conf_pbx/test1/springCezenPBX/pom.xml @@ -80,6 +80,25 @@ spring-security-test test + + + + io.jsonwebtoken + jjwt-api + 0.12.3 + + + io.jsonwebtoken + jjwt-impl + 0.12.3 + runtime + + + io.jsonwebtoken + jjwt-jackson + 0.12.3 + runtime + diff --git a/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/DAO/UserOpsDAO.java b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/DAO/UserOpsDAO.java new file mode 100644 index 0000000..6764c15 --- /dev/null +++ b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/DAO/UserOpsDAO.java @@ -0,0 +1,10 @@ +package com.example.cezenPBX.DAO; + +// TODO only one admin allowed ... once the admin creates an +// account they should not be able to make the account again +// admin login, logout and signup DAO operations +public interface UserOpsDAO { + + + // admin login +} diff --git a/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/DAO/UserOpsDAOImpl.java b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/DAO/UserOpsDAOImpl.java new file mode 100644 index 0000000..7c3f179 --- /dev/null +++ b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/DAO/UserOpsDAOImpl.java @@ -0,0 +1,9 @@ +package com.example.cezenPBX.DAO; + +import org.springframework.stereotype.Repository; + +@Repository +public class UserOpsDAOImpl implements UserOpsDAO{ + + +} diff --git a/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/config/CezenLoginSecurityChain.java b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/config/CezenLoginSecurityChain.java index b214d24..aa35a37 100644 --- a/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/config/CezenLoginSecurityChain.java +++ b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/config/CezenLoginSecurityChain.java @@ -1,11 +1,102 @@ package com.example.cezenPBX.config; +import com.example.cezenPBX.security.JWTTokenGeneratorFilter; +import com.example.cezenPBX.security.JWTTokenValidatorFilter; +import jakarta.servlet.http.HttpServletRequest; +import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +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.www.BasicAuthenticationFilter; +import org.springframework.security.web.csrf.CookieCsrfTokenRepository; +import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; + +import java.util.Collections; +import java.util.List; // this class will handel the routs that are protected and // allow spring security to accept login details from our custom login page @Configuration public class CezenLoginSecurityChain { + @Bean + SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { + + //the token is generated here + CsrfTokenRequestAttributeHandler requestHandler = new CsrfTokenRequestAttributeHandler(); + requestHandler.setCsrfRequestAttributeName("_csrf"); + + //CSRF cookie + final CookieCsrfTokenRepository cookieCsrfTokenRepo = new CookieCsrfTokenRepository(); + //make secure true when using only https + cookieCsrfTokenRepo.setCookieCustomizer(responseCookieBuilder -> responseCookieBuilder.secure(true)); + + // bellow line is used when you are using JWT tokens instead of jSession session keys but i put always because i guess CSRF token needs it + http. + logout((logout) -> logout.deleteCookies("Authorization", "JSESSIONID", "XSRF-TOKEN")) + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + + //now because we aare sending the JWT token to The UI Application in a Header + //we need to manage it in the CORs config + .cors(corsCustomizer -> corsCustomizer.configurationSource(new CorsConfigurationSource() { + @Override + public CorsConfiguration getCorsConfiguration(HttpServletRequest request) { + //check CORs and CSRF in Previous commits + CorsConfiguration config = new CorsConfiguration(); +// config.setAllowedOrigins(Collections.singletonList("http://localhost:4200")); + config.setAllowedOrigins(Collections.singletonList("*")); + config.setAllowedMethods(Collections.singletonList("*")); + config.setAllowCredentials(true); + config.setAllowedHeaders(Collections.singletonList("*")); + //the JWT will be sent to UI under Authorization header and XSR under X-XSRF-TOKEN + config.setExposedHeaders(List.of("Authorization", "X-XSRF-TOKEN")); + config.setMaxAge(3600L); + return config; + } + })) + + + .csrf(AbstractHttpConfigurer::disable) + //.addFilterAfter(new CsrfCookieFilter(), BasicAuthenticationFilter.class) + + //token generation after BasicAuthenticationFilter.class + .addFilterAfter(new JWTTokenGeneratorFilter(), BasicAuthenticationFilter.class) + //then position the verification filter + .addFilterBefore(new JWTTokenValidatorFilter(), BasicAuthenticationFilter.class) + .authorizeHttpRequests((requests) -> requests + //only admin can use this rout + //user roles :- ROLE_admin ROLE_employee ROLE_manager ROLE_user + .requestMatchers( + "/admin/get_all_users", + "/admin/list_all_branches_with_manager" + ).hasAnyRole("admin") + //any one who is authenticated can access /logout + .requestMatchers("/bankUser/login", "/user/getXSRfToken", "/logout").authenticated() + .requestMatchers("/bankUser/**").hasAnyRole("user") + //all the rest are open to public + .requestMatchers("/open/**").permitAll() + //.requestMatchers(HttpMethod.POST, "/open/**").permitAll() + ) + // redirect to /login if the user is not authenticated Customizer.withDefaults() enables a security feature using the defaults provided by Spring Security + .formLogin(Customizer.withDefaults()) + .httpBasic(Customizer.withDefaults()); + + return http.build(); + + } + + // to encode the password + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } } diff --git a/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/config/CustomAuthenticationProviderForCezen.java b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/config/CustomAuthenticationProviderForCezen.java new file mode 100644 index 0000000..3eb2a41 --- /dev/null +++ b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/config/CustomAuthenticationProviderForCezen.java @@ -0,0 +1,146 @@ +//package com.example.cezenPBX.config; +// +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.security.authentication.AuthenticationProvider; +//import org.springframework.security.authentication.BadCredentialsException; +//import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +//import org.springframework.security.core.Authentication; +//import org.springframework.security.core.AuthenticationException; +//import org.springframework.security.core.GrantedAuthority; +//import org.springframework.security.core.authority.SimpleGrantedAuthority; +//import org.springframework.security.crypto.password.PasswordEncoder; +// +//import java.util.ArrayList; +//import java.util.List; +// +//public class CustomAuthenticationProviderForCezen implements AuthenticationProvider { +// +// @Autowired +// private UserRepository userRepository; +// +// @Autowired +// private EmployeeRepository employeeRepository; +// +// @Autowired +// private PasswordEncoder passwordEncoder; +// +// @Override +// public Authentication authenticate(Authentication authentication) throws AuthenticationException { +// +// //get credentials from login form +// String username = authentication.getName(); +// String pwd = authentication.getCredentials().toString(); +// +// //sanity check +// if (username.isEmpty() || pwd.isEmpty()) return null; +// +// System.out.println(pwd); +// System.out.println(username); +// +// int employeeId = 0; +// boolean isEmployee = false; +// +// //what if the username is an employee login +// try { +// //if true +// employeeId = Integer.parseInt(username); +// isEmployee = true; +// } catch (Exception e) { +// System.out.println(e.toString()); +// } +// +// //employee auth +// if (isEmployee) { +// // if it is a valid number range +// if (employeeId > 0) { +// //check for employee +// Employee employee = null; +// try { +// //check if employee exists if yes then fetch details +// employee = employeeRepository.getEmployeeAndRolesById(employeeId); +// } catch (Exception e) { +// System.out.println(e.toString()); +// return null; +// } +// +// if (passwordEncoder.matches(pwd, employee.getPassword())) { +// +// //then it is a match a number of springs granted authorities +// List authorities = new ArrayList<>(); +// +// //loop through the users authorities and add each of them to simple granted authority +// try { +// +// //check if employee is part of permission set for employee signing in +// boolean hasEmployee = false; +// for(var permission : employee.getRoles()){ +// if(permission.getRole().equals("ROLE_employee")) hasEmployee = true; +// } +// if(!hasEmployee) throw new BadCredentialsException("no employee permission for given employee"); +// +// employee.getRoles().forEach(a -> authorities.add(new SimpleGrantedAuthority(a.getRole()))); +// } catch (Exception e) { +// //use/**/r doesn't have permissions or roles = null +// System.out.println(e.toString()); +// return null; +// } +// +// return new UsernamePasswordAuthenticationToken(employeeId, pwd, authorities); +// } else { +// throw new BadCredentialsException("Invalid password!"); +// } +// } else { +// throw new BadCredentialsException("No user registered with this details!"); +// } +// +// } +// +// //customer +// User customer = null; +// try { +// customer = userRepository.getUserDetailsByUserName(username); +// +// } catch (Exception e) { +// throw new BadCredentialsException("No user registered with this details!"); +// } +// +// //if the person exists +// if (customer != null) { +// System.out.println(customer.getPassword()); +// +// //check for a match +// if (passwordEncoder.matches(pwd, customer.getPassword())) { +// +// //then it is a match a number of springs granted authorities +// List authorities = new ArrayList<>(); +// +// //loop through the users authorities and add each of them to simple granted authority +// try { +// customer.getRoles().forEach(a -> authorities.add(new SimpleGrantedAuthority(a.getRole()))); +// } catch (Exception e) { +// //user doesn't have permissions or roles = null +// System.out.println(e.toString()); +// return null; +// } +// //final send the username password and auth as a token which will call the authenticate method in the ProviderManager +// // in this edit i wont store the password but a use id +// +// //this is so that i can get a global access to an authenticated users name and id +// username = username + "," + customer.getId() + "," + customer.getUserAccountId().getId(); +// +// return new UsernamePasswordAuthenticationToken(username, pwd, authorities); +// } else { +// throw new BadCredentialsException("Invalid password!"); +// } +// } else { +// throw new BadCredentialsException("No user registered with this details!"); +// } +// } +// +// @Override +// public boolean supports(Class authentication) { +// //tells spring that i want to support username password style of auth +// return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); +// } +// +//} diff --git a/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/constents/SecurityConstants.java b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/constents/SecurityConstants.java new file mode 100644 index 0000000..f72c978 --- /dev/null +++ b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/constents/SecurityConstants.java @@ -0,0 +1,7 @@ +package com.example.cezenPBX.constents; + +public interface SecurityConstants { + + public static final String JWT_KEY = ";sdmn3426FHB426RH62389;]['/.sdwswa"; + public static final String JWT_HEADER = "Authorization"; +} diff --git a/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/controller/SignUpController.java b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/controller/SignUpController.java new file mode 100644 index 0000000..1abe1a9 --- /dev/null +++ b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/controller/SignUpController.java @@ -0,0 +1,25 @@ +package com.example.cezenPBX.controller; + +import com.example.cezenPBX.DTO.ReturnStatus; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/open") +public class SignUpController { + + + //sign up route + @PostMapping("/signup") + public ReturnStatus signUp(){ + + return new ReturnStatus(true, "User created successfully", ""); + } + + // and a login route + + + + // forgot password +} diff --git a/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/security/JWTTokenGeneratorFilter.java b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/security/JWTTokenGeneratorFilter.java new file mode 100644 index 0000000..e1d8be5 --- /dev/null +++ b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/security/JWTTokenGeneratorFilter.java @@ -0,0 +1,81 @@ +package com.example.cezenPBX.security; + +import com.example.cezenPBX.constents.SecurityConstants; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.crypto.SecretKey; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +public class JWTTokenGeneratorFilter extends OncePerRequestFilter { + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { + + //at this point the user is authenticated we just have to send the token back + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + System.out.println(authentication); + if (null != authentication) { + + //get the JWT key from the contents we defined + // Keys, Jwts class comes from pom.xml + SecretKey key = Keys.hmacShaKeyFor(SecurityConstants.JWT_KEY.getBytes(StandardCharsets.UTF_8)); + + //creating a JWT token + // issuer issues a jwt token + //subject can be any value + String jwt = Jwts.builder().issuer("Mathew Francis").subject("JWT_Token") + //building the token + .claim("username", authentication.getName()) + .claim("authorities", populateAuthorities(authentication.getAuthorities())) + .issuedAt(new Date()) + .expiration(new Date((new Date()).getTime() + 30000000)) + //signing it with the key we set on line 35 + .signWith(key).compact(); + //SecurityConstants.JWT_HEADER, in the Constants SecurityConstants folder + //response.setHeader(SecurityConstants.JWT_HEADER, jwt); + //uncomment for cookie based saving + Cookie cookie = new Cookie(SecurityConstants.JWT_HEADER,jwt); + cookie.setHttpOnly(true); + cookie.setSecure(true); + cookie.setPath("/"); + response.addCookie(cookie); + System.out.println("JWT Generated"); + } + System.out.println("Intercepted"); + + System.out.println(response.getHeader("X-XSRF-TOKEN")); + filterChain.doFilter(request, response); + } + + //only generate if the path is login + //other words this method will return false for /login + @Override + protected boolean shouldNotFilter(HttpServletRequest request) { + + return (request.getServletPath().equals("/open/signup") || request.getServletPath().equals("/open/employee-login")); + } + + // gets the authority's from granted authority which we set in the configuration CustomAuthenticationProvider class + // plug in user auth into jwt token + private String populateAuthorities(Collection collection) { + Set authoritiesSet = new HashSet<>(); + for (GrantedAuthority authority : collection) { + authoritiesSet.add(authority.getAuthority()); + } + return String.join(",", authoritiesSet); + } +} diff --git a/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/security/JWTTokenValidatorFilter.java b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/security/JWTTokenValidatorFilter.java new file mode 100644 index 0000000..60e23df --- /dev/null +++ b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/security/JWTTokenValidatorFilter.java @@ -0,0 +1,81 @@ +package com.example.cezenPBX.security; + +import com.example.cezenPBX.constents.SecurityConstants; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.security.authentication.BadCredentialsException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.crypto.SecretKey; +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +public class JWTTokenValidatorFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + + // SecurityConstants + // public static final String JWT_KEY = "jxgEQeXHuPq8VdbyYFNkANdudQ53YUn4"; + // public static final String JWT_HEADER = "Authorization"; + //String jwt = request.getHeader(SecurityConstants.JWT_HEADER); + //below is the COOKIE approach + String jwt = null; + for(var cookie : request.getCookies()){ + if(cookie.getName().equals("Authorization")){ + System.out.print("COOKIE"); + System.out.println(cookie.getValue()); + jwt = cookie.getValue(); + } + } + if (null != jwt) { + try { + //generating the key + SecretKey key = Keys.hmacShaKeyFor( + SecurityConstants.JWT_KEY.getBytes(StandardCharsets.UTF_8)); + + //verification of legitimacy + Claims claims = Jwts.parser() + .verifyWith(key) + .build() + .parseSignedClaims(jwt) + .getPayload(); + String username = String.valueOf(claims.get("username")); + String authorities = (String) claims.get("authorities"); + +// System.out.println("JWT name : "+ username); +// System.out.println("JWT auth "+ authorities); + + //if successful the result will be stored in SecurityContextHolder + Authentication auth = new UsernamePasswordAuthenticationToken(username, null, + //this comes in a string of comas and values + AuthorityUtils.commaSeparatedStringToAuthorityList(authorities)); + SecurityContextHolder.getContext().setAuthentication(auth); + } catch (Exception e) { + throw new BadCredentialsException("Invalid Token received!"); + } + + } + filterChain.doFilter(request, response); + } + + //should be executed for all the api except the login api + @Override + protected boolean shouldNotFilter(HttpServletRequest request) { + + return request.getServletPath().equals("/open/signup") + || request.getServletPath().equals("/employee/employee-login"); +// //bellow was done to archive this /exposed/** +// request.getServletPath().split("/")[1].equals("exposed"); + } +} diff --git a/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/service/PbxUserController.java b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/service/PbxUserController.java new file mode 100644 index 0000000..d8ac35f --- /dev/null +++ b/MySQL_conf_pbx/test1/springCezenPBX/src/main/java/com/example/cezenPBX/service/PbxUserController.java @@ -0,0 +1,7 @@ +package com.example.cezenPBX.service; + +import org.springframework.stereotype.Service; + +@Service +public class PbxUserController { +}