From 915f0f1679d7404c0e5f0c87f5e2538a27a9a931 Mon Sep 17 00:00:00 2001 From: jomu Date: Fri, 23 Mar 2018 09:58:27 +0100 Subject: [PATCH] added JWT support --- jeeutil/pom.xml | 44 ++++------ .../shared/jeeutil/jwt/JWTDecoder.java | 84 +++++++++++++++++++ .../shared/jeeutil/jwt/JWTEncoder.java | 36 ++++++++ .../shared/jeeutil/jwt/JWTException.java | 40 +++++++++ .../shared/jeeutil/jwt/JWTGuard.java | 25 ++++++ 5 files changed, 199 insertions(+), 30 deletions(-) create mode 100644 jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTDecoder.java create mode 100644 jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTEncoder.java create mode 100644 jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTException.java create mode 100644 jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTGuard.java diff --git a/jeeutil/pom.xml b/jeeutil/pom.xml index a56310a..0f21b79 100644 --- a/jeeutil/pom.xml +++ b/jeeutil/pom.xml @@ -15,11 +15,20 @@ shared-jeeutil - ${project.build.directory}/endorsed UTF-8 + + com.inversoft + prime-jwt + 1.3.0 + + + javax + javaee-api + provided + org.slf4j slf4j-api @@ -35,12 +44,12 @@ primefaces jar provided - + - javax - javaee-api + org.apache.shiro + shiro-web provided - + @@ -52,31 +61,6 @@ 3.1 - - org.apache.maven.plugins - maven-dependency-plugin - 2.1 - - - validate - - copy - - - ${endorsed.dir} - true - - - javax - javaee-endorsed-api - 6.0 - jar - - - - - - diff --git a/jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTDecoder.java b/jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTDecoder.java new file mode 100644 index 0000000..f5dc43a --- /dev/null +++ b/jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTDecoder.java @@ -0,0 +1,84 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package de.muehlencord.shared.jeeutil.jwt; + +import java.time.ZonedDateTime; +import org.primeframework.jwt.Verifier; +import org.primeframework.jwt.domain.JWT; +import org.primeframework.jwt.domain.JWTException; +import org.primeframework.jwt.hmac.HMACVerifier; + +/** + * + * @author Joern Muehlencord + */ +public class JWTDecoder { + + private boolean parsedSuccessfully = false; + private JWT jwt = null; + + public JWTDecoder(String password, String issuer, String jwtString) throws JWTException { + if ((password == null) || (issuer == null) || (jwtString == null)) { + throw new JWTException("password, issuer and jwt must not be null"); + } + Verifier verifier = HMACVerifier.newVerifier(password); +// Verifier verifier = RSAVerifier.newVerifier(new String(Files.readAllBytes(Paths.get("public_key.pem")))); + try { + jwt = JWT.getDecoder().decode(jwtString, verifier); + parsedSuccessfully = jwt.issuer.equals(issuer); + } catch (JWTException ex) { + jwt = null; + } + } + + public String getIssuer() { + if (jwt == null) { + return null; + } else { + return jwt.issuer; + } + } + + public ZonedDateTime getIssuedAt() { + if (jwt == null) { + return null; + } else { + return jwt.issuedAt; + } + } + + public String getSubject() { + if (jwt == null) { + return null; + } else { + return jwt.subject; + } + } + + public String getUniqueId() { + if (jwt == null) { + return null; + } else { + return jwt.uniqueId; + } + } + + public ZonedDateTime getExpiration() { + if (jwt == null) { + return null; + } else { + return jwt.expiration; + } + } + + public boolean isValid() { + if ((jwt == null) || (jwt.isExpired())) { + return false; + } else { + return this.parsedSuccessfully; + } + } +} diff --git a/jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTEncoder.java b/jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTEncoder.java new file mode 100644 index 0000000..fb938da --- /dev/null +++ b/jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTEncoder.java @@ -0,0 +1,36 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package de.muehlencord.shared.jeeutil.jwt; + +import java.time.ZonedDateTime; +import org.primeframework.jwt.Signer; +import org.primeframework.jwt.domain.JWT; +import org.primeframework.jwt.hmac.HMACSigner; + +/** + * + * @author Joern Muehlencord + */ +public abstract class JWTEncoder { + + public static String encode(String password, String issuer, ZonedDateTime issuedAt, String subject, String uniqueId, short expirationInMinutes ) throws JWTException { + if ((password == null) || (issuer == null)) { + throw new JWTException("password and issuer must not be null"); + } + Signer signer = HMACSigner.newSHA256Signer(password); +// Signer signer = RSASigner.newSHA256Signer(new String(Files.readAllBytes(Paths.get("private_key.pem")))); + + + JWT jwt = new JWT().setIssuer(issuer) // FIXME - make configurable + .setIssuedAt(issuedAt) + .setSubject(subject) + .setUniqueId(uniqueId) + .setExpiration(issuedAt.plusMinutes(expirationInMinutes)); + return JWT.getEncoder().encode(jwt, signer); + + } + +} diff --git a/jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTException.java b/jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTException.java new file mode 100644 index 0000000..594dbd7 --- /dev/null +++ b/jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTException.java @@ -0,0 +1,40 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package de.muehlencord.shared.jeeutil.jwt; + +/** + * + * @author Joern Muehlencord + */ +public class JWTException extends Exception { + + private static final long serialVersionUID = 423992803027530544L; + + /** + * Creates a new instance of JWTException without detail message. + */ + public JWTException() { + } + + + /** + * Constructs an instance of JWTException with the specified detail message. + * @param msg the detail message. + */ + public JWTException(String msg) { + super(msg); + } + + /** + * Constructs an instance of JWTException with the specified detail message and root cause. + * @param msg the detail message. + * @param th the root cause + */ + public JWTException(String msg, Throwable th) { + super(msg,th); + } +} diff --git a/jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTGuard.java b/jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTGuard.java new file mode 100644 index 0000000..25ee84e --- /dev/null +++ b/jeeutil/src/main/java/de/muehlencord/shared/jeeutil/jwt/JWTGuard.java @@ -0,0 +1,25 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package de.muehlencord.shared.jeeutil.jwt; + +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; +import org.apache.shiro.web.filter.authc.AuthenticationFilter; + +/** + * + * @author Joern Muehlencord + */ +public class JWTGuard extends AuthenticationFilter { + + @Override + protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { + HttpServletResponse httpResponse = (HttpServletResponse) response; + httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return false; + } +}