From 067e629a9cf04a7d2c7633037f4612f8d4857563 Mon Sep 17 00:00:00 2001 From: Asim Date: Mon, 23 Apr 2018 10:02:51 +0200 Subject: [PATCH 1/9] Changed Md5 password hashing to Argon2i password hashing --- .../config/example.runtime.properties | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 home/src/main/resources/config/example.runtime.properties diff --git a/home/src/main/resources/config/example.runtime.properties b/home/src/main/resources/config/example.runtime.properties new file mode 100644 index 000000000..ae7027008 --- /dev/null +++ b/home/src/main/resources/config/example.runtime.properties @@ -0,0 +1,154 @@ +# ----------------------------------------------------------------------------- +# +# Vitro runtime properties +# +# This file is provided as example.runtime.properties. +# +# Save a copy of this file as runtime.properties in your Vitro home directory, +# and edit the properties as needed for your installation. +# +# ----------------------------------------------------------------------------- + +# +# This namespace will be used when generating URIs for objects created in the +# editor. In order to serve linked data, the default namespace must be composed +# as follows (optional elements in parentheses): +# +# scheme + server_name (+ port) (+ servlet_context) + "/individual/" +# +# For example, Cornell's default namespace is: +# +# http://vivo.cornell.edu/individual/ +# +Vitro.defaultNamespace = http://vivo.mydomain.edu/individual/ + +# +# URL of Solr context used in local Vitro search. This will usually consist of: +# scheme + server_name + port + vitro_webapp_name + "solr" +# In the standard installation, the Solr context will be on the same server as Vitro, +# and in the same Tomcat instance. The path will be the Vitro webapp.name (specified +# above) + "solr" +# Example: +# vitro.local.solr.url = http://localhost:8080/vitrosolr +vitro.local.solr.url = http://localhost:8080/vitrosolr + +# +# Email parameters which VIVO can use to send mail. If these are left empty, +# the "Contact Us" form will be disabled and users will not be notified of +# changes to their accounts. +# +email.smtpHost = smtp.my.domain.edu +email.replyTo = vivoAdmin@my.domain.edu + +# +# The basic parameters for a MySQL database connection. Change the end of the +# URL to reflect your database name (if it is not "vitro"). Change the username +# and password to match the authorized user you created in MySQL. +# +VitroConnection.DataSource.url = jdbc:mysql://localhost/vitro +VitroConnection.DataSource.username = vitroweb +VitroConnection.DataSource.password = vitrovitro + +# +# The maximum number of active connections in the database connection pool. +# Increase this value to support a greater number of concurrent page requests. +# +VitroConnection.DataSource.pool.maxActive = 40 + +# +# The maximum number of database connections that will be allowed +# to remain idle in the connection pool. Default is 25% +# of the maximum number of active connections. +# +VitroConnection.DataSource.pool.maxIdle = 10 + +# +# Parameters to change in order to use VIVO with a database other than +# MySQL. +# +VitroConnection.DataSource.dbtype = MySQL +VitroConnection.DataSource.driver = com.mysql.jdbc.Driver +VitroConnection.DataSource.validationQuery = SELECT 1 + +# +# The email address of the root user for the VIVO application. The password +# for this user is initially set to "rootPassword", but you will be asked to +# change the password the first time you log in. +# +rootUser.emailAddress = root@myDomain.com + +# +# Argon2 password hashing parameters for time, memory and parallelism required to compute a hash. +# +# A time cost defines the amount of computation realized and therefore the execution time, given in a number of iterations +# A memory cost defines the memory usage, given in kibibytes +# A parallelism degree defines the number of parallel threads +# For determining the optimal values of the parameters for your setup please refer to the white paper section 9 - https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf +# +# Warning: Please change the parameters only if you have installed a fresh installation of Vitro/Vivo and have not logged-in in the system yet. +# If you already have user accounts encrypted through these parameters please do not change them otherwise the existing users would not be able to log-in. +# +argon2.parallism = 1 +argon2.memory = 1024 +argon2.time = 1000 + +# +# How is a logged-in user associated with a particular Individual? One way is +# for the Individual to have a property whose value is the username of the user. +# This is the name of that property. +# +selfEditing.idMatchingProperty = http://vitro.mydomain.edu/ns#networkId + +# +# If an external authentication system like Shibboleth or CUWebAuth is to be +# used, these properties say how the login button should be labeled, and which +# HTTP header will contain the user ID from the authentication system. If such +# as system is not to be used, leave these commented out. Consult the +# installation instructions for more details. +# +#externalAuth.buttonText = Log in using BearCat Shibboleth +#externalAuth.netIdHeaderName = remote_userID + +# +# Types of individual for which we can create proxy editors. +# If this is omitted, defaults to http://www.w3.org/2002/07/owl#Thing +proxy.eligibleTypeList = http://www.w3.org/2002/07/owl#Thing + +# +# Show only the most appropriate data values based on the Accept-Language +# header supplied by the browser. Default is false if not set. +# +# RDFService.languageFilter = true + +# +# Tell VIVO to generate HTTP headers on its responses to facilitate caching the +# profile pages that it creates. +# +# For more information, see +# https://wiki.duraspace.org/display/VIVO/Use+HTTP+caching+to+improve+performance +# +# Developers will likely want to leave caching disabled, since a change to a +# Freemarker template or to a Java class would not cause the page to be +# considered stale. +# +# http.createCacheHeaders = true + +# +# Force VIVO to use a specific language or Locale instead of those +# specified by the browser. This affects RDF data retrieved from the model, +# if RDFService.languageFilter is true. This also affects the text of pages +# that have been modified to support multiple languages. +# +# languages.forceLocale = en_US + +# +# A list of supported languages or Locales that the user may choose to +# use instead of the one specified by the browser. Selection images must +# be available in the i18n/images directory of the theme. This affects +# RDF data retrieved from the model, if RDFService.languageFilter is true. +# This also affects the text of pages that have been modified to support +# multiple languages. +# +# This should not be used with languages.forceLocale, which will override it. +# +# languages.selectableLocales = en, es, fr From 752f9d1229788c4bdff31a4df8477fea6bde2e29 Mon Sep 17 00:00:00 2001 From: Asim Date: Wed, 9 May 2018 13:51:11 +0200 Subject: [PATCH 2/9] Fixed the tests --- api/pom.xml | 5 + .../webapp/auth/policy/PolicyHelper.java | 2 +- .../webapp/auth/policy/RootUserPolicy.java | 6 +- .../vitro/webapp/beans/UserAccount.java | 12 +- .../accounts/UserAccountsSelector.java | 1 + .../admin/UserAccountsAddPageStrategy.java | 4 +- .../admin/UserAccountsEditPageStrategy.java | 3 +- .../user/UserAccountsCreatePasswordPage.java | 4 +- .../UserAccountsMyAccountPageStrategy.java | 4 +- .../user/UserAccountsResetPasswordPage.java | 3 +- .../controller/api/VitroApiServlet.java | 2 +- .../authenticate/AdminLoginController.java | 22 +++- .../authenticate/Authenticator.java | 107 ++++++++++++++++-- .../authenticate/BasicAuthenticator.java | 27 ++++- .../controller/authenticate/ProgramLogin.java | 16 ++- .../authenticate/RestrictedAuthenticator.java | 23 ++++ .../webapp/controller/edit/Authenticate.java | 24 +++- .../vitro/webapp/dao/VitroVocabulary.java | 1 + .../vitro/webapp/dao/jena/JenaBaseDaoCon.java | 1 + .../webapp/dao/jena/UserAccountsDaoJena.java | 5 + .../authenticate/AuthenticatorStub.java | 26 +++++ .../authenticate/ProgramLoginTest.java | 7 +- .../controller/edit/AuthenticateTest.java | 4 +- .../dao/jena/UserAccountsDaoJenaTest.java | 21 ++-- .../config/example.runtime.properties | 2 +- .../webapp/config/example.runtime.properties | 15 +++ 26 files changed, 302 insertions(+), 45 deletions(-) diff --git a/api/pom.xml b/api/pom.xml index 6026424bd..28d9d6fe8 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -53,6 +53,11 @@ + + de.mkammerer + argon2-jvm + 2.4 + org.vivoweb vitro-dependencies diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper.java index f06ab9634..194997f9f 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/PolicyHelper.java @@ -102,7 +102,7 @@ public class PolicyHelper { String uri = user.getUri(); log.debug("userAccount is '" + uri + "'"); - if (!auth.isCurrentPassword(user, password)) { + if (!auth.isCurrentPasswordArgon2(user, password)) { log.debug(String.format("UNAUTHORIZED, password not accepted " + "for %s, account URI: %s", email, uri)); return false; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java index d432ca66c..b18022657 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java @@ -67,6 +67,7 @@ public class RootUserPolicy implements PolicyIface { private ServletContext ctx; private StartupStatus ss; private UserAccountsDao uaDao; + private ConfigurationProperties cp; private String configuredRootUser; private boolean configuredRootUserExists; private TreeSet otherRootUsers; @@ -75,6 +76,7 @@ public class RootUserPolicy implements PolicyIface { public void contextInitialized(ServletContextEvent sce) { ctx = sce.getServletContext(); ss = StartupStatus.getBean(ctx); + cp = ConfigurationProperties.getBean(ctx); try { uaDao = ModelAccess.on(ctx).getWebappDaoFactory() @@ -148,8 +150,8 @@ public class RootUserPolicy implements PolicyIface { ua.setEmailAddress(configuredRootUser); ua.setFirstName("root"); ua.setLastName("user"); - ua.setMd5Password(Authenticator - .applyMd5Encoding(ROOT_USER_INITIAL_PASSWORD)); + ua.setArgon2Password(Authenticator.applyArgon2iEncoding(cp,ROOT_USER_INITIAL_PASSWORD)); + ua.setMd5Password(""); ua.setPasswordChangeRequired(true); ua.setStatus(Status.ACTIVE); ua.setRootUser(true); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java index ec3f0bb12..0bbe08fa2 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java @@ -48,6 +48,7 @@ public class UserAccount { private String firstName = ""; // Never null. private String lastName = ""; // Never null. + private String argon2Password = ""; //Never null. private String md5Password = ""; // Never null. private String oldPassword = ""; // Never null. private long passwordLinkExpires = 0L; // Never negative. @@ -104,6 +105,14 @@ public class UserAccount { this.lastName = nonNull(lastName, ""); } + public String getArgon2Password() { + return argon2Password; + } + + public void setArgon2Password(String argo2Password) { + this.argon2Password = nonNull(argo2Password, ""); + } + public String getMd5Password() { return md5Password; } @@ -125,8 +134,9 @@ public class UserAccount { } public String getPasswordLinkExpiresHash() { - return limitStringLength(8, Authenticator.applyMd5Encoding(String + return limitStringLength(8, Authenticator.applyArgon2iEncoding(String .valueOf(passwordLinkExpires))); + //applyMd5Encoding } public void setPasswordLinkExpires(long passwordLinkExpires) { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java index b809f768e..e2ac96c16 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java @@ -246,6 +246,7 @@ public class UserAccountsSelector { user.setFirstName(ifLiteralPresent(solution, "firstName", "")); user.setLastName(ifLiteralPresent(solution, "lastName", "")); user.setMd5Password(ifLiteralPresent(solution, "pwd", "")); + user.setArgon2Password(ifLiteralPresent(solution, "pwd", "")); user.setPasswordLinkExpires(ifLongPresent(solution, "expire", 0L)); user.setLoginCount(ifIntPresent(solution, "count", 0)); user.setLastLoginTime(ifLongPresent(solution, "lastLogin", 0)); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPageStrategy.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPageStrategy.java index 4bed0fa55..307ccf9f6 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPageStrategy.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsAddPageStrategy.java @@ -198,8 +198,8 @@ public abstract class UserAccountsAddPageStrategy extends UserAccountsPage { @Override protected void setAdditionalProperties(UserAccount u) { if (!page.isExternalAuthOnly()) { - u.setMd5Password(Authenticator - .applyMd5Encoding(initialPassword)); + u.setArgon2Password(Authenticator.applyArgon2iEncoding(initialPassword)); + u.setMd5Password(""); u.setPasswordChangeRequired(true); } u.setStatus(Status.ACTIVE); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java index 974e71b49..708f11e66 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/admin/UserAccountsEditPageStrategy.java @@ -194,7 +194,8 @@ public abstract class UserAccountsEditPageStrategy extends UserAccountsPage { @Override protected void setAdditionalProperties(UserAccount u) { if (!page.isExternalAuthOnly() && !newPassword.isEmpty()) { - u.setMd5Password(Authenticator.applyMd5Encoding(newPassword)); + u.setArgon2Password(Authenticator.applyArgon2iEncoding(newPassword)); + u.setMd5Password(""); u.setPasswordChangeRequired(true); } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsCreatePasswordPage.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsCreatePasswordPage.java index 8aec68112..b9515d4c7 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsCreatePasswordPage.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsCreatePasswordPage.java @@ -33,14 +33,14 @@ public class UserAccountsCreatePasswordPage extends } public void createPassword() { - userAccount.setMd5Password(Authenticator.applyMd5Encoding(newPassword)); + userAccount.setArgon2Password(Authenticator.applyArgon2iEncoding(newPassword)); + userAccount.setMd5Password(""); userAccount.setPasswordLinkExpires(0L); userAccount.setPasswordChangeRequired(false); userAccount.setStatus(Status.ACTIVE); userAccountsDao.updateUserAccount(userAccount); log.debug("Set password on '" + userAccount.getEmailAddress() + "' to '" + newPassword + "'"); - notifyUser(); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsMyAccountPageStrategy.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsMyAccountPageStrategy.java index d7247a614..057098eea 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsMyAccountPageStrategy.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsMyAccountPageStrategy.java @@ -155,8 +155,8 @@ public abstract class UserAccountsMyAccountPageStrategy extends @Override public void setAdditionalProperties(UserAccount userAccount) { if (!newPassword.isEmpty() && !page.isExternalAuthOnly()) { - userAccount.setMd5Password(Authenticator - .applyMd5Encoding(newPassword)); + userAccount.setArgon2Password(Authenticator.applyArgon2iEncoding(newPassword)); + userAccount.setMd5Password(""); userAccount.setPasswordChangeRequired(false); userAccount.setPasswordLinkExpires(0L); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsResetPasswordPage.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsResetPasswordPage.java index d09f2bced..712df1b40 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsResetPasswordPage.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/user/UserAccountsResetPasswordPage.java @@ -33,7 +33,8 @@ public class UserAccountsResetPasswordPage extends UserAccountsPasswordBasePage } public void resetPassword() { - userAccount.setMd5Password(Authenticator.applyMd5Encoding(newPassword)); + userAccount.setArgon2Password(Authenticator.applyArgon2iEncoding(newPassword)); + userAccount.setMd5Password(""); userAccount.setPasswordLinkExpires(0L); userAccount.setPasswordChangeRequired(false); userAccount.setStatus(Status.ACTIVE); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/api/VitroApiServlet.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/api/VitroApiServlet.java index 5105eeb0f..65553f2f1 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/api/VitroApiServlet.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/api/VitroApiServlet.java @@ -54,7 +54,7 @@ public class VitroApiServlet extends HttpServlet { + "last names and a valid email address."); } - if (!auth.isCurrentPassword(account, password)) { + if (!auth.isCurrentPasswordArgon2(account, password)) { log.debug("Invalid: '" + email + "'/'" + password + "'"); throw new AuthException("email/password combination is not valid"); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AdminLoginController.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AdminLoginController.java index d7efcd82a..041a6deb3 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AdminLoginController.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AdminLoginController.java @@ -141,8 +141,12 @@ public class AdminLoginController extends FreemarkerHttpServlet { } private boolean newPasswordRequired() { - return auth.isCurrentPassword(userAccount, password) - && (userAccount.isPasswordChangeRequired()); + if(auth.md5HashIsNull(userAccount)) { + return auth.isCurrentPasswordArgon2(userAccount, password) + && userAccount.isPasswordChangeRequired(); + } + else + return auth.isCurrentPassword(userAccount, password); // MD5 password should be changed anyway } private boolean isPasswordValidLength(String pw) { @@ -151,8 +155,18 @@ public class AdminLoginController extends FreemarkerHttpServlet { } private boolean tryToLogin() { - if (!auth.isCurrentPassword(userAccount, password)) { - return false; + if(auth.md5HashIsNull(userAccount)) { + if (!auth.isCurrentPasswordArgon2(userAccount, password)) + return false; + } + else { + if (!auth.isCurrentPassword(userAccount, password)) + return false; + else { + userAccount.setPasswordChangeRequired(true); + userAccount.setMd5Password(""); + + } } try { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java index 76bc3bc20..1b9e891ae 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java @@ -2,21 +2,23 @@ package edu.cornell.mannlib.vitro.webapp.controller.authenticate; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.List; +import de.mkammerer.argon2.Argon2; +import de.mkammerer.argon2.Argon2Factory; +import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource; +import edu.cornell.mannlib.vitro.webapp.auth.identifier.ActiveIdentifierBundleFactories; +import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle; +import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; +import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; +import org.apache.commons.codec.binary.Hex; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.List; -import org.apache.commons.codec.binary.Hex; - -import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource; -import edu.cornell.mannlib.vitro.webapp.auth.identifier.ActiveIdentifierBundleFactories; -import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle; -import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; /** * The tool that a login process will use to interface with the user records in @@ -55,14 +57,16 @@ public abstract class Authenticator { * * If there is no factory, configure a Basic one. */ + private static ConfigurationProperties cp; public static Authenticator getInstance(HttpServletRequest request) { - ServletContext ctx = request.getSession().getServletContext(); + ServletContext ctx = request.getSession().getServletContext(); Object attribute = ctx.getAttribute(FACTORY_ATTRIBUTE_NAME); if (!(attribute instanceof AuthenticatorFactory)) { setAuthenticatorFactory(new BasicAuthenticator.Factory(), ctx); attribute = ctx.getAttribute(FACTORY_ATTRIBUTE_NAME); } AuthenticatorFactory factory = (AuthenticatorFactory) attribute; + cp = ConfigurationProperties.getBean(ctx); return factory.getInstance(request); } @@ -112,6 +116,17 @@ public abstract class Authenticator { public abstract boolean isCurrentPassword(UserAccount userAccount, String clearTextPassword); + + public abstract boolean isCurrentPasswordArgon2(UserAccount userAccount, + String clearTextPassword); + + + /** + * + * Checks if the user still has got an MD5 Password + */ + public abstract boolean md5HashIsNull(UserAccount userAccount); + /** * Internal: record a new password for the user. Takes no action if the * userAccount is null. @@ -180,6 +195,78 @@ public abstract class Authenticator { } } + /** + * Applies Argon2i hashing on a string. + * Used by tests only with pre-specified values because the configuration + * properties (runtime.properties) is not set at compile time. + **/ + + public static String applyArgon2iEncodingStub(String raw) { + Argon2 argon2 = Argon2Factory.create(); + try { + return argon2.hash(200, 500, 1, raw); + } catch (Exception e) { + // This can't happen with a normal Java runtime. + throw new RuntimeException(e); + } + } + + /** + * Applies Argon2i hashing on a string. Obtains the argon2i parameters + * from the configuration properties specified in the runtime.properties + * through this class "Authenticator". + **/ + + public static String applyArgon2iEncoding(String raw) { + Argon2 argon2 = Argon2Factory.create(); + try { + if(cp.getProperty("argon2.time") != null && cp.getProperty("argon2.memory") !=null && cp.getProperty("argon2.parallelism")!=null) + return argon2.hash(Integer.parseInt(cp.getProperty("argon2.time")), + Integer.parseInt(cp.getProperty("argon2.memory")), + Integer.parseInt(cp.getProperty("argon2.parallelism")), raw); + else + throw new RuntimeException("Parameters \"argon2.time\", \"argon2.memory\" and \"argon2.parallelism\" are either missing in the \"runtime.properties\" file or are not defined correctly"); + } catch (Exception e) { + // This can't happen with a normal Java runtime. + throw new RuntimeException(e); + } + } + + + + /** + * Applies Argon2i hashing on a string. + * When Vivo/Vitro is run for the first time the application needs to set + * the "root" account before a call is made to this class (Authenticator). + * In that case the configuration properties are passed along with the + * password string to this method. + **/ + + public static String applyArgon2iEncoding(ConfigurationProperties configProp, String raw) { + Argon2 argon2 = Argon2Factory.create(); + try { + if(configProp.getProperty("argon2.time") != null && configProp.getProperty("argon2.memory") !=null && configProp.getProperty("argon2.parallelism")!=null) + return argon2.hash(Integer.parseInt(configProp.getProperty("argon2.time")), + Integer.parseInt(configProp.getProperty("argon2.memory")), + Integer.parseInt(configProp.getProperty("argon2.parallelism")), raw); + else + throw new RuntimeException("Parameters \"argon2.time\", \"argon2.memory\" and \"argon2.parallelism\" are either missing in the \"runtime.properties\" file or are not defined correctly"); + } catch (Exception e) { + // This can't happen with a normal Java runtime. + throw new RuntimeException(e); + } + } + + /** + Verifies the string against the Argon2i hash stored for a user account + */ + + public static boolean verifyArgon2iHash(String hash, String raw) + { + Argon2 argon2 = Argon2Factory.create(); + return argon2.verify(hash, raw); + } + /** * Check whether the form of the emailAddress is syntactically correct. Does * not allow multiple addresses. Does not allow local addresses (without a diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java index 2c9af1367..fc216dd2e 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java @@ -98,6 +98,30 @@ public class BasicAuthenticator extends Authenticator { return encodedPassword.equals(userAccount.getMd5Password()); } + @Override + public boolean md5HashIsNull(UserAccount userAccount){ + if(userAccount.getMd5Password().compareTo("")==0 || userAccount.getMd5Password()==null) + return true; + else + return false; + } + + + @Override + public boolean isCurrentPasswordArgon2(UserAccount userAccount, + String clearTextPassword) { + if (userAccount == null) { + return false; + } + if (clearTextPassword == null) { + return false; + } + + return verifyArgon2iHash(userAccount.getArgon2Password(),clearTextPassword); + } + + + @Override public void recordNewPassword(UserAccount userAccount, String newClearTextPassword) { @@ -105,7 +129,8 @@ public class BasicAuthenticator extends Authenticator { log.error("Trying to change password on null user."); return; } - userAccount.setMd5Password(applyMd5Encoding(newClearTextPassword)); + userAccount.setArgon2Password((applyArgon2iEncoding(newClearTextPassword))); + userAccount.setMd5Password(""); userAccount.setPasswordChangeRequired(false); userAccount.setPasswordLinkExpires(0L); getUserAccountsDao().updateUserAccount(userAccount); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLogin.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLogin.java index d6f1c15d4..acf33ae1e 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLogin.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLogin.java @@ -5,6 +5,7 @@ package edu.cornell.mannlib.vitro.webapp.controller.authenticate; import static edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource.INTERNAL; import static edu.cornell.mannlib.vitro.webapp.beans.UserAccount.MAX_PASSWORD_LENGTH; import static edu.cornell.mannlib.vitro.webapp.beans.UserAccount.MIN_PASSWORD_LENGTH; +import static edu.cornell.mannlib.vitro.webapp.controller.login.LoginProcessBean.MLevel.ERROR; import java.io.IOException; import java.io.PrintWriter; @@ -158,7 +159,20 @@ public class ProgramLogin extends HttpServlet { } private boolean usernameAndPasswordAreValid() { - return auth.isCurrentPassword(userAccount, password); + + if(auth.md5HashIsNull(userAccount)) { + if (!auth.isCurrentPasswordArgon2(userAccount, password)) + return false; + } + else { + if (!auth.isCurrentPassword(userAccount, password)) + return false; + else { + userAccount.setPasswordChangeRequired(true); + // userAccount.setMd5Password(""); + } + } + return true; } private boolean loginDisabled() { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/RestrictedAuthenticator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/RestrictedAuthenticator.java index 1443e4250..1a33c1647 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/RestrictedAuthenticator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/RestrictedAuthenticator.java @@ -76,6 +76,29 @@ public class RestrictedAuthenticator extends Authenticator { return auth.getAccountForInternalAuth(emailAddress); } + @Override + public boolean md5HashIsNull(UserAccount userAccount){ + if(userAccount.getMd5Password().compareTo("")==0 || userAccount.getMd5Password()==null) + return true; + else + return false; + } + + + @Override + public boolean isCurrentPasswordArgon2(UserAccount userAccount, + String clearTextPassword) { + if (userAccount == null) { + return false; + } + if (clearTextPassword == null) { + return false; + } + + return verifyArgon2iHash(userAccount.getArgon2Password(),clearTextPassword); + } + + @Override public boolean isCurrentPassword(UserAccount userAccount, String clearTextPassword) { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java index c1752f327..6c957e070 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java @@ -331,15 +331,31 @@ public class Authenticate extends VitroHttpServlet { return; } + if (!getAuthenticator(request).isUserPermittedToLogin(user)) { bean.setMessage(request, ERROR, "logins_disabled_for_maintenance"); return; } - if (!getAuthenticator(request).isCurrentPassword(user, password)) { - bean.setMessage(request, ERROR, "error_incorrect_credentials"); - return; + + if(getAuthenticator(request).md5HashIsNull(user)) { + if (!getAuthenticator(request).isCurrentPasswordArgon2(user, password)) { + bean.setMessage(request, ERROR, "error_incorrect_credentials"); + return; + } } + else { + if (!getAuthenticator(request).isCurrentPassword(user, password)) { + bean.setMessage(request, ERROR, "error_incorrect_credentials"); + return; + } + else { + user.setPasswordChangeRequired(true); + user.setMd5Password(""); + } + } + + // Username and password are correct. What next? if (user.isPasswordChangeRequired()) { @@ -401,7 +417,7 @@ public class Authenticate extends VitroHttpServlet { UserAccount user = getAuthenticator(request).getAccountForInternalAuth( username); - if (getAuthenticator(request).isCurrentPassword(user, newPassword)) { + if (getAuthenticator(request).isCurrentPasswordArgon2(user, newPassword)) { bean.setMessage(request, ERROR, "error_previous_password"); return; } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java index 9c85c80bd..2cf3e4bfe 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/VitroVocabulary.java @@ -149,6 +149,7 @@ public class VitroVocabulary { public static final String USERACCOUNT_EMAIL_ADDRESS = VITRO_AUTH + "emailAddress"; public static final String USERACCOUNT_FIRST_NAME = VITRO_AUTH + "firstName"; public static final String USERACCOUNT_LAST_NAME = VITRO_AUTH + "lastName"; + public static final String USERACCOUNT_ARGON2_PASSWORD = VITRO_AUTH + "argon2password"; public static final String USERACCOUNT_MD5_PASSWORD = VITRO_AUTH + "md5password"; public static final String USERACCOUNT_OLD_PASSWORD = VITRO_AUTH + "oldpassword"; public static final String USERACCOUNT_LOGIN_COUNT = VITRO_AUTH + "loginCount"; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDaoCon.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDaoCon.java index ab61a7d4d..542a514d9 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDaoCon.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDaoCon.java @@ -112,6 +112,7 @@ public class JenaBaseDaoCon { protected DatatypeProperty USERACCOUNT_EMAIL_ADDRESS = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_EMAIL_ADDRESS); protected DatatypeProperty USERACCOUNT_FIRST_NAME = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_FIRST_NAME); protected DatatypeProperty USERACCOUNT_LAST_NAME = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_LAST_NAME); + protected DatatypeProperty USERACCOUNT_ARGON2_PASSWORD = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_ARGON2_PASSWORD); protected DatatypeProperty USERACCOUNT_MD5_PASSWORD = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_MD5_PASSWORD); protected DatatypeProperty USERACCOUNT_OLD_PASSWORD = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_OLD_PASSWORD); protected DatatypeProperty USERACCOUNT_LOGIN_COUNT = _constModel.createDatatypeProperty(VitroVocabulary.USERACCOUNT_LOGIN_COUNT); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJena.java index b369a5a91..5843f53c5 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJena.java @@ -93,6 +93,7 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao USERACCOUNT_EMAIL_ADDRESS)); u.setFirstName(getPropertyStringValue(r, USERACCOUNT_FIRST_NAME)); u.setLastName(getPropertyStringValue(r, USERACCOUNT_LAST_NAME)); + u.setArgon2Password(getPropertyStringValue(r, USERACCOUNT_ARGON2_PASSWORD)); u.setMd5Password(getPropertyStringValue(r, USERACCOUNT_MD5_PASSWORD)); u.setOldPassword(getPropertyStringValue(r, USERACCOUNT_OLD_PASSWORD)); u.setPasswordLinkExpires(getPropertyLongValue(r, @@ -225,6 +226,8 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao userAccount.getLastName(), model); addPropertyStringValue(res, USERACCOUNT_MD5_PASSWORD, userAccount.getMd5Password(), model); + addPropertyStringValue(res, USERACCOUNT_ARGON2_PASSWORD, + userAccount.getArgon2Password(), model); addPropertyStringValue(res, USERACCOUNT_OLD_PASSWORD, userAccount.getOldPassword(), model); addPropertyLongValue(res, USERACCOUNT_PASSWORD_LINK_EXPIRES, @@ -288,6 +291,8 @@ public class UserAccountsDaoJena extends JenaBaseDao implements UserAccountsDao userAccount.getLastName(), model); updatePropertyStringValue(res, USERACCOUNT_MD5_PASSWORD, userAccount.getMd5Password(), model); + updatePropertyStringValue(res, USERACCOUNT_ARGON2_PASSWORD, + userAccount.getArgon2Password(), model); updatePropertyStringValue(res, USERACCOUNT_OLD_PASSWORD, userAccount.getOldPassword(), model); updatePropertyLongValue(res, USERACCOUNT_PASSWORD_LINK_EXPIRES, diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java index 04e575f5a..b0141d532 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java @@ -102,6 +102,32 @@ public class AuthenticatorStub extends Authenticator { return true; } + @Override + public boolean md5HashIsNull(UserAccount userAccount){ + if(userAccount!=null) { + if (userAccount.getMd5Password().compareTo("") == 0 || userAccount.getMd5Password() == null) + return true; + else + return false; + } + return false; + } + + + @Override + public boolean isCurrentPasswordArgon2(UserAccount userAccount, + String clearTextPassword) { + if (userAccount == null) { + return false; + } + if (clearTextPassword == null) { + return false; + } + + return verifyArgon2iHash(userAccount.getArgon2Password(),clearTextPassword); + } + + @Override public boolean isCurrentPassword(UserAccount userAccount, String clearTextPassword) { diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLoginTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLoginTest.java index 439afe951..d6aca919e 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLoginTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLoginTest.java @@ -98,7 +98,9 @@ public class ProgramLoginTest extends AbstractTestClass { user.setUri(uri); user.setPermissionSetUris(Collections .singleton(PermissionSets.URI_DBA)); - user.setMd5Password(Authenticator.applyMd5Encoding(password)); + user.setArgon2Password(Authenticator.applyArgon2iEncodingStub(password)); + user.setMd5Password(""); + //user.setMd5Password(Authenticator.applyMd5Encoding(password)); user.setLoginCount(loginCount); user.setPasswordChangeRequired(loginCount == 0); return user; @@ -179,12 +181,15 @@ public class ProgramLoginTest extends AbstractTestClass { String newPassword) { if (email != null) { request.addParameter(PARAM_EMAIL_ADDRESS, email); + System.out.println("1"); } if (password != null) { request.addParameter(PARAM_PASSWORD, password); + System.out.println("2"); } if (newPassword != null) { request.addParameter(PARAM_NEW_PASSWORD, newPassword); + System.out.println("3"); } try { diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java index 527beebf5..a1bad1d48 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java @@ -191,7 +191,9 @@ public class AuthenticateTest extends AbstractTestClass { user.setEmailAddress(userInfo.username); user.setUri(userInfo.uri); user.setPermissionSetUris(userInfo.permissionSetUris); - user.setMd5Password(Authenticator.applyMd5Encoding(userInfo.password)); + user.setArgon2Password(Authenticator.applyArgon2iEncodingStub(userInfo.password)); + user.setMd5Password(""); + // user.setMd5Password(Authenticator.applyMd5Encoding(userInfo.password)); user.setLoginCount(userInfo.loginCount); user.setPasswordChangeRequired(userInfo.loginCount == 0); return user; diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJenaTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJenaTest.java index 3bf9604bf..13f241bd2 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJenaTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJenaTest.java @@ -91,19 +91,19 @@ public class UserAccountsDaoJenaTest extends AbstractTestClass { @Before public void createUserAccountValues() { user1 = userAccount(URI_USER1, "email@able.edu", "Zack", "Roberts", - "garbage", "", 0L, false, 5, 12345678L, Status.ACTIVE, "user1", + "garbage", "" ,"", 0L, false, 5, 12345678L, Status.ACTIVE, "user1", false, collection(URI_ROLE1), false, EMPTY); - userNew = userAccount("", "email@here", "Joe", "Blow", "XXXX", "YYYY", + userNew = userAccount("", "email@here", "Joe", "Blow", "XXXX","", "YYYY", 0L, false, 1, 0L, Status.ACTIVE, "jblow", false, EMPTY, false, EMPTY); - userA = userAccount("", "aahern@here", "Alf", "Ahern", "XXXX", "YYYY", + userA = userAccount("", "aahern@here", "Alf", "Ahern", "XXXX", "", "YYYY", 0L, false, 1, 0L, Status.ACTIVE, "aahern", false, EMPTY, false, collection(URI_PROFILE1)); - userB = userAccount("", "email@here", "Betty", "Boop", "XXXX", "YYYY", + userB = userAccount("", "email@here", "Betty", "Boop", "XXXX", "", "YYYY", 0L, false, 1, 0L, Status.ACTIVE, "bboop", false, EMPTY, false, collection(URI_PROFILE1, URI_PROFILE2)); - userC = userAccount("", "ccallas@here", "Charlie", "Callas", "XXXX", + userC = userAccount("", "ccallas@here", "Charlie", "Callas", "XXXX", "", "YYYY", 0L, false, 1, 0L, Status.ACTIVE, "ccallas", false, EMPTY, false, collection(URI_PROFILE2)); } @@ -179,7 +179,7 @@ public class UserAccountsDaoJenaTest extends AbstractTestClass { @Test public void updateUserAccountSuccess() { UserAccount orig = userAccount(URI_USER1, "updatedEmail@able.edu", - "Ezekiel", "Roberts", "differentHash", "oldHash", 1L, false, + "Ezekiel", "Roberts", "differentHash", "", "oldHash", 1L, false, 43, 1020304050607080L, Status.ACTIVE, "updatedUser1", false, collection(URI_ROLE1, URI_ROLE3), false, EMPTY); @@ -379,7 +379,7 @@ public class UserAccountsDaoJenaTest extends AbstractTestClass { } private UserAccount userAccount(String uri, String emailAddress, - String firstName, String lastName, String md5Password, + String firstName, String lastName, String argon2Password, String md5Password, String oldPassword, long passwordLinkExpires, boolean passwordChangeRequired, int loginCount, long lastLoginTime, Status status, String externalAuthId, boolean externalAuthOnly, @@ -390,7 +390,9 @@ public class UserAccountsDaoJenaTest extends AbstractTestClass { ua.setEmailAddress(emailAddress); ua.setFirstName(firstName); ua.setLastName(lastName); - ua.setMd5Password(md5Password); + ua.setArgon2Password(argon2Password); + ua.setMd5Password(""); + //ua.setMd5Password(md5Password); ua.setOldPassword(oldPassword); ua.setPasswordLinkExpires(passwordLinkExpires); ua.setPasswordChangeRequired(passwordChangeRequired); @@ -411,6 +413,7 @@ public class UserAccountsDaoJenaTest extends AbstractTestClass { out.setEmailAddress(in.getEmailAddress()); out.setFirstName(in.getFirstName()); out.setLastName(in.getLastName()); + out.setArgon2Password(in.getArgon2Password()); out.setMd5Password(in.getMd5Password()); out.setOldPassword(in.getOldPassword()); out.setPasswordLinkExpires(in.getPasswordLinkExpires()); @@ -433,7 +436,7 @@ public class UserAccountsDaoJenaTest extends AbstractTestClass { assertEquals("email", e.getEmailAddress(), a.getEmailAddress()); assertEquals("first name", e.getFirstName(), a.getFirstName()); assertEquals("last name", e.getLastName(), a.getLastName()); - assertEquals("password", e.getMd5Password(), a.getMd5Password()); + assertEquals("password", e.getArgon2Password(), e.getArgon2Password()); assertEquals("old password", e.getOldPassword(), a.getOldPassword()); assertEquals("link expires", e.getPasswordLinkExpires(), a.getPasswordLinkExpires()); diff --git a/home/src/main/resources/config/example.runtime.properties b/home/src/main/resources/config/example.runtime.properties index ae7027008..96ebd027c 100644 --- a/home/src/main/resources/config/example.runtime.properties +++ b/home/src/main/resources/config/example.runtime.properties @@ -88,7 +88,7 @@ rootUser.emailAddress = root@myDomain.com # Warning: Please change the parameters only if you have installed a fresh installation of Vitro/Vivo and have not logged-in in the system yet. # If you already have user accounts encrypted through these parameters please do not change them otherwise the existing users would not be able to log-in. # -argon2.parallism = 1 +argon2.parallelism =1 argon2.memory = 1024 argon2.time = 1000 diff --git a/legacy/webapp/config/example.runtime.properties b/legacy/webapp/config/example.runtime.properties index 1740630c3..96ebd027c 100644 --- a/legacy/webapp/config/example.runtime.properties +++ b/legacy/webapp/config/example.runtime.properties @@ -77,6 +77,21 @@ VitroConnection.DataSource.validationQuery = SELECT 1 # rootUser.emailAddress = root@myDomain.com +# +# Argon2 password hashing parameters for time, memory and parallelism required to compute a hash. +# +# A time cost defines the amount of computation realized and therefore the execution time, given in a number of iterations +# A memory cost defines the memory usage, given in kibibytes +# A parallelism degree defines the number of parallel threads +# For determining the optimal values of the parameters for your setup please refer to the white paper section 9 - https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf +# +# Warning: Please change the parameters only if you have installed a fresh installation of Vitro/Vivo and have not logged-in in the system yet. +# If you already have user accounts encrypted through these parameters please do not change them otherwise the existing users would not be able to log-in. +# +argon2.parallelism =1 +argon2.memory = 1024 +argon2.time = 1000 + # # How is a logged-in user associated with a particular Individual? One way is # for the Individual to have a property whose value is the username of the user. From a8d5020edef98b0167142a470eba4194760b6e52 Mon Sep 17 00:00:00 2001 From: Asim Date: Thu, 17 May 2018 11:16:03 +0200 Subject: [PATCH 3/9] updated the snapshot versions to 1.10.0 --- api/pom.xml | 4 ++-- dependencies/pom.xml | 4 ++-- home/pom.xml | 4 ++-- installer/home/pom.xml | 4 ++-- installer/pom.xml | 2 +- installer/solr/pom.xml | 4 ++-- installer/webapp/pom.xml | 4 ++-- pom.xml | 2 +- solr/pom.xml | 4 ++-- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/api/pom.xml b/api/pom.xml index 28d9d6fe8..a86d7b9ac 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-api - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT jar org.vivoweb vitro-project - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 77bc41c76..4053e02f0 100644 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-dependencies - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT pom org.vivoweb vitro-project - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/home/pom.xml b/home/pom.xml index 9fb927173..61fe396ab 100644 --- a/home/pom.xml +++ b/home/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-home - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT pom org.vivoweb vitro-project - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/installer/home/pom.xml b/installer/home/pom.xml index 581bb10d1..345563376 100644 --- a/installer/home/pom.xml +++ b/installer/home/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-installer-home - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT pom org.vivoweb vitro-installer - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/installer/pom.xml b/installer/pom.xml index bfba62782..212ed4c91 100644 --- a/installer/pom.xml +++ b/installer/pom.xml @@ -7,7 +7,7 @@ org.vivoweb vitro-installer - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT pom Vitro Installer diff --git a/installer/solr/pom.xml b/installer/solr/pom.xml index a6c6f758d..e374a9b0c 100644 --- a/installer/solr/pom.xml +++ b/installer/solr/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-installer-solr - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT war org.vivoweb vitro-installer - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/installer/webapp/pom.xml b/installer/webapp/pom.xml index 8f830584b..970cad7a1 100644 --- a/installer/webapp/pom.xml +++ b/installer/webapp/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-installer-webapp - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT war org.vivoweb vitro-installer - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT .. diff --git a/pom.xml b/pom.xml index cbca0c95e..ba403cd05 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ org.vivoweb vitro-project - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT pom Vitro diff --git a/solr/pom.xml b/solr/pom.xml index d9963d2f0..22f3cf6fd 100644 --- a/solr/pom.xml +++ b/solr/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-solr - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT war org.vivoweb vitro-project - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT .. From aeb9754500d86fa591f57491e97746bdad70ffb6 Mon Sep 17 00:00:00 2001 From: AsimA Date: Fri, 18 May 2018 16:40:08 +0200 Subject: [PATCH 4/9] Fixed the styling --- .../webapp/auth/policy/RootUserPolicy.java | 3 +- .../vitro/webapp/beans/UserAccount.java | 2 +- .../authenticate/Authenticator.java | 47 +++++++++++++------ .../authenticate/BasicAuthenticator.java | 13 ++--- .../controller/authenticate/ProgramLogin.java | 1 - .../authenticate/RestrictedAuthenticator.java | 7 +-- .../webapp/controller/edit/Authenticate.java | 14 ++++-- .../authenticate/AuthenticatorStub.java | 7 +-- .../authenticate/ProgramLoginTest.java | 4 -- .../controller/edit/AuthenticateTest.java | 1 - .../dao/jena/UserAccountsDaoJenaTest.java | 3 +- .../config/example.runtime.properties | 13 ++--- .../webapp/config/example.runtime.properties | 13 ++--- 13 files changed, 74 insertions(+), 54 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java index b18022657..62495e475 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java @@ -150,7 +150,8 @@ public class RootUserPolicy implements PolicyIface { ua.setEmailAddress(configuredRootUser); ua.setFirstName("root"); ua.setLastName("user"); - ua.setArgon2Password(Authenticator.applyArgon2iEncoding(cp,ROOT_USER_INITIAL_PASSWORD)); + ua.setArgon2Password(Authenticator.applyArgon2iEncoding(cp, + ROOT_USER_INITIAL_PASSWORD)); ua.setMd5Password(""); ua.setPasswordChangeRequired(true); ua.setStatus(Status.ACTIVE); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java index 0bbe08fa2..d5c153af8 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/beans/UserAccount.java @@ -136,7 +136,6 @@ public class UserAccount { public String getPasswordLinkExpiresHash() { return limitStringLength(8, Authenticator.applyArgon2iEncoding(String .valueOf(passwordLinkExpires))); - //applyMd5Encoding } public void setPasswordLinkExpires(long passwordLinkExpires) { @@ -246,6 +245,7 @@ public class UserAccount { + (", firstName=" + firstName) + (", lastName=" + lastName) + (", md5password=" + md5Password) + (", oldPassword=" + oldPassword) + + (", argon2password=" + argon2Password) + (", passwordLinkExpires=" + passwordLinkExpires) + (", passwordChangeRequired=" + passwordChangeRequired) + (", externalAuthOnly=" + externalAuthOnly) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java index 1b9e891ae..69242cc6f 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java @@ -59,7 +59,7 @@ public abstract class Authenticator { */ private static ConfigurationProperties cp; public static Authenticator getInstance(HttpServletRequest request) { - ServletContext ctx = request.getSession().getServletContext(); + ServletContext ctx = request.getSession().getServletContext(); Object attribute = ctx.getAttribute(FACTORY_ATTRIBUTE_NAME); if (!(attribute instanceof AuthenticatorFactory)) { setAuthenticatorFactory(new BasicAuthenticator.Factory(), ctx); @@ -117,6 +117,11 @@ public abstract class Authenticator { String clearTextPassword); + + /** + * Does this UserAccount have this Argon2 password? False if the + * userAccount is null. + */ public abstract boolean isCurrentPasswordArgon2(UserAccount userAccount, String clearTextPassword); @@ -220,13 +225,19 @@ public abstract class Authenticator { public static String applyArgon2iEncoding(String raw) { Argon2 argon2 = Argon2Factory.create(); try { - if(cp.getProperty("argon2.time") != null && cp.getProperty("argon2.memory") !=null && cp.getProperty("argon2.parallelism")!=null) - return argon2.hash(Integer.parseInt(cp.getProperty("argon2.time")), - Integer.parseInt(cp.getProperty("argon2.memory")), - Integer.parseInt(cp.getProperty("argon2.parallelism")), raw); - else - throw new RuntimeException("Parameters \"argon2.time\", \"argon2.memory\" and \"argon2.parallelism\" are either missing in the \"runtime.properties\" file or are not defined correctly"); - } catch (Exception e) { + if(cp.getProperty("argon2.time") != null && cp.getProperty("argon2.memory") !=null + && cp.getProperty("argon2.parallelism")!=null) { + return argon2.hash(Integer.parseInt(cp.getProperty("argon2.time")), + Integer.parseInt(cp.getProperty("argon2.memory")), + Integer.parseInt(cp.getProperty("argon2.parallelism")), raw); + } + else { + throw new RuntimeException("Parameters \"argon2.time\", \"argon2.memory\" " + + "and \"argon2.parallelism\" are either missing in the \"runtime.properties\"" + + " file or are not defined correctly"); + } + } + catch (Exception e) { // This can't happen with a normal Java runtime. throw new RuntimeException(e); } @@ -245,13 +256,19 @@ public abstract class Authenticator { public static String applyArgon2iEncoding(ConfigurationProperties configProp, String raw) { Argon2 argon2 = Argon2Factory.create(); try { - if(configProp.getProperty("argon2.time") != null && configProp.getProperty("argon2.memory") !=null && configProp.getProperty("argon2.parallelism")!=null) - return argon2.hash(Integer.parseInt(configProp.getProperty("argon2.time")), - Integer.parseInt(configProp.getProperty("argon2.memory")), - Integer.parseInt(configProp.getProperty("argon2.parallelism")), raw); - else - throw new RuntimeException("Parameters \"argon2.time\", \"argon2.memory\" and \"argon2.parallelism\" are either missing in the \"runtime.properties\" file or are not defined correctly"); - } catch (Exception e) { + if(configProp.getProperty("argon2.time") != null && configProp.getProperty("argon2.memory") !=null + && configProp.getProperty("argon2.parallelism")!=null) { + return argon2.hash(Integer.parseInt(configProp.getProperty("argon2.time")), + Integer.parseInt(configProp.getProperty("argon2.memory")), + Integer.parseInt(configProp.getProperty("argon2.parallelism")), raw); + } + else { + throw new RuntimeException("Parameters \"argon2.time\", \"argon2.memory\" " + + "and \"argon2.parallelism\" are either missing in the \"runtime.properties\"" + + " file or are not defined correctly"); + } + } + catch (Exception e) { // This can't happen with a normal Java runtime. throw new RuntimeException(e); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java index fc216dd2e..946e1ff6c 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/BasicAuthenticator.java @@ -100,7 +100,8 @@ public class BasicAuthenticator extends Authenticator { @Override public boolean md5HashIsNull(UserAccount userAccount){ - if(userAccount.getMd5Password().compareTo("")==0 || userAccount.getMd5Password()==null) + if(userAccount.getMd5Password().compareTo("")==0 || + userAccount.getMd5Password()==null) return true; else return false; @@ -109,19 +110,18 @@ public class BasicAuthenticator extends Authenticator { @Override public boolean isCurrentPasswordArgon2(UserAccount userAccount, - String clearTextPassword) { + String clearTextPassword) { if (userAccount == null) { return false; } if (clearTextPassword == null) { return false; } - - return verifyArgon2iHash(userAccount.getArgon2Password(),clearTextPassword); + return verifyArgon2iHash(userAccount.getArgon2Password(), + clearTextPassword); } - @Override public void recordNewPassword(UserAccount userAccount, String newClearTextPassword) { @@ -129,7 +129,8 @@ public class BasicAuthenticator extends Authenticator { log.error("Trying to change password on null user."); return; } - userAccount.setArgon2Password((applyArgon2iEncoding(newClearTextPassword))); + userAccount.setArgon2Password((applyArgon2iEncoding( + newClearTextPassword))); userAccount.setMd5Password(""); userAccount.setPasswordChangeRequired(false); userAccount.setPasswordLinkExpires(0L); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLogin.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLogin.java index acf33ae1e..3a241d965 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLogin.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLogin.java @@ -169,7 +169,6 @@ public class ProgramLogin extends HttpServlet { return false; else { userAccount.setPasswordChangeRequired(true); - // userAccount.setMd5Password(""); } } return true; diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/RestrictedAuthenticator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/RestrictedAuthenticator.java index 1a33c1647..1f6533f5c 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/RestrictedAuthenticator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/RestrictedAuthenticator.java @@ -78,7 +78,8 @@ public class RestrictedAuthenticator extends Authenticator { @Override public boolean md5HashIsNull(UserAccount userAccount){ - if(userAccount.getMd5Password().compareTo("")==0 || userAccount.getMd5Password()==null) + if(userAccount.getMd5Password().compareTo("")==0 || + userAccount.getMd5Password()==null) return true; else return false; @@ -94,8 +95,8 @@ public class RestrictedAuthenticator extends Authenticator { if (clearTextPassword == null) { return false; } - - return verifyArgon2iHash(userAccount.getArgon2Password(),clearTextPassword); + return verifyArgon2iHash(userAccount.getArgon2Password(), + clearTextPassword); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java index 6c957e070..8f19df8d5 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java @@ -339,21 +339,25 @@ public class Authenticate extends VitroHttpServlet { if(getAuthenticator(request).md5HashIsNull(user)) { - if (!getAuthenticator(request).isCurrentPasswordArgon2(user, password)) { - bean.setMessage(request, ERROR, "error_incorrect_credentials"); + if (!getAuthenticator(request) + .isCurrentPasswordArgon2(user, password)) { + bean.setMessage(request, ERROR, + "error_incorrect_credentials"); return; } } else { - if (!getAuthenticator(request).isCurrentPassword(user, password)) { - bean.setMessage(request, ERROR, "error_incorrect_credentials"); + if (!getAuthenticator(request) + .isCurrentPassword(user, password)) { + bean.setMessage(request, ERROR, + "error_incorrect_credentials"); return; } else { user.setPasswordChangeRequired(true); user.setMd5Password(""); } - } + } diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java index b0141d532..387b2e7e3 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java @@ -105,7 +105,8 @@ public class AuthenticatorStub extends Authenticator { @Override public boolean md5HashIsNull(UserAccount userAccount){ if(userAccount!=null) { - if (userAccount.getMd5Password().compareTo("") == 0 || userAccount.getMd5Password() == null) + if (userAccount.getMd5Password().compareTo("") == 0 || + userAccount.getMd5Password() == null) return true; else return false; @@ -123,8 +124,8 @@ public class AuthenticatorStub extends Authenticator { if (clearTextPassword == null) { return false; } - - return verifyArgon2iHash(userAccount.getArgon2Password(),clearTextPassword); + return verifyArgon2iHash(userAccount.getArgon2Password(), + clearTextPassword); } diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLoginTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLoginTest.java index d6aca919e..1a6138323 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLoginTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLoginTest.java @@ -100,7 +100,6 @@ public class ProgramLoginTest extends AbstractTestClass { .singleton(PermissionSets.URI_DBA)); user.setArgon2Password(Authenticator.applyArgon2iEncodingStub(password)); user.setMd5Password(""); - //user.setMd5Password(Authenticator.applyMd5Encoding(password)); user.setLoginCount(loginCount); user.setPasswordChangeRequired(loginCount == 0); return user; @@ -181,15 +180,12 @@ public class ProgramLoginTest extends AbstractTestClass { String newPassword) { if (email != null) { request.addParameter(PARAM_EMAIL_ADDRESS, email); - System.out.println("1"); } if (password != null) { request.addParameter(PARAM_PASSWORD, password); - System.out.println("2"); } if (newPassword != null) { request.addParameter(PARAM_NEW_PASSWORD, newPassword); - System.out.println("3"); } try { diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java index a1bad1d48..f918fe6a9 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java @@ -193,7 +193,6 @@ public class AuthenticateTest extends AbstractTestClass { user.setPermissionSetUris(userInfo.permissionSetUris); user.setArgon2Password(Authenticator.applyArgon2iEncodingStub(userInfo.password)); user.setMd5Password(""); - // user.setMd5Password(Authenticator.applyMd5Encoding(userInfo.password)); user.setLoginCount(userInfo.loginCount); user.setPasswordChangeRequired(userInfo.loginCount == 0); return user; diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJenaTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJenaTest.java index 13f241bd2..5f1e35992 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJenaTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJenaTest.java @@ -104,7 +104,7 @@ public class UserAccountsDaoJenaTest extends AbstractTestClass { 0L, false, 1, 0L, Status.ACTIVE, "bboop", false, EMPTY, false, collection(URI_PROFILE1, URI_PROFILE2)); userC = userAccount("", "ccallas@here", "Charlie", "Callas", "XXXX", "", - "YYYY", 0L, false, 1, 0L, Status.ACTIVE, "ccallas", false, + "YYYY", 0L, false, 1, 0L, Status.ACTIVE, "ccallas", false, EMPTY, false, collection(URI_PROFILE2)); } @@ -392,7 +392,6 @@ public class UserAccountsDaoJenaTest extends AbstractTestClass { ua.setLastName(lastName); ua.setArgon2Password(argon2Password); ua.setMd5Password(""); - //ua.setMd5Password(md5Password); ua.setOldPassword(oldPassword); ua.setPasswordLinkExpires(passwordLinkExpires); ua.setPasswordChangeRequired(passwordChangeRequired); diff --git a/home/src/main/resources/config/example.runtime.properties b/home/src/main/resources/config/example.runtime.properties index 96ebd027c..882026b55 100644 --- a/home/src/main/resources/config/example.runtime.properties +++ b/home/src/main/resources/config/example.runtime.properties @@ -78,15 +78,16 @@ VitroConnection.DataSource.validationQuery = SELECT 1 rootUser.emailAddress = root@myDomain.com # -# Argon2 password hashing parameters for time, memory and parallelism required to compute a hash. +# Argon2 password hashing parameters for time, memory and parallelism required to +# compute a hash. # -# A time cost defines the amount of computation realized and therefore the execution time, given in a number of iterations +# A time cost defines the amount of computation realized and therefore the execution +# time, given in a number of iterations. # A memory cost defines the memory usage, given in kibibytes # A parallelism degree defines the number of parallel threads -# For determining the optimal values of the parameters for your setup please refer to the white paper section 9 - https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf -# -# Warning: Please change the parameters only if you have installed a fresh installation of Vitro/Vivo and have not logged-in in the system yet. -# If you already have user accounts encrypted through these parameters please do not change them otherwise the existing users would not be able to log-in. +# For determining the optimal values of the parameters for your setup please refer to +# the white paper section 9 +# https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf # argon2.parallelism =1 argon2.memory = 1024 diff --git a/legacy/webapp/config/example.runtime.properties b/legacy/webapp/config/example.runtime.properties index 96ebd027c..882026b55 100644 --- a/legacy/webapp/config/example.runtime.properties +++ b/legacy/webapp/config/example.runtime.properties @@ -78,15 +78,16 @@ VitroConnection.DataSource.validationQuery = SELECT 1 rootUser.emailAddress = root@myDomain.com # -# Argon2 password hashing parameters for time, memory and parallelism required to compute a hash. +# Argon2 password hashing parameters for time, memory and parallelism required to +# compute a hash. # -# A time cost defines the amount of computation realized and therefore the execution time, given in a number of iterations +# A time cost defines the amount of computation realized and therefore the execution +# time, given in a number of iterations. # A memory cost defines the memory usage, given in kibibytes # A parallelism degree defines the number of parallel threads -# For determining the optimal values of the parameters for your setup please refer to the white paper section 9 - https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf -# -# Warning: Please change the parameters only if you have installed a fresh installation of Vitro/Vivo and have not logged-in in the system yet. -# If you already have user accounts encrypted through these parameters please do not change them otherwise the existing users would not be able to log-in. +# For determining the optimal values of the parameters for your setup please refer to +# the white paper section 9 +# https://github.com/P-H-C/phc-winner-argon2/blob/master/argon2-specs.pdf # argon2.parallelism =1 argon2.memory = 1024 From 96388c0951ea644d869ab69c1ed7bbbecbf984e9 Mon Sep 17 00:00:00 2001 From: AsimA Date: Tue, 22 May 2018 13:41:26 +0200 Subject: [PATCH 5/9] Removed the overloaded Argon2Encoding methods in Authenticator and moved the Argon2StubEncoding method to AuthenticatorStub --- .../webapp/auth/policy/RootUserPolicy.java | 2 +- .../authenticate/Authenticator.java | 89 +++++-------------- .../authenticate/AuthenticatorStub.java | 18 ++++ .../authenticate/ProgramLoginTest.java | 2 +- .../controller/edit/AuthenticateTest.java | 2 +- 5 files changed, 43 insertions(+), 70 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java index 62495e475..1ad842cec 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/auth/policy/RootUserPolicy.java @@ -150,7 +150,7 @@ public class RootUserPolicy implements PolicyIface { ua.setEmailAddress(configuredRootUser); ua.setFirstName("root"); ua.setLastName("user"); - ua.setArgon2Password(Authenticator.applyArgon2iEncoding(cp, + ua.setArgon2Password(Authenticator.applyArgon2iEncoding( ROOT_USER_INITIAL_PASSWORD)); ua.setMd5Password(""); ua.setPasswordChangeRequired(true); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java index 69242cc6f..5fa995f13 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/Authenticator.java @@ -10,7 +10,7 @@ import edu.cornell.mannlib.vitro.webapp.auth.identifier.IdentifierBundle; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; import org.apache.commons.codec.binary.Hex; - +import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.servlet.ServletContext; @@ -57,7 +57,7 @@ public abstract class Authenticator { * * If there is no factory, configure a Basic one. */ - private static ConfigurationProperties cp; + public static Authenticator getInstance(HttpServletRequest request) { ServletContext ctx = request.getSession().getServletContext(); Object attribute = ctx.getAttribute(FACTORY_ATTRIBUTE_NAME); @@ -66,7 +66,6 @@ public abstract class Authenticator { attribute = ctx.getAttribute(FACTORY_ATTRIBUTE_NAME); } AuthenticatorFactory factory = (AuthenticatorFactory) attribute; - cp = ConfigurationProperties.getBean(ctx); return factory.getInstance(request); } @@ -200,80 +199,36 @@ public abstract class Authenticator { } } - /** - * Applies Argon2i hashing on a string. - * Used by tests only with pre-specified values because the configuration - * properties (runtime.properties) is not set at compile time. - **/ - public static String applyArgon2iEncodingStub(String raw) { - Argon2 argon2 = Argon2Factory.create(); - try { - return argon2.hash(200, 500, 1, raw); - } catch (Exception e) { - // This can't happen with a normal Java runtime. - throw new RuntimeException(e); - } - } + /** + * Applies Argon2i hashing on a string. Obtains the argon2i parameters + * from the configuration properties specified in the runtime.properties + * through this class "Authenticator". + **/ - /** - * Applies Argon2i hashing on a string. Obtains the argon2i parameters - * from the configuration properties specified in the runtime.properties - * through this class "Authenticator". - **/ public static String applyArgon2iEncoding(String raw) { + ServletContext ctx = ApplicationUtils.instance().getServletContext(); + ConfigurationProperties configProp = ConfigurationProperties.getBean(ctx); + Argon2 argon2 = Argon2Factory.create(); - try { - if(cp.getProperty("argon2.time") != null && cp.getProperty("argon2.memory") !=null - && cp.getProperty("argon2.parallelism")!=null) { - return argon2.hash(Integer.parseInt(cp.getProperty("argon2.time")), - Integer.parseInt(cp.getProperty("argon2.memory")), - Integer.parseInt(cp.getProperty("argon2.parallelism")), raw); - } - else { - throw new RuntimeException("Parameters \"argon2.time\", \"argon2.memory\" " + - "and \"argon2.parallelism\" are either missing in the \"runtime.properties\"" + - " file or are not defined correctly"); - } - } - catch (Exception e) { - // This can't happen with a normal Java runtime. - throw new RuntimeException(e); + if (configProp.getProperty("argon2.time") != null + && configProp.getProperty("argon2.memory") != null + && configProp.getProperty("argon2.parallelism") != null) { + return argon2.hash( + Integer.parseInt(configProp.getProperty("argon2.time")), + Integer.parseInt(configProp.getProperty("argon2.memory")), + Integer.parseInt(configProp.getProperty("argon2.parallelism")), raw); + } else { + throw new RuntimeException( + "Parameters \"argon2.time\", \"argon2.memory\" and " + + "\"argon2.parallelism\" are either missing in the " + + "\"runtime.properties\" file or are not defined correctly"); } } - /** - * Applies Argon2i hashing on a string. - * When Vivo/Vitro is run for the first time the application needs to set - * the "root" account before a call is made to this class (Authenticator). - * In that case the configuration properties are passed along with the - * password string to this method. - **/ - - public static String applyArgon2iEncoding(ConfigurationProperties configProp, String raw) { - Argon2 argon2 = Argon2Factory.create(); - try { - if(configProp.getProperty("argon2.time") != null && configProp.getProperty("argon2.memory") !=null - && configProp.getProperty("argon2.parallelism")!=null) { - return argon2.hash(Integer.parseInt(configProp.getProperty("argon2.time")), - Integer.parseInt(configProp.getProperty("argon2.memory")), - Integer.parseInt(configProp.getProperty("argon2.parallelism")), raw); - } - else { - throw new RuntimeException("Parameters \"argon2.time\", \"argon2.memory\" " + - "and \"argon2.parallelism\" are either missing in the \"runtime.properties\"" + - " file or are not defined correctly"); - } - } - catch (Exception e) { - // This can't happen with a normal Java runtime. - throw new RuntimeException(e); - } - } - /** Verifies the string against the Argon2i hash stored for a user account */ diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java index 387b2e7e3..025218b3d 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/AuthenticatorStub.java @@ -9,6 +9,8 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; +import de.mkammerer.argon2.Argon2; +import de.mkammerer.argon2.Argon2Factory; import edu.cornell.mannlib.vedit.beans.LoginStatusBean; import edu.cornell.mannlib.vedit.beans.LoginStatusBean.AuthenticationSource; import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; @@ -114,6 +116,22 @@ public class AuthenticatorStub extends Authenticator { return false; } + /** + * Applies Argon2i hashing on a string. + * Used by tests only with pre-specified values because the configuration + * properties (runtime.properties) is not set at compile time. + **/ + + public static String applyArgon2iEncodingStub(String raw) { + Argon2 argon2 = Argon2Factory.create(); + try { + return argon2.hash(200, 500, 1, raw); + } catch (Exception e) { + // This can't happen with a normal Java runtime. + throw new RuntimeException(e); + } + } + @Override public boolean isCurrentPasswordArgon2(UserAccount userAccount, diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLoginTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLoginTest.java index 1a6138323..01280f6b5 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLoginTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/authenticate/ProgramLoginTest.java @@ -98,7 +98,7 @@ public class ProgramLoginTest extends AbstractTestClass { user.setUri(uri); user.setPermissionSetUris(Collections .singleton(PermissionSets.URI_DBA)); - user.setArgon2Password(Authenticator.applyArgon2iEncodingStub(password)); + user.setArgon2Password(AuthenticatorStub.applyArgon2iEncodingStub(password)); user.setMd5Password(""); user.setLoginCount(loginCount); user.setPasswordChangeRequired(loginCount == 0); diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java index f918fe6a9..db160e00a 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/edit/AuthenticateTest.java @@ -191,7 +191,7 @@ public class AuthenticateTest extends AbstractTestClass { user.setEmailAddress(userInfo.username); user.setUri(userInfo.uri); user.setPermissionSetUris(userInfo.permissionSetUris); - user.setArgon2Password(Authenticator.applyArgon2iEncodingStub(userInfo.password)); + user.setArgon2Password(AuthenticatorStub.applyArgon2iEncodingStub(userInfo.password)); user.setMd5Password(""); user.setLoginCount(userInfo.loginCount); user.setPasswordChangeRequired(userInfo.loginCount == 0); From 1e231013b0c22735639417fc49a19135a24d3983 Mon Sep 17 00:00:00 2001 From: AsimA Date: Tue, 22 May 2018 14:57:42 +0200 Subject: [PATCH 6/9] Updated the tests to store argon2 as well as md5password --- .../webapp/controller/accounts/UserAccountsSelector.java | 9 +++++---- .../controller/accounts/UserAccountsSelectorTest.java | 7 ++++--- .../vitro/webapp/dao/jena/UserAccountsDaoJenaTest.java | 2 +- .../controller/accounts/UserAccountsSelectorTest.n3 | 2 ++ 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java index e2ac96c16..6caadf24c 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelector.java @@ -37,7 +37,7 @@ public class UserAccountsSelector { + "PREFIX auth: \n"; private static final String ALL_VARIABLES = "?uri ?email ?firstName " - + "?lastName ?pwd ?expire ?count ?lastLogin ?status ?isRoot"; + + "?lastName ?md5pwd ?a2pwd ?expire ?count ?lastLogin ?status ?isRoot"; private static final String COUNT_VARIABLE = "?uri"; @@ -158,7 +158,8 @@ public class UserAccountsSelector { private String optionalClauses() { return "OPTIONAL { ?uri auth:firstName ?firstName } \n" + " OPTIONAL { ?uri auth:lastName ?lastName } \n" - + " OPTIONAL { ?uri auth:md5password ?pwd } \n" + + " OPTIONAL { ?uri auth:md5password ?md5pwd } \n" + + " OPTIONAL { ?uri auth:argon2password ?a2pwd } \n" + " OPTIONAL { ?uri auth:passwordChangeExpires ?expire } \n" + " OPTIONAL { ?uri auth:loginCount ?count } \n" + " OPTIONAL { ?uri auth:lastLoginTime ?lastLogin } \n" @@ -245,8 +246,8 @@ public class UserAccountsSelector { user.setEmailAddress(solution.getLiteral("email").getString()); user.setFirstName(ifLiteralPresent(solution, "firstName", "")); user.setLastName(ifLiteralPresent(solution, "lastName", "")); - user.setMd5Password(ifLiteralPresent(solution, "pwd", "")); - user.setArgon2Password(ifLiteralPresent(solution, "pwd", "")); + user.setMd5Password(ifLiteralPresent(solution, "md5pwd", "")); + user.setArgon2Password(ifLiteralPresent(solution, "a2pwd", "")); user.setPasswordLinkExpires(ifLongPresent(solution, "expire", 0L)); user.setLoginCount(ifIntPresent(solution, "count", 0)); user.setLastLoginTime(ifLongPresent(solution, "lastLogin", 0)); diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.java index b58b596c1..a66c5998e 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.java @@ -81,8 +81,8 @@ public class UserAccountsSelectorTest extends AbstractTestClass { assertEquals("email", "email@jones.edu", acct.getEmailAddress()); assertEquals("firstName", "Bob", acct.getFirstName()); assertEquals("lastName", "Caruso", acct.getLastName()); - assertEquals("password", "garbage", acct.getMd5Password()); - assertEquals("expires", 1100234965897L, acct.getPasswordLinkExpires()); + assertEquals("md5password", "garbage", acct.getMd5Password()); + assertEquals("argon2password", "betterGarbage", acct.getArgon2Password()); assertEquals("loginCount", 50, acct.getLoginCount()); assertEquals("lastLogin", 1020304050607080L, acct.getLastLoginTime()); assertEquals("status", UserAccount.Status.ACTIVE, acct.getStatus()); @@ -105,7 +105,8 @@ public class UserAccountsSelectorTest extends AbstractTestClass { assertEquals("email", "email@henry.edu", acct.getEmailAddress()); assertEquals("firstName", "Mary", acct.getFirstName()); assertEquals("lastName", "McInerney", acct.getLastName()); - assertEquals("password", "garbage", acct.getMd5Password()); + assertEquals("md5password", "garbage", acct.getMd5Password()); + assertEquals("argon2password", "betterGarbage", acct.getArgon2Password()); assertEquals("expires", 0L, acct.getPasswordLinkExpires()); assertEquals("loginCount", 7, acct.getLoginCount()); assertEquals("lastLogin", 1122334455667788L, acct.getLastLoginTime()); diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJenaTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJenaTest.java index 5f1e35992..9e18f5603 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJenaTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/dao/jena/UserAccountsDaoJenaTest.java @@ -391,7 +391,7 @@ public class UserAccountsDaoJenaTest extends AbstractTestClass { ua.setFirstName(firstName); ua.setLastName(lastName); ua.setArgon2Password(argon2Password); - ua.setMd5Password(""); + ua.setMd5Password(md5Password); ua.setOldPassword(oldPassword); ua.setPasswordLinkExpires(passwordLinkExpires); ua.setPasswordChangeRequired(passwordChangeRequired); diff --git a/api/src/test/resources/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.n3 b/api/src/test/resources/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.n3 index 45f4cfd47..95307fd2e 100644 --- a/api/src/test/resources/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.n3 +++ b/api/src/test/resources/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.n3 @@ -113,6 +113,7 @@ mydomain:user08 auth:firstName "Mary" ; auth:lastName "McInerney" ; auth:md5password "garbage" ; + auth:argon2password "betterGarbage" ; auth:passwordChangeExpires 0 ; auth:loginCount 7 ; auth:lastLoginTime 1122334455667788 ; @@ -138,6 +139,7 @@ mydomain:user10 auth:firstName "Bob" ; auth:lastName "Caruso" ; auth:md5password "garbage" ; + auth:argon2password "betterGarbage" ; auth:passwordChangeExpires 1100234965897 ; auth:loginCount 50 ; auth:lastLoginTime 1020304050607080 ; From fcaf3155494dcada61045057e46c2e540376a783 Mon Sep 17 00:00:00 2001 From: AsimA Date: Tue, 22 May 2018 15:55:00 +0200 Subject: [PATCH 7/9] added smokeTests for argon2 parameters --- .../ConfigurationPropertiesSmokeTests.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java index e5d92aeeb..72b96ccc7 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/config/ConfigurationPropertiesSmokeTests.java @@ -29,6 +29,9 @@ public class ConfigurationPropertiesSmokeTests implements private static final String PROPERTY_LANGUAGE_SELECTABLE = "languages.selectableLocales"; private static final String PROPERTY_LANGUAGE_FORCE = "languages.forceLocale"; private static final String PROPERTY_LANGUAGE_FILTER = "RDFService.languageFilter"; + private static final String PROPERTY_ARGON2_TIME = "argon2.time"; + private static final String PROPERTY_ARGON2_MEMORY = "argon2.memory"; + private static final String PROPERTY_ARGON2_PARALLELISM = "argon2.parallelism"; @Override public void contextInitialized(ServletContextEvent sce) { @@ -38,6 +41,7 @@ public class ConfigurationPropertiesSmokeTests implements checkDefaultNamespace(ctx, props, ss); checkLanguages(props, ss); + checkEncryptionParameters(props, ss); } /** @@ -122,6 +126,26 @@ public class ConfigurationPropertiesSmokeTests implements } } + /** + * Fail if there are no config properties for the Argon2 encryption. + */ + private void checkEncryptionParameters(ConfigurationProperties props, + StartupStatus ss) { + failIfNotPresent(props, ss, PROPERTY_ARGON2_TIME); + failIfNotPresent(props, ss, PROPERTY_ARGON2_MEMORY); + failIfNotPresent(props, ss, PROPERTY_ARGON2_PARALLELISM); + } + + private void failIfNotPresent(ConfigurationProperties props, + StartupStatus ss, String name) { + String value = props.getProperty(name); + if (value == null || value.isEmpty()) { + ss.fatal(this, "runtime.properties does not contain a value for '" + + name + "'"); + return; + } + } + @Override public void contextDestroyed(ServletContextEvent sce) { // nothing to do at shutdown From fea33a456a8755efebaaf4737526a1487ade3608 Mon Sep 17 00:00:00 2001 From: AsimA Date: Wed, 23 May 2018 11:25:58 +0200 Subject: [PATCH 8/9] Fixed the user experience --- api/pom.xml | 2 +- .../mannlib/vitro/webapp/controller/edit/Authenticate.java | 7 +++++-- .../controller/accounts/UserAccountsSelectorTest.java | 1 + webapp/pom.xml | 6 +++--- webapp/src/main/webapp/i18n/all.properties | 2 ++ 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/api/pom.xml b/api/pom.xml index a86d7b9ac..f000f3c29 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -61,7 +61,7 @@ org.vivoweb vitro-dependencies - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT pom diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java index 8f19df8d5..3637c3f29 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java @@ -23,6 +23,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import com.mysql.cj.api.x.core.Warning; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -354,8 +355,10 @@ public class Authenticate extends VitroHttpServlet { return; } else { - user.setPasswordChangeRequired(true); - user.setMd5Password(""); + user.setPasswordChangeRequired(true); + user.setMd5Password(""); + bean.setMessage(request, ERROR, + "password_system_has_changed"); } } diff --git a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.java b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.java index a66c5998e..129442d44 100644 --- a/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.java +++ b/api/src/test/java/edu/cornell/mannlib/vitro/webapp/controller/accounts/UserAccountsSelectorTest.java @@ -83,6 +83,7 @@ public class UserAccountsSelectorTest extends AbstractTestClass { assertEquals("lastName", "Caruso", acct.getLastName()); assertEquals("md5password", "garbage", acct.getMd5Password()); assertEquals("argon2password", "betterGarbage", acct.getArgon2Password()); + assertEquals("expires", 1100234965897L, acct.getPasswordLinkExpires()); assertEquals("loginCount", 50, acct.getLoginCount()); assertEquals("lastLogin", 1020304050607080L, acct.getLastLoginTime()); assertEquals("status", UserAccount.Status.ACTIVE, acct.getStatus()); diff --git a/webapp/pom.xml b/webapp/pom.xml index f2e8afc94..b407d9cbf 100644 --- a/webapp/pom.xml +++ b/webapp/pom.xml @@ -7,13 +7,13 @@ org.vivoweb vitro-webapp - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT war org.vivoweb vitro-project - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT .. @@ -41,7 +41,7 @@ org.vivoweb vitro-api - 2.0.0-SNAPSHOT + 1.10.0-SNAPSHOT diff --git a/webapp/src/main/webapp/i18n/all.properties b/webapp/src/main/webapp/i18n/all.properties index b25b63184..47ea21baf 100644 --- a/webapp/src/main/webapp/i18n/all.properties +++ b/webapp/src/main/webapp/i18n/all.properties @@ -123,6 +123,8 @@ error_no_new_password = Please enter your new password. error_passwords_dont_match = The passwords entered do not match. error_password_length = Please enter a password between {0} and {1} characters in length. error_previous_password = Your new password cannot match the current one. +password_system_has_changed = Our password system has been upgraded to make it more secure. \ +Please enter a new password. search_accounts_button = Search accounts accounts_search_results = Search results for From df58f2d18c99b60ed5a6bece95a2ac9870af8d2d Mon Sep 17 00:00:00 2001 From: AsimA Date: Wed, 23 May 2018 11:28:35 +0200 Subject: [PATCH 9/9] remvoed the unused import --- .../mannlib/vitro/webapp/controller/edit/Authenticate.java | 1 - 1 file changed, 1 deletion(-) diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java index 3637c3f29..ce002659b 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/controller/edit/Authenticate.java @@ -23,7 +23,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import com.mysql.cj.api.x.core.Warning; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;