Open Route added with Spring security
This commit is contained in:
parent
b87c2b6f7b
commit
824d824275
@ -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": []
|
||||
}
|
||||
]
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -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
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -80,6 +80,25 @@
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- JWT dependency -->
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-api</artifactId>
|
||||
<version>0.12.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-impl</artifactId>
|
||||
<version>0.12.3</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.jsonwebtoken</groupId>
|
||||
<artifactId>jjwt-jackson</artifactId>
|
||||
<version>0.12.3</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
package com.example.cezenPBX.DAO;
|
||||
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public class UserOpsDAOImpl implements UserOpsDAO{
|
||||
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<GrantedAuthority> 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<GrantedAuthority> 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));
|
||||
// }
|
||||
//
|
||||
//}
|
||||
@ -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";
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
@ -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<? extends GrantedAuthority> collection) {
|
||||
Set<String> authoritiesSet = new HashSet<>();
|
||||
for (GrantedAuthority authority : collection) {
|
||||
authoritiesSet.add(authority.getAuthority());
|
||||
}
|
||||
return String.join(",", authoritiesSet);
|
||||
}
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
package com.example.cezenPBX.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class PbxUserController {
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user