package io.mangoo.helpers.cookie; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.Objects; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jwts; import io.mangoo.core.Application; import io.mangoo.crypto.Crypto; import io.mangoo.enums.ClaimKey; import io.mangoo.enums.Required; import io.mangoo.routing.handlers.DispatcherHandler; /** * * @author svenkubiak * */ public class CookieParser { private static final Logger LOG = LogManager.getLogger(DispatcherHandler.class); private Map<String, String> sessionValues = new HashMap<>(); private String secret; private String value; private String authenticityToken; private String authenticatedUser; private LocalDateTime expiresDate; private boolean encrypted; private boolean twoFactor; public static CookieParser build() { return new CookieParser(); } public CookieParser withContent(String value) { this.value = value; return this; } public CookieParser withSecret(String secret) { Objects.requireNonNull(secret, Required.APPLICATION_SECRET.toString()); this.secret = secret; return this; } public CookieParser isEncrypted(boolean encrypted) { this.encrypted = encrypted; return this; } public boolean isTwoFactor() { return this.twoFactor; } @SuppressWarnings("unchecked") public boolean hasValidSessionCookie() { decrypt(); boolean valid = false; if (StringUtils.isNotBlank(this.value)) { try { Jws<Claims> jwsClaims = Jwts.parser() .setSigningKey(this.secret) .parseClaimsJws(this.value); Claims claims = jwsClaims.getBody(); Date expiration = claims.getExpiration(); if (expiration != null) { this.sessionValues = claims.get(ClaimKey.DATA.toString(), Map.class); this.authenticityToken = claims.get(ClaimKey.AUTHENTICITY.toString(), String.class); this.expiresDate = dateToLocalDateTime(expiration); valid = true; } } catch (Exception e) { //NOSONAR LOG.error("Failed to parse JWS for seesion cookie", e); } } return valid; } public boolean hasValidAuthenticationCookie() { decrypt(); boolean valid = false; if (StringUtils.isNotBlank(this.value)) { try { Jws<Claims> jwsClaims = Jwts.parser() .setSigningKey(this.secret) .parseClaimsJws(this.value); Claims claims = jwsClaims.getBody(); Date expiration = claims.getExpiration(); if (expiration != null) { this.authenticatedUser = claims.getSubject(); this.twoFactor = claims.get(ClaimKey.TWO_FACTOR.toString(), Boolean.class); this.expiresDate = dateToLocalDateTime(expiration); valid = true; } } catch (Exception e) { //NOSONAR LOG.error("Failed to parse JWS for authentication cookie", e); } } return valid; } public Map<String, String> getSessionValues() { return this.sessionValues; } public String getAuthenticity() { return this.authenticityToken; } public LocalDateTime getExpiresDate() { return this.expiresDate; } public String getAuthenticatedUser() { return this.authenticatedUser; } private void decrypt() { if (this.encrypted && StringUtils.isNotBlank(this.value) && !this.value.contains("\\|")) { this.value = Application.getInstance(Crypto.class).decrypt(this.value); } } private LocalDateTime dateToLocalDateTime(Date date) { Objects.requireNonNull(date, Required.DATE.toString()); Instant instant = Instant.ofEpochMilli(date.getTime()); return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); } }