Skip to content

Commit 37b0893

Browse files
Indrani BandyopadhyayIndrani Bandyopadhyay
authored andcommitted
jwt api implementation
1 parent 2be93bd commit 37b0893

11 files changed

Lines changed: 349 additions & 0 deletions

pom.xml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,26 @@
278278
<artifactId>spring-web</artifactId>
279279
<version>6.1.12</version>
280280
</dependency>
281+
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api -->
282+
<dependency>
283+
<groupId>io.jsonwebtoken</groupId>
284+
<artifactId>jjwt-api</artifactId>
285+
<version>0.11.5</version>
286+
</dependency>
287+
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
288+
<dependency>
289+
<groupId>io.jsonwebtoken</groupId>
290+
<artifactId>jjwt-impl</artifactId>
291+
<version>0.11.5</version>
292+
<scope>runtime</scope>
293+
</dependency>
294+
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-jackson -->
295+
<dependency>
296+
<groupId>io.jsonwebtoken</groupId>
297+
<artifactId>jjwt-jackson</artifactId>
298+
<version>0.11.5</version>
299+
<scope>runtime</scope>
300+
</dependency>
281301
</dependencies>
282302

283303

src/main/environment/common_ci.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ prescription=TMPrescription SMS
8686

8787
### Redis IP
8888
spring.redis.host=localhost
89+
jwt.secret=<Enter_Your_Secret_Key>
8990

9091

9192

src/main/environment/common_dev.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ prescription=TMPrescription SMS
8686

8787
### Redis IP
8888
spring.redis.host=localhost
89+
jwt.secret=<Enter_Your_Secret_Key>
8990

9091

9192

src/main/environment/common_example.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ prescription=TMPrescription SMS
8686

8787
### Redis IP
8888
spring.redis.host=localhost
89+
jwt.secret=<Enter_Your_Secret_Key>
8990

9091

9192

src/main/environment/common_prod.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ prescription=TMPrescription SMS
8888

8989
### Redis IP
9090
spring.redis.host=localhost
91+
jwt.secret=<Enter_Your_Secret_Key>
9192

9293

9394

src/main/environment/common_test.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ prescription=TMPrescription SMS
9090

9191
### Redis IP
9292
spring.redis.host=localhost
93+
jwt.secret=<Enter_Your_Secret_Key>
9394

9495

9596

src/main/environment/common_uat.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ prescription=TMPrescription SMS
9090

9191
### Redis IP
9292
spring.redis.host=localhost
93+
jwt.secret=<Enter_Your_Secret_Key>
9394

9495

9596

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.iemr.hwc.utils;
2+
3+
import java.util.Arrays;
4+
import java.util.Optional;
5+
6+
import org.springframework.stereotype.Service;
7+
8+
import jakarta.servlet.http.Cookie;
9+
import jakarta.servlet.http.HttpServletRequest;
10+
import jakarta.servlet.http.HttpServletResponse;
11+
12+
@Service
13+
public class CookieUtil {
14+
15+
public Optional<String> getCookieValue(HttpServletRequest request, String cookieName) {
16+
Cookie[] cookies = request.getCookies();
17+
if (cookies != null) {
18+
for (Cookie cookie : cookies) {
19+
if (cookieName.equals(cookie.getName())) {
20+
return Optional.of(cookie.getValue());
21+
}
22+
}
23+
}
24+
return Optional.empty();
25+
}
26+
27+
public void addJwtTokenToCookie(String Jwttoken, HttpServletResponse response) {
28+
// Create a new cookie with the JWT token
29+
Cookie cookie = new Cookie("Jwttoken", Jwttoken);
30+
cookie.setHttpOnly(true); // Prevent JavaScript access for security
31+
cookie.setSecure(true); // Ensure the cookie is sent only over HTTPS
32+
cookie.setMaxAge(60 * 60 * 24); // 1 day expiration time
33+
cookie.setPath("/"); // Make the cookie available for the entire application
34+
response.addCookie(cookie); // Add the cookie to the response
35+
}
36+
37+
public String getJwtTokenFromCookie(HttpServletRequest request) {
38+
return Arrays.stream(request.getCookies())
39+
.filter(cookie -> "Jwttoken".equals(cookie.getName()))
40+
.map(Cookie::getValue)
41+
.findFirst()
42+
.orElse(null);
43+
}
44+
}
45+
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.iemr.hwc.utils;
2+
3+
import java.util.Optional;
4+
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
7+
import org.springframework.beans.factory.annotation.Autowired;
8+
import org.springframework.http.HttpStatus;
9+
import org.springframework.http.ResponseEntity;
10+
import org.springframework.stereotype.Component;
11+
12+
import com.iemr.hwc.data.login.Users;
13+
import com.iemr.hwc.repo.login.UserLoginRepo;
14+
import com.iemr.hwc.utils.exception.IEMRException;
15+
16+
import io.jsonwebtoken.Claims;
17+
import jakarta.servlet.http.HttpServletRequest;
18+
19+
@Component
20+
public class JwtAuthenticationUtil {
21+
22+
@Autowired
23+
private final CookieUtil cookieUtil;
24+
@Autowired
25+
private final JwtUtil jwtUtil;
26+
@Autowired
27+
private UserLoginRepo userLoginRepo;
28+
private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
29+
30+
31+
public JwtAuthenticationUtil(CookieUtil cookieUtil, JwtUtil jwtUtil) {
32+
this.cookieUtil = cookieUtil;
33+
this.jwtUtil = jwtUtil;
34+
}
35+
36+
public ResponseEntity<String> validateJwtToken(HttpServletRequest request) {
37+
Optional<String> jwtTokenOpt = cookieUtil.getCookieValue(request, "Jwttoken");
38+
39+
if (jwtTokenOpt.isEmpty()) {
40+
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
41+
.body("Error 401: Unauthorized - JWT Token is not set!");
42+
}
43+
44+
String jwtToken = jwtTokenOpt.get();
45+
46+
// Validate the token
47+
Claims claims = jwtUtil.validateToken(jwtToken);
48+
if (claims == null) {
49+
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Error 401: Unauthorized - Invalid JWT Token!");
50+
}
51+
52+
// Extract username from token
53+
String usernameFromToken = claims.getSubject();
54+
if (usernameFromToken == null || usernameFromToken.isEmpty()) {
55+
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("Error 401: Unauthorized - Username is missing!");
56+
}
57+
58+
// Return the username if valid
59+
return ResponseEntity.ok(usernameFromToken);
60+
}
61+
62+
public boolean validateUserIdAndJwtToken(String jwtToken) throws IEMRException {
63+
try {
64+
// Validate JWT token and extract claims
65+
Claims claims = jwtUtil.validateToken(jwtToken);
66+
67+
if (claims == null) {
68+
throw new IEMRException("Invalid JWT token.");
69+
}
70+
71+
String userId = claims.get("userId", String.class);
72+
String tokenUsername = jwtUtil.extractUsername(jwtToken);
73+
74+
// Fetch user based on userId from the database or cache
75+
Users user = userLoginRepo.getUserByUserID(Long.parseLong(userId));
76+
if (user == null) {
77+
throw new IEMRException("Invalid User ID.");
78+
}
79+
80+
// Check if the token's username matches the user retrieved by userId
81+
if (!user.getUserName().equalsIgnoreCase(tokenUsername)) {
82+
throw new IEMRException("JWT token and User ID mismatch.");
83+
}
84+
85+
return true; // Valid userId and JWT token
86+
} catch (Exception e) {
87+
logger.error("Validation failed: " + e.getMessage(), e);
88+
throw new IEMRException("Validation error: " + e.getMessage(), e);
89+
}
90+
}
91+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
package com.iemr.hwc.utils;
2+
3+
import java.io.IOException;
4+
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
7+
import org.springframework.stereotype.Component;
8+
9+
10+
import jakarta.servlet.Filter;
11+
import jakarta.servlet.FilterChain;
12+
import jakarta.servlet.ServletException;
13+
import jakarta.servlet.ServletRequest;
14+
import jakarta.servlet.ServletResponse;
15+
import jakarta.servlet.http.Cookie;
16+
import jakarta.servlet.http.HttpServletRequest;
17+
import jakarta.servlet.http.HttpServletResponse;
18+
19+
@Component
20+
public class JwtUserIdValidationFilter implements Filter {
21+
22+
private final JwtAuthenticationUtil jwtAuthenticationUtil;
23+
private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
24+
25+
public JwtUserIdValidationFilter(JwtAuthenticationUtil jwtAuthenticationUtil) {
26+
this.jwtAuthenticationUtil = jwtAuthenticationUtil;
27+
}
28+
29+
@Override
30+
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
31+
throws IOException, ServletException {
32+
HttpServletRequest request = (HttpServletRequest) servletRequest;
33+
HttpServletResponse response = (HttpServletResponse) servletResponse;
34+
35+
String path = request.getRequestURI();
36+
String contextPath = request.getContextPath();
37+
logger.info("JwtUserIdValidationFilter invoked for path: " + path);
38+
39+
// Log cookies for debugging
40+
Cookie[] cookies = request.getCookies();
41+
if (cookies != null) {
42+
for (Cookie cookie : cookies) {
43+
if ("userId".equals(cookie.getName())) {
44+
logger.warn("userId found in cookies! Clearing it...");
45+
clearUserIdCookie(response); // Explicitly remove userId cookie
46+
}
47+
}
48+
} else {
49+
logger.info("No cookies found in the request");
50+
}
51+
52+
53+
// Log headers for debugging
54+
String jwtTokenFromHeader = request.getHeader("Jwttoken");
55+
logger.info("JWT token from header: " + jwtTokenFromHeader);
56+
57+
// Skip login and public endpoints
58+
if (path.equals(contextPath + "/user/userAuthenticate") ||
59+
path.equalsIgnoreCase(contextPath + "/user/logOutUserFromConcurrentSession") ||
60+
path.startsWith(contextPath + "/public")) {
61+
logger.info("Skipping filter for path: " + path);
62+
filterChain.doFilter(servletRequest, servletResponse);
63+
return;
64+
}
65+
66+
try {
67+
// Retrieve JWT token from cookies
68+
String jwtTokenFromCookie = getJwtTokenFromCookies(request);
69+
logger.info("JWT token from cookie: " + jwtTokenFromCookie);
70+
71+
// Determine which token (cookie or header) to validate
72+
String jwtToken = jwtTokenFromCookie != null ? jwtTokenFromCookie : jwtTokenFromHeader;
73+
if (jwtToken == null) {
74+
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "JWT token not found in cookies or headers");
75+
return;
76+
}
77+
78+
// Validate JWT token and userId
79+
boolean isValid = jwtAuthenticationUtil.validateUserIdAndJwtToken(jwtToken);
80+
81+
if (isValid) {
82+
// If token is valid, allow the request to proceed
83+
filterChain.doFilter(servletRequest, servletResponse);
84+
} else {
85+
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid JWT token");
86+
}
87+
} catch (Exception e) {
88+
logger.error("Authorization error: ", e);
89+
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authorization error: " + e.getMessage());
90+
}
91+
}
92+
93+
private String getJwtTokenFromCookies(HttpServletRequest request) {
94+
Cookie[] cookies = request.getCookies();
95+
if (cookies != null) {
96+
for (Cookie cookie : cookies) {
97+
if (cookie.getName().equals("Jwttoken")) {
98+
return cookie.getValue();
99+
}
100+
}
101+
}
102+
return null;
103+
}
104+
105+
private void clearUserIdCookie(HttpServletResponse response) {
106+
Cookie cookie = new Cookie("userId", null);
107+
cookie.setPath("/");
108+
cookie.setMaxAge(0); // Invalidate the cookie
109+
response.addCookie(cookie);
110+
}
111+
}

0 commit comments

Comments
 (0)