diff --git a/Goobi/.classpath b/Goobi/.classpath index dced35abd..04ccc545e 100644 --- a/Goobi/.classpath +++ b/Goobi/.classpath @@ -160,6 +160,7 @@ + diff --git a/Goobi/.gitignore b/Goobi/.gitignore index 6426b00b9..133b1b6b8 100644 --- a/Goobi/.gitignore +++ b/Goobi/.gitignore @@ -12,3 +12,4 @@ /goobi-jar/ /goobi-war/ /target/ +/module-war/ diff --git a/Goobi/src/de/sub/goobi/config/ConfigurationHelper.java b/Goobi/src/de/sub/goobi/config/ConfigurationHelper.java index 1d5bb4e3b..8b98851b1 100644 --- a/Goobi/src/de/sub/goobi/config/ConfigurationHelper.java +++ b/Goobi/src/de/sub/goobi/config/ConfigurationHelper.java @@ -320,6 +320,10 @@ public int getBatchMaxSize() { return getLocalInt("batchMaxSize", 100); } + public String getJwtSecret() { + return getLocalString("jwtSecret", null); + } + public boolean useS3() { return getLocalBoolean("useS3", false); } @@ -525,8 +529,7 @@ public boolean isMetsEditorShowOCRButton() { public boolean isMetsEditorShowMetadataPopup() { return getLocalBoolean("MetsEditorShowMetadataPopup", true); } - - + public String getFormatOfMetsBackup() { return getLocalString("formatOfMetaBackups"); } @@ -683,17 +686,17 @@ public List getMetsEditorImageSizes() { return getLocalList("MetsEditorImageSize"); } - + public List getMetsEditorImageTileSizes() { return getLocalList("MetsEditorImageTileSize"); } - + public List getMetsEditorImageTileScales() { return getLocalList("MetsEditorImageTileScale"); } - + public boolean getMetsEditorUseImageTiles() { return getLocalBoolean("MetsEditorUseImageTiles", true); diff --git a/Goobi/src/de/sub/goobi/helper/JwtHelper.java b/Goobi/src/de/sub/goobi/helper/JwtHelper.java new file mode 100644 index 000000000..91c70bb21 --- /dev/null +++ b/Goobi/src/de/sub/goobi/helper/JwtHelper.java @@ -0,0 +1,66 @@ +package de.sub.goobi.helper; + +import java.util.Date; + +import javax.naming.ConfigurationException; + +import org.goobi.beans.Step; +import org.joda.time.DateTime; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.JWTVerifier; +import com.auth0.jwt.algorithms.Algorithm; +import com.auth0.jwt.exceptions.JWTVerificationException; +import com.auth0.jwt.interfaces.DecodedJWT; + +import de.sub.goobi.config.ConfigurationHelper; +import lombok.extern.log4j.Log4j; + +@Log4j +public class JwtHelper { + public static String createChangeStepToken(Step step) throws ConfigurationException { + String secret = ConfigurationHelper.getInstance().getJwtSecret(); + if (secret == null) { + throw new ConfigurationException( + "Could not get JWT secret from configuration. Please configure the key 'jwtSecret' in the file goobi_config.properties"); + } + Algorithm algorithm = Algorithm.HMAC256("secret"); + Date expiryDate = new DateTime().plusHours(37).toDate(); + String token = JWT.create() + .withIssuer("Goobi") + .withClaim("stepId", step.getId()) + .withClaim("changeStepAllowed", true) + .withExpiresAt(expiryDate) + .sign(algorithm); + return token; + } + + public static boolean verifyChangeStepToken(String token, Integer stepId) throws ConfigurationException { + String secret = ConfigurationHelper.getInstance().getJwtSecret(); + if (secret == null) { + throw new ConfigurationException( + "Could not get JWT secret from configuration. Please configure the key 'jwtSecret' in the file goobi_config.properties"); + } + try { + Algorithm algorithm = Algorithm.HMAC256("secret"); + JWTVerifier verifier = JWT.require(algorithm) + .withIssuer("Goobi") + .build(); + DecodedJWT jwt = verifier.verify(token); + Integer claimId = jwt.getClaim("stepId").asInt(); + if (claimId == null || !stepId.equals(claimId)) { + log.debug("token rejected: step IDs do not match"); + return false; + } + Boolean changeStepAllowed = jwt.getClaim("changeStepAllowed").asBoolean(); + if (changeStepAllowed == null || !changeStepAllowed) { + log.debug("token rejected: changing the step not allowed"); + return false; + } + } catch (JWTVerificationException exception) { + //Invalid signature/claims + return false; + } + return true; + } +} diff --git a/Goobi/src/de/sub/goobi/helper/VariableReplacer.java b/Goobi/src/de/sub/goobi/helper/VariableReplacer.java index 4d2b359f1..7fc806d1a 100644 --- a/Goobi/src/de/sub/goobi/helper/VariableReplacer.java +++ b/Goobi/src/de/sub/goobi/helper/VariableReplacer.java @@ -35,6 +35,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.naming.ConfigurationException; + import org.apache.commons.lang.SystemUtils; import org.apache.commons.lang.text.StrTokenizer; import org.apache.log4j.Logger; @@ -94,6 +96,7 @@ private enum MetadataLevel { private static Pattern pMetaFile = Pattern.compile("\\$?(:?\\(|\\{)metaFile(:?\\}|\\))"); private static Pattern pStepId = Pattern.compile("\\$?(:?\\(|\\{)stepid(:?\\}|\\))"); private static Pattern pStepName = Pattern.compile("\\$?(:?\\(|\\{)stepname(:?\\}|\\))"); + private static Pattern pChangeStepToken = Pattern.compile("\\\\$?(:?\\\\(|\\\\{)changesteptoken(:?\\\\}|\\\\))"); DigitalDocument dd; Prefs prefs; @@ -258,6 +261,16 @@ public String replace(String inString) { inString = pStepId.matcher(inString).replaceAll(stepId); inString = pStepName.matcher(inString).replaceAll(stepname); + + Matcher tokenMatcher = pChangeStepToken.matcher(inString); + if (tokenMatcher.find()) { + try { + String token = JwtHelper.createChangeStepToken(step); + inString = tokenMatcher.replaceAll(token); + } catch (ConfigurationException e) { + logger.error(e); + } + } } // replace WerkstueckEigenschaft, usage: (product.PROPERTYTITLE) diff --git a/Goobi/webapp/WEB-INF/lib/java-jwt-3.4.1.jar b/Goobi/webapp/WEB-INF/lib/java-jwt-3.4.1.jar new file mode 100644 index 000000000..aa26a594e Binary files /dev/null and b/Goobi/webapp/WEB-INF/lib/java-jwt-3.4.1.jar differ