Index: oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserAuthentication.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserAuthentication.java (revision 1628650) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserAuthentication.java (revision ) @@ -118,6 +118,10 @@ } checkSuccess(success, "UserId/Password mismatch."); + // change the password if the credentials object has the UserConstants.CREDENTIALS_ATTRIBUTE_NEWPASSWORD + // attribute set + changePassword(user, creds); + if (isPasswordExpired(user)) { throw new CredentialExpiredException("User password has expired"); } @@ -140,6 +144,18 @@ private static void checkSuccess(boolean success, String msg) throws LoginException { if (!success) { throw new FailedLoginException(msg); + } + } + + private static void changePassword(User user, SimpleCredentials credentials) throws RepositoryException { + Object newPasswordObject = credentials.getAttribute(CREDENTIALS_ATTRIBUTE_NEWPASSWORD); + if (null != newPasswordObject && newPasswordObject instanceof String) { + log.debug("User " + user.getID() + ": new password attribute set"); + String newPassword = (String) newPasswordObject; + if (newPassword.length() > 0) { + user.changePassword(newPassword); + log.debug("User " + user.getID() + ": changed user password"); + } } } \ No newline at end of file Index: oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordExpiryTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordExpiryTest.java (revision 1628650) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/PasswordExpiryTest.java (revision ) @@ -129,6 +129,22 @@ } @Test + public void testAuthenticatePasswordExpiredThenChanged() throws Exception { + Authentication a = new UserAuthentication(getUserConfiguration(), root, userId); + // set password last modified to beginning of epoch + root.getTree(getTestUser().getPath()).getChild(UserConstants.REP_PWD).setProperty(UserConstants.REP_PASSWORD_LAST_MODIFIED, 0); + root.commit(); + try { + SimpleCredentials creds = new SimpleCredentials(userId, userId.toCharArray()); + creds.setAttribute(UserConstants.CREDENTIALS_ATTRIBUTE_NEWPASSWORD, userId); + a.authenticate(creds); + // success + } catch (CredentialExpiredException e) { + fail("Credentials should not be expired"); + } + } + + @Test public void testAuthenticateBeforePasswordExpired() throws Exception { Authentication a = new UserAuthentication(getUserConfiguration(), root, userId); // set password last modified to beginning of epoch Index: oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserConstants.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserConstants.java (revision 1628650) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserConstants.java (revision ) @@ -222,4 +222,10 @@ * Default value for {@link #PARAM_PASSWORD_INITIAL_CHANGE} */ boolean DEFAULT_PASSWORD_INITIAL_CHANGE = false; + + /** + * Name of the {@link javax.jcr.SimpleCredentials} attribute containing the new password. + * This may be used change the password via the credentials object. + */ + String CREDENTIALS_ATTRIBUTE_NEWPASSWORD = "newPassword"; }