initial commit
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
package de.w665.biblenotes.service;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.crypto.SecretKey;
|
||||
import java.util.Base64;
|
||||
import java.util.Date;
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AuthenticationService {
|
||||
private final UserRepository userRepository;
|
||||
private final UserLoginRepository userLoginRepository;
|
||||
|
||||
@Value("${secureapi.jwt.secret}")
|
||||
private String secretString;
|
||||
@Value("${secureapi.jwt.expiration}")
|
||||
private long expirationTime; // in milliseconds
|
||||
private SecretKey secretKey;
|
||||
|
||||
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
|
||||
|
||||
public AuthenticationService(UserRepository userRepository, UserLoginRepository userLoginRepository) {
|
||||
this.userRepository = userRepository;
|
||||
this.userLoginRepository = userLoginRepository;
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
log.debug("Initializing secret key");
|
||||
byte[] encodedKey = Base64.getEncoder().encode(secretString.getBytes()); // encode the secret key
|
||||
this.secretKey = Keys.hmacShaKeyFor(encodedKey);
|
||||
}
|
||||
|
||||
public String authenticate(String username, String password, String remoteAddr, long... expirationTime/*FOR TESTING VALIDITY*/) {
|
||||
if(expirationTime.length > 0) {
|
||||
this.expirationTime = expirationTime[0];
|
||||
}
|
||||
Optional<User> optionalUser = userRepository.retrieveUserByUsername(username);
|
||||
if (optionalUser.isPresent() && passwordEncoder.matches(password, optionalUser.get().getPassword())) {
|
||||
User user = optionalUser.get();
|
||||
|
||||
userLoginRepository.insertUserLogin(new UserLogin(""/*Auto generated*/, user.getId(), new Date(), remoteAddr));
|
||||
userRepository.updateLastLoginForUser(user.getUsername(), new Date());
|
||||
return generateToken(user);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String generateToken(User username) {
|
||||
long nowMillis = System.currentTimeMillis();
|
||||
Date now = new Date(nowMillis);
|
||||
Date expiryDate = new Date(nowMillis + expirationTime);
|
||||
|
||||
return Jwts.builder()
|
||||
.subject("SharePulse Authentication Token")
|
||||
.issuedAt(now)
|
||||
.claim("role", username.getRole())
|
||||
.claim("username", username.getUsername())
|
||||
.expiration(expiryDate)
|
||||
.signWith(secretKey)
|
||||
.compact();
|
||||
}
|
||||
|
||||
public boolean validateToken(String token) {
|
||||
try {
|
||||
Jwt<?,?> jwt = Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token);
|
||||
Claims claims = (Claims) jwt.getPayload();
|
||||
return !claims.getExpiration().before(new Date()); // Checks if the token is expired too
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public String extractSubject(String token) {
|
||||
return Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload().getSubject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a typed claim from the JWT.
|
||||
* @param token the JWT from which to extract the claim
|
||||
* @param claimName the name of the claim to retrieve
|
||||
* @param claimType the Class object of <T> the expected type of the claim value
|
||||
* @return the value of the specified claim as type T, or null if not found or in case of an error
|
||||
* Usage example: getClaimValue(token, "role", String.class)
|
||||
*/
|
||||
public <T> T getClaimValue(String token, String claimName, Class<T> claimType) {
|
||||
try {
|
||||
Jwt<?, ?> jwt = Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token);
|
||||
Claims claims = (Claims) jwt.getPayload();
|
||||
return claims.get(claimName, claimType);
|
||||
} catch (Exception e) {
|
||||
log.error("Error parsing claims from token: ", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String encodePassword(String password) {
|
||||
return passwordEncoder.encode(password);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user