Files
bflows-bandi-be/src/main/java/net/gepafin/tendermanagement/config/jwt/TokenProvider.java
2024-09-25 20:12:34 +05:30

248 lines
9.8 KiB
Java

package net.gepafin.tendermanagement.config.jwt;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import jakarta.annotation.PostConstruct;
import jakarta.servlet.http.HttpServletRequest;
import net.gepafin.tendermanagement.config.Translator;
import net.gepafin.tendermanagement.constants.GepafinConstant;
import net.gepafin.tendermanagement.entities.UserEntity;
import net.gepafin.tendermanagement.repositories.UserRepository;
import net.gepafin.tendermanagement.util.Utils;
import net.gepafin.tendermanagement.web.rest.api.errors.Status;
import net.gepafin.tendermanagement.web.rest.api.errors.UnauthorizedAccessException;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import javax.crypto.SecretKey;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
import com.google.gson.Gson;
import static io.micrometer.common.util.StringUtils.isEmpty;
@Component
public class TokenProvider {
private final Logger log = LoggerFactory.getLogger(TokenProvider.class);
@Value("${security.authentication.jwt.secret}")
private String secretKey;
@Value("${security.authentication.jwt.token-validity-in-seconds}")
private long tokenValidityInSeconds;
@Autowired
private UserRepository userRepository;
private SecretKey key;
private static final String AUTHORITIES_KEY = "auth";
private static final String MERCHANTID="merchantId";
static final String AUTH_SECRET = "X-Api-Secret";
private final Set<String> invalidatedTokens = new HashSet<>();
private static final String USER_ID = "userId";
public UserEntity validateUser(Map<String, Object> userInfo) {
if (userInfo == null || userInfo.get(USER_ID) == null) {
throw new UnauthorizedAccessException(Status.UNAUTHORIZED, Translator.toLocale(GepafinConstant.INVALID_USER));
}
Long userId = Long.valueOf(userInfo.get(USER_ID).toString());
UserEntity userEntity = userRepository.findById(userId).orElse(null);
if (userEntity == null) {
throw new UnauthorizedAccessException(Status.UNAUTHORIZED, Translator.toLocale(GepafinConstant.INVALID_USER));
}
if (!userEntity.getStatus().equals("ACTIVE")) {
throw new UnauthorizedAccessException(Status.UNAUTHORIZED, Translator.toLocale(GepafinConstant.INVALID_USER));
}
return userEntity;
}
@PostConstruct
public void init() {
this.key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8));
log.info("JWT Secret Key initialized.");
}
public String createToken(Boolean rememberMe, UserEntity user) {
// String authorities = authentication.getAuthorities().stream()
// .map(GrantedAuthority::getAuthority)
// .collect(Collectors.joining(","));
String authorities = user.getRoleEntity().getRoleType();
Long now;
Date validity;
if (Boolean.TRUE.equals(rememberMe)) {
now = DateUtils.addMonths(new Date(), 2).getTime();
validity = new Date(now);
log.info("Creating token with extended validity for 2 months.");
} else {
now = (new Date()).getTime();
validity = new Date(now + (this.tokenValidityInSeconds * 1000));
log.info("Creating token with standard validity of {} seconds.", this.tokenValidityInSeconds);
}
String payload = user.getEmail();
if(user != null) {
payload += ":"+user.getId();
}
String token = Jwts.builder()
.setSubject(payload)
.claim("auth", authorities)
.signWith(key, SignatureAlgorithm.HS512)
.setExpiration(validity)
.compact();
log.debug("Generated token: {}", token);
return token;
}
public Authentication getAuthentication(String token) {
Claims claims = Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(token)
.getBody();
UserDetails principal = new User(claims.getSubject(), "", Collections.emptyList());
log.info("Authenticated user: {}", claims.getSubject());
return new UsernamePasswordAuthenticationToken(principal, token, ClaimsToAuthorities(claims.get("auth")));
}
private Collection<? extends GrantedAuthority> ClaimsToAuthorities(Object authClaim) {
Collection<? extends GrantedAuthority> authorities = authClaim == null || ((String) authClaim).isEmpty() ?
Collections.emptyList() :
Arrays.stream(((String) authClaim).split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
log.debug("Converted authorities from claims: {}", authorities);
return authorities;
}
public boolean validateToken(String authToken) {
try {
if (isTokenInvalid(authToken)) {
log.warn("Token is invalidated.");
return false;
}
Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(authToken);
log.info("Token is valid.");
return true;
} catch (Exception e) {
log.error("Token validation failed: {}", e.getMessage());
return false;
}
}
public void invalidateToken(String token) {
invalidatedTokens.add(token);
log.info("Token invalidated: {}", token);
}
public boolean isTokenInvalid(String token) {
return invalidatedTokens.contains(token);
}
public Map<String, Object> getUserInfoAndUserIdFromToken(HttpServletRequest request) {
Map<String, Object> userInfo = new HashMap<>();
String authSecretHeader=request.getHeader(AUTH_SECRET);
// userInfo.put(MERCHANTID, null);
String bearerToken = request.getHeader("Authorization");
String token = "";
if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
token = bearerToken.substring(7, bearerToken.length());
}
extractDetailsFromTheToken(userInfo, authSecretHeader, token);
return userInfo;
}
public Map<String, Object> extractDetailsFromTheToken(Map<String, Object> userInfo, String authSecretHeader,
String token) {
String payload = null;
Boolean isSuperAdmin = false;
// if (StringUtils.hasText(token) && token.endsWith("_superKey" + getSuperUserToken())) {
// Map<String, Object> payloadMap = getUserDetailsForSuperUser(token);
// payload = payloadMap.get("sub").toString();
// isSuperAdmin = true;
//
// } else
if (!isEmpty(authSecretHeader)) {
String secret = Utils.decodeBase64String(authSecretHeader);
String[] tokenArr = secret.split("\\.", 2);
String[] merchant = tokenArr[0].split("-");
if (ArrayUtils.isNotEmpty(merchant) && 2 <= merchant.length) {
userInfo.put(MERCHANTID, merchant[1]);
return userInfo;
}
} else {
payload = getUserDetails(token);
}
if (payload != null && !isSuperAdmin) {
String[] payloadString = payload.split(":");{
if (payloadString.length > 1) {
// userInfo.put(MERCHANTID, payloadString[1]);
// userInfo.put("associatedTags", payloadString[2]);
userInfo.put("userId", payloadString[1]);
}
}
if (payloadString.length > 1) {
// userInfo.put(MERCHANTID, payloadString[1]);
// userInfo.put("associatedTags", payloadString[2]);
userInfo.put("userId", payloadString[1]);
}
} else {
String[] payloadString = payload.split(":");
if (payloadString.length > 1) {
userInfo.put("userId", payloadString[1]);
}
}
return userInfo;
}
public Map<String, Object> getUserDetailsForSuperUser(String token) {
Base64.Decoder decoder = Base64.getUrlDecoder();
String[] parts = token.split("\\."); // Splitting header, payload and signature
Gson g = new Gson();
return g.fromJson(new String(decoder.decode(parts[1])), Map.class);
}
// public String getSuperUserToken() {
// return superUserToken;
// }
public String getUserDetails(String token) {
Claims claims = Jwts.parser().setSigningKey(key).parseClaimsJws(token).getBody();
return claims.getSubject();
}
public String extractTokenFromRequest(HttpServletRequest request) {
String bearerToken = request.getHeader("Authorization");
if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
return bearerToken.substring(7); // Remove "Bearer " prefix
}
return null; // Return null if token is not found or not in Bearer format
}
}