200 lines
7.7 KiB
Java
200 lines
7.7 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.entities.UserEntity;
|
|
import net.gepafin.tendermanagement.util.Utils;
|
|
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.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;
|
|
|
|
private SecretKey key;
|
|
|
|
private static final String AUTHORITIES_KEY = "auth";
|
|
private static final String MERCHANTID="merchantId";
|
|
|
|
public static final String INVALID_USER = "invalid_user";
|
|
static final String AUTH_SECRET = "X-Api-Secret";
|
|
|
|
@PostConstruct
|
|
public void init() {
|
|
this.key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8));
|
|
log.info("JWT Secret Key initialized.");
|
|
}
|
|
|
|
public String createToken(Authentication authentication, Boolean rememberMe, UserEntity user) {
|
|
String authorities = authentication.getAuthorities().stream()
|
|
.map(GrantedAuthority::getAuthority)
|
|
.collect(Collectors.joining(","));
|
|
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 = authentication.getName();
|
|
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 {
|
|
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 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();
|
|
}
|
|
}
|