Index: lams_central/conf/language/lams/ApplicationResources_en_AU.properties =================================================================== RCS file: /usr/local/cvsroot/lams_central/conf/language/lams/ApplicationResources_en_AU.properties,v diff -u -r1.111.2.9 -r1.111.2.10 --- lams_central/conf/language/lams/ApplicationResources_en_AU.properties 11 May 2016 07:07:56 -0000 1.111.2.9 +++ lams_central/conf/language/lams/ApplicationResources_en_AU.properties 26 Aug 2016 15:02:59 -0000 1.111.2.10 @@ -1,9 +1,6 @@ appName = lams_central #language code: en -#locale code: AU - - - +#locale code: AU #=================== labels for LAMS Central =================# label.username =Username @@ -672,4 +669,9 @@ label.private.notifications.read.hint =Mark notification as read label.private.notifications.read.all.hint =Mark all notifications as read +label.verification.code =Verification code +error.verification.code =Sorry, entered verification code is incorrect. Please try again. +label.your.new.shared.secret =Your new shared secret: {0} +label.2FA.shared.secret =Two-factor authorization shared secret + #======= End labels: Exported 439 labels for en AU ===== \ No newline at end of file Index: lams_central/src/java/org/lamsfoundation/lams/web/IndexAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/web/IndexAction.java,v diff -u -r1.54.2.7 -r1.54.2.8 --- lams_central/src/java/org/lamsfoundation/lams/web/IndexAction.java 5 May 2016 08:09:45 -0000 1.54.2.7 +++ lams_central/src/java/org/lamsfoundation/lams/web/IndexAction.java 26 Aug 2016 15:02:59 -0000 1.54.2.8 @@ -53,40 +53,16 @@ import org.springframework.web.context.support.WebApplicationContextUtils; /** - * @version * - *

- * View Source - *

- * * @author Fei Yang - * - * Created at 16:59:28 on 13/06/2006 */ -/** - * struts doclet - * - * - * - * - * - * - * - * - * - * - * - */ public class IndexAction extends Action { private static final String PATH_PEDAGOGICAL_PLANNER = "pedagogical_planner"; private static final String PATH_LAMS_CENTRAL = "lams-central.war"; private static Logger log = Logger.getLogger(IndexAction.class); private static IUserManagementService userManagementService; - private static IExportToolContentService exportService; - private static IAuthoringService authoringService; - private static Configuration configurationService; @Override @SuppressWarnings("unchecked") @@ -110,11 +86,14 @@ // check if user is flagged as needing to change their password User loggedInUser = getUserManagementService().getUserByLogin(request.getRemoteUser()); - if (loggedInUser.getChangePassword() != null) { - if (loggedInUser.getChangePassword()) { - return mapping.findForward("password"); - } + if (loggedInUser.getChangePassword() != null && loggedInUser.getChangePassword()) { + return mapping.findForward("password"); } + + // check if user needs to get his shared two-factor authorization secret + if (loggedInUser.isTwoFactorAuthenticationEnabled() && loggedInUser.getTwoFactorAuthenticationSecret() == null) { + return mapping.findForward("twoFactorAuthentication"); + } User user = getUserManagementService().getUserByLogin(userDTO.getLogin()); request.setAttribute("portraitUuid", user.getPortraitUuid()); Index: lams_central/src/java/org/lamsfoundation/lams/web/PasswordAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/web/PasswordAction.java,v diff -u -r1.3.22.3 -r1.3.22.4 --- lams_central/src/java/org/lamsfoundation/lams/web/PasswordAction.java 11 May 2016 07:07:58 -0000 1.3.22.3 +++ lams_central/src/java/org/lamsfoundation/lams/web/PasswordAction.java 26 Aug 2016 15:02:59 -0000 1.3.22.4 @@ -21,7 +21,6 @@ * **************************************************************** */ - package org.lamsfoundation.lams.web; import javax.servlet.http.HttpServletRequest; @@ -34,13 +33,6 @@ /** * @author jliew - * - * - * - * - * - * - * */ public class PasswordAction extends Action { Index: lams_central/src/java/org/lamsfoundation/lams/web/ProfileAction.java =================================================================== RCS file: /usr/local/cvsroot/lams_central/src/java/org/lamsfoundation/lams/web/ProfileAction.java,v diff -u -r1.25.2.3 -r1.25.2.4 --- lams_central/src/java/org/lamsfoundation/lams/web/ProfileAction.java 5 May 2016 08:09:45 -0000 1.25.2.3 +++ lams_central/src/java/org/lamsfoundation/lams/web/ProfileAction.java 26 Aug 2016 15:02:58 -0000 1.25.2.4 @@ -66,24 +66,9 @@ import org.springframework.web.context.support.WebApplicationContextUtils; /** - * @version * - *

- * View Source - *

- * * @author Fei Yang - * - * Created at 14:21:53 on 28/06/2006 */ - -/** - * - * - * - * - * - */ public class ProfileAction extends LamsDispatchAction { private static Logger log = Logger.getLogger(ProfileAction.class); @@ -229,6 +214,9 @@ } userForm.set("localeId", locale.getLocaleId()); request.setAttribute("locales", locales); + if (requestor.isTwoFactorAuthenticationEnabled()) { + request.setAttribute("sharedSecret", requestor.getTwoFactorAuthenticationSecret()); + } request.setAttribute("tab", "profile"); boolean hasLamsCommunityToken = requestor.getLamsCommunityToken() != null; Fisheye: Tag 1.1 refers to a dead (removed) revision in file `lams_central/src/java/org/lamsfoundation/lams/web/action/TwoFactorAuthenticationAction.java'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_central/web/editprofile.jsp =================================================================== RCS file: /usr/local/cvsroot/lams_central/web/editprofile.jsp,v diff -u -r1.23.2.1 -r1.23.2.2 --- lams_central/web/editprofile.jsp 16 Mar 2016 12:13:54 -0000 1.23.2.1 +++ lams_central/web/editprofile.jsp 26 Aug 2016 15:02:59 -0000 1.23.2.2 @@ -157,6 +157,15 @@ + + + : + + ${sharedSecret} + + + + Fisheye: Tag 1.1 refers to a dead (removed) revision in file `lams_central/web/loginTwoFactorAuth.jsp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1.1 refers to a dead (removed) revision in file `lams_central/web/twoFactorAuthSecret.jsp'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_central/web/WEB-INF/struts-config.xml =================================================================== RCS file: /usr/local/cvsroot/lams_central/web/WEB-INF/Attic/struts-config.xml,v diff -u -r1.1.2.1 -r1.1.2.2 --- lams_central/web/WEB-INF/struts-config.xml 27 Apr 2016 13:22:51 -0000 1.1.2.1 +++ lams_central/web/WEB-INF/struts-config.xml 26 Aug 2016 15:02:59 -0000 1.1.2.2 @@ -149,6 +149,11 @@ redirect="false" /> + + + + + + + + + Index: lams_central/web/WEB-INF/web.xml =================================================================== RCS file: /usr/local/cvsroot/lams_central/web/WEB-INF/Attic/web.xml,v diff -u -r1.51.2.21 -r1.51.2.22 --- lams_central/web/WEB-INF/web.xml 19 Aug 2016 00:55:55 -0000 1.51.2.21 +++ lams_central/web/WEB-INF/web.xml 26 Aug 2016 15:02:59 -0000 1.51.2.22 @@ -665,6 +665,7 @@ /forgotPassword.jsp /forgotPasswordChange.jsp /forgotPasswordProc.jsp + /loginTwoFactorAuth.jsp /signup/* /rest/* /runtimeStats Index: lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/User.hbm.xml =================================================================== RCS file: /usr/local/cvsroot/lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/User.hbm.xml,v diff -u -r1.35.2.9 -r1.35.2.10 --- lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/User.hbm.xml 9 May 2016 14:27:14 -0000 1.35.2.9 +++ lams_common/conf/hibernate/mappings/org/lamsfoundation/lams/usermanagement/User.hbm.xml 26 Aug 2016 15:03:05 -0000 1.35.2.10 @@ -58,6 +58,24 @@ not-null="false" + + + @hibernate.property + column="two_factor_auth_enabled" + length="1" + not-null="true" + + + + + @hibernate.property + column="two_factor_auth_secret" + length="64" + not-null="true" + + Fisheye: Tag 1.1 refers to a dead (removed) revision in file `lams_common/src/java/org/lamsfoundation/lams/dbupdates/patch2040067.sql'. Fisheye: No comparison available. Pass `N' to diff? Index: lams_common/src/java/org/lamsfoundation/lams/integration/security/SsoHandler.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/integration/security/Attic/SsoHandler.java,v diff -u -r1.1.2.19 -r1.1.2.20 --- lams_common/src/java/org/lamsfoundation/lams/integration/security/SsoHandler.java 18 Aug 2016 14:09:16 -0000 1.1.2.19 +++ lams_common/src/java/org/lamsfoundation/lams/integration/security/SsoHandler.java 26 Aug 2016 15:03:05 -0000 1.1.2.20 @@ -25,9 +25,11 @@ import javax.servlet.ServletContext; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.math.NumberUtils; import org.lamsfoundation.lams.usermanagement.User; import org.lamsfoundation.lams.usermanagement.dto.UserDTO; import org.lamsfoundation.lams.usermanagement.service.IUserManagementService; @@ -37,6 +39,8 @@ import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; +import com.warrenstrange.googleauth.GoogleAuthenticator; + import io.undertow.Handlers; import io.undertow.server.session.Session; import io.undertow.servlet.ServletExtension; @@ -96,6 +100,35 @@ User user = getUserManagementService(session.getServletContext()).getUserByLogin(login); if (user != null) { userDTO = user.getUserDTO(); + + // if user is not yet authorized and has 2FA shared secret set up - redirect him to + // loginTwoFactorAuth.jsp to prompt user to enter his verification code (Time-based One-time Password) + if (request.getRemoteUser() == null && user.isTwoFactorAuthenticationEnabled() + && user.getTwoFactorAuthenticationSecret() != null) { + String verificationCodeStr = request.getParameter("verificationCode"); + int verificationCode = NumberUtils.toInt(verificationCodeStr); + GoogleAuthenticator gAuth = new GoogleAuthenticator(); + boolean isCodeValid = gAuth.authorize(user.getTwoFactorAuthenticationSecret(), + verificationCode); + + //user entered correct TOTP password + if (isCodeValid) { + //do nothing and let regular login to happen + + //user hasn't yet entered TOTP password (request came from login.jsp) or entered the wrong one + } else { + session.setAttribute("login", login); + String password = request.getParameter("j_password"); + session.setAttribute("password", password); + + //verificationCodeStr equals null in case request came from login.jsp + String redirectUrl = "/lams/loginTwoFactorAuth.jsp" + ((verificationCodeStr == null) ? "" : "?failed=true" ); + HttpServletResponse response = (HttpServletResponse) context.getServletResponse(); + response.sendRedirect(redirectUrl); + return; + } + + } } } Index: lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java,v diff -u -r1.50.2.8 -r1.50.2.9 --- lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java 11 May 2016 07:07:23 -0000 1.50.2.8 +++ lams_common/src/java/org/lamsfoundation/lams/usermanagement/User.java 26 Aug 2016 15:03:05 -0000 1.50.2.9 @@ -53,6 +53,10 @@ * persistent field */ private String password; + + private Boolean twoFactorAuthenticationEnabled; + + private String twoFactorAuthenticationSecret; /** * persistent field @@ -172,6 +176,7 @@ /** default constructor */ public User() { changePassword = false; + twoFactorAuthenticationEnabled = false; } public Integer getUserId() { @@ -205,7 +210,23 @@ public void setSalt(String salt) { this.salt = salt; } + + public Boolean isTwoFactorAuthenticationEnabled() { + return twoFactorAuthenticationEnabled; + } + public void setTwoFactorAuthenticationEnabled(Boolean twoFactorAuthenticationEnabled) { + this.twoFactorAuthenticationEnabled = twoFactorAuthenticationEnabled; + } + + public String getTwoFactorAuthenticationSecret() { + return twoFactorAuthenticationSecret; + } + + public void setTwoFactorAuthenticationSecret(String twoFactorAuthenticationSecret) { + this.twoFactorAuthenticationSecret = twoFactorAuthenticationSecret; + } + public String getTitle() { return title; }