Search in sources :

Example 1 with ContextAuthenticationException

use of org.openmrs.api.context.ContextAuthenticationException in project openmrs-core by openmrs.

the class BaseContextSensitiveTest method authenticate.

/**
 * Authenticate to the Context. A popup box will appear asking the current user to enter
 * credentials unless there is a junit.username and junit.password defined in the runtime
 * properties
 *
 * @throws Exception
 */
public void authenticate() {
    if (Context.isAuthenticated() && Context.getAuthenticatedUser().equals(authenticatedUser)) {
        return;
    }
    try {
        Context.authenticate("admin", "test");
        authenticatedUser = Context.getAuthenticatedUser();
        return;
    } catch (ContextAuthenticationException wrongCredentialsError) {
        if (useInMemoryDatabase()) {
            // if we get here the user is using some database other than the standard
            // in-memory database, prompt the user for input
            log.error("For some reason we couldn't auth as admin:test ?!", wrongCredentialsError);
        }
    }
    Integer attempts = 0;
    // TODO: how to make this a locale specific message for the user to see?
    String message = null;
    // only need to authenticate once per session
    while (!Context.isAuthenticated() && attempts < 3) {
        // look in the runtime properties for a defined username and
        // password first
        String junitusername = null;
        String junitpassword = null;
        try {
            Properties props = this.getRuntimeProperties();
            junitusername = props.getProperty("junit.username");
            junitpassword = props.getProperty("junit.password");
        } catch (Exception e) {
        // if anything happens just default to asking the user
        }
        String[] credentials = null;
        // in the runtime properties or if that username/pass failed already
        if (junitusername == null || junitpassword == null || attempts > 0) {
            credentials = askForUsernameAndPassword(message);
            // credentials are null if the user clicked "cancel" in popup
            if (credentials == null)
                return;
        } else
            credentials = new String[] { junitusername, junitpassword };
        // popup
        try {
            Context.authenticate(credentials[0], credentials[1]);
            authenticatedUser = Context.getAuthenticatedUser();
        } catch (ContextAuthenticationException e) {
            message = "Invalid username/password.  Try again.";
        }
        attempts++;
    }
}
Also used : ContextAuthenticationException(org.openmrs.api.context.ContextAuthenticationException) Properties(java.util.Properties) DatabaseUnitRuntimeException(org.dbunit.DatabaseUnitRuntimeException) ContextAuthenticationException(org.openmrs.api.context.ContextAuthenticationException) FileNotFoundException(java.io.FileNotFoundException) DataSetException(org.dbunit.dataset.DataSetException) SQLException(java.sql.SQLException) DatabaseUnitException(org.dbunit.DatabaseUnitException) IOException(java.io.IOException)

Example 2 with ContextAuthenticationException

use of org.openmrs.api.context.ContextAuthenticationException in project openmrs-core by openmrs.

the class HibernateContextDAO method authenticate.

/**
 * @see org.openmrs.api.db.ContextDAO#authenticate(java.lang.String, java.lang.String)
 */
@Override
@Transactional(noRollbackFor = ContextAuthenticationException.class)
public User authenticate(String login, String password) throws ContextAuthenticationException {
    String errorMsg = "Invalid username and/or password: " + login;
    Session session = sessionFactory.getCurrentSession();
    User candidateUser = null;
    if (login != null) {
        // if username is blank or white space character(s)
        if (StringUtils.isEmpty(login) || StringUtils.isWhitespace(login)) {
            throw new ContextAuthenticationException(errorMsg);
        }
        // loginWithoutDash is used to compare to the system id
        String loginWithDash = login;
        if (login.matches("\\d{2,}")) {
            loginWithDash = login.substring(0, login.length() - 1) + "-" + login.charAt(login.length() - 1);
        }
        try {
            candidateUser = (User) session.createQuery("from User u where (u.username = ? or u.systemId = ? or u.systemId = ?) and u.retired = '0'").setString(0, login).setString(1, login).setString(2, loginWithDash).uniqueResult();
        } catch (HibernateException he) {
            log.error("Got hibernate exception while logging in: '" + login + "'", he);
        } catch (Exception e) {
            log.error("Got regular exception while logging in: '" + login + "'", e);
        }
    }
    // only continue if this is a valid username and a nonempty password
    if (candidateUser != null && password != null) {
        if (log.isDebugEnabled()) {
            log.debug("Candidate user id: " + candidateUser.getUserId());
        }
        String lockoutTimeString = candidateUser.getUserProperty(OpenmrsConstants.USER_PROPERTY_LOCKOUT_TIMESTAMP, null);
        Long lockoutTime = null;
        if (lockoutTimeString != null && !"0".equals(lockoutTimeString)) {
            try {
                // putting this in a try/catch in case the admin decided to put junk into the property
                lockoutTime = Long.valueOf(lockoutTimeString);
            } catch (NumberFormatException e) {
                log.debug("bad value stored in " + OpenmrsConstants.USER_PROPERTY_LOCKOUT_TIMESTAMP + " user property: " + lockoutTimeString);
            }
        }
        // if they've been locked out, don't continue with the authentication
        if (lockoutTime != null) {
            // to now and make them wait another 5 mins
            if (System.currentTimeMillis() - lockoutTime > 300000) {
                candidateUser.setUserProperty(OpenmrsConstants.USER_PROPERTY_LOGIN_ATTEMPTS, "0");
                candidateUser.removeUserProperty(OpenmrsConstants.USER_PROPERTY_LOCKOUT_TIMESTAMP);
                saveUserProperties(candidateUser);
            } else {
                candidateUser.setUserProperty(OpenmrsConstants.USER_PROPERTY_LOCKOUT_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
                throw new ContextAuthenticationException("Invalid number of connection attempts. Please try again later.");
            }
        }
        String passwordOnRecord = (String) session.createSQLQuery("select password from users where user_id = ?").addScalar("password", StandardBasicTypes.STRING).setInteger(0, candidateUser.getUserId()).uniqueResult();
        String saltOnRecord = (String) session.createSQLQuery("select salt from users where user_id = ?").addScalar("salt", StandardBasicTypes.STRING).setInteger(0, candidateUser.getUserId()).uniqueResult();
        // if the username and password match, hydrate the user and return it
        if (passwordOnRecord != null && Security.hashMatches(passwordOnRecord, password + saltOnRecord)) {
            // hydrate the user object
            candidateUser.getAllRoles().size();
            candidateUser.getUserProperties().size();
            candidateUser.getPrivileges().size();
            // only clean up if the were some login failures, otherwise all should be clean
            Integer attempts = getUsersLoginAttempts(candidateUser);
            if (attempts > 0) {
                candidateUser.setUserProperty(OpenmrsConstants.USER_PROPERTY_LOGIN_ATTEMPTS, "0");
                candidateUser.removeUserProperty(OpenmrsConstants.USER_PROPERTY_LOCKOUT_TIMESTAMP);
                saveUserProperties(candidateUser);
            }
            // to indicate that this is the valid user
            return candidateUser;
        } else {
            // the user failed the username/password, increment their
            // attempts here and set the "lockout" timestamp if necessary
            Integer attempts = getUsersLoginAttempts(candidateUser);
            attempts++;
            Integer allowedFailedLoginCount = 7;
            try {
                allowedFailedLoginCount = Integer.valueOf(Context.getAdministrationService().getGlobalProperty(OpenmrsConstants.GP_ALLOWED_FAILED_LOGINS_BEFORE_LOCKOUT).trim());
            } catch (Exception ex) {
                log.error("Unable to convert the global property " + OpenmrsConstants.GP_ALLOWED_FAILED_LOGINS_BEFORE_LOCKOUT + "to a valid integer. Using default value of 7");
            }
            if (attempts > allowedFailedLoginCount) {
                // set the user as locked out at this exact time
                candidateUser.setUserProperty(OpenmrsConstants.USER_PROPERTY_LOCKOUT_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
            } else {
                candidateUser.setUserProperty(OpenmrsConstants.USER_PROPERTY_LOGIN_ATTEMPTS, String.valueOf(attempts));
            }
            saveUserProperties(candidateUser);
        }
    }
    // throw this exception only once in the same place with the same
    // message regardless of username/pw combo entered
    log.info("Failed login attempt (login=" + login + ") - " + errorMsg);
    throw new ContextAuthenticationException(errorMsg);
}
Also used : ContextAuthenticationException(org.openmrs.api.context.ContextAuthenticationException) User(org.openmrs.User) HibernateException(org.hibernate.HibernateException) ContextAuthenticationException(org.openmrs.api.context.ContextAuthenticationException) HibernateException(org.hibernate.HibernateException) FullTextSession(org.hibernate.search.FullTextSession) Session(org.hibernate.Session) Transactional(org.springframework.transaction.annotation.Transactional)

Example 3 with ContextAuthenticationException

use of org.openmrs.api.context.ContextAuthenticationException in project openmrs-core by openmrs.

the class ContextDAOTest method authenticate_shouldGiveIdenticalErrorMessagesBetweenUsernameAndPasswordMismatch.

/**
 * @see ContextDAO#authenticate(String,String)
 */
@Test()
public void authenticate_shouldGiveIdenticalErrorMessagesBetweenUsernameAndPasswordMismatch() {
    User user = dao.authenticate("admin", "test");
    Assert.assertNotNull("This test depends on there being an admin:test user", user);
    String invalidUsernameErrorMessage = null;
    String invalidPasswordErrorMessage = null;
    try {
        dao.authenticate("some invalid username", "and an invalid password");
    } catch (ContextAuthenticationException authException) {
        invalidUsernameErrorMessage = authException.getMessage();
        invalidUsernameErrorMessage = invalidUsernameErrorMessage.replace("some invalid username", "");
    }
    try {
        // a valid username but an invalid password for that user
        dao.authenticate("admin", "and an invalid password");
    } catch (ContextAuthenticationException authException) {
        invalidPasswordErrorMessage = authException.getMessage();
        invalidPasswordErrorMessage = invalidPasswordErrorMessage.replace("admin", "");
    }
    Assert.assertEquals(invalidUsernameErrorMessage, invalidPasswordErrorMessage);
}
Also used : ContextAuthenticationException(org.openmrs.api.context.ContextAuthenticationException) User(org.openmrs.User) Test(org.junit.Test) BaseContextSensitiveTest(org.openmrs.test.BaseContextSensitiveTest)

Example 4 with ContextAuthenticationException

use of org.openmrs.api.context.ContextAuthenticationException in project openmrs-module-mirebalais by PIH.

the class LoginPageController method post.

public String post(@RequestParam(value = "username", required = false) String username, @RequestParam(value = "password", required = false) String password, @RequestParam(value = "sessionLocation", required = false) Integer sessionLocationId, @SpringBean ContextDAO contextDao, @SpringBean("locationService") LocationService locationService, UiUtils ui, EmrContext context, PageRequest request) {
    HttpSession httpSession = request.getRequest().getSession();
    Location sessionLocation = null;
    try {
        // TODO as above, grant this privilege to Anonymous instead of using a proxy privilege
        Context.addProxyPrivilege(PrivilegeConstants.GET_LOCATIONS);
        if (sessionLocationId != null) {
            sessionLocation = locationService.getLocation(sessionLocationId);
            if (!sessionLocation.hasTag(EmrApiConstants.LOCATION_TAG_SUPPORTS_LOGIN)) {
                // the UI shouldn't allow this, but protect against it just in case
                httpSession.setAttribute(EmrConstants.SESSION_ATTRIBUTE_ERROR_MESSAGE, ui.message("mirebalais.login.error.invalidLocation"));
                return "redirect:" + ui.pageLink("mirebalais", "login");
            }
        }
        if (sessionLocation == null) {
            httpSession.setAttribute(EmrConstants.SESSION_ATTRIBUTE_ERROR_MESSAGE, ui.message("mirebalais.login.error.locationRequired"));
            return "redirect:" + ui.pageLink("mirebalais", "login");
        }
        // Set a cookie, so next time someone logs in on this machine, we can default to that same location
        request.setCookieValue(EmrConstants.COOKIE_NAME_LAST_SESSION_LOCATION, sessionLocationId.toString());
    } finally {
        Context.removeProxyPrivilege(PrivilegeConstants.GET_LOCATIONS);
    }
    try {
        context.getUserContext().authenticate(username, password, contextDao);
        context.setSessionLocation(sessionLocation);
        // set the locale based on the user's default locale
        Locale userLocale = GeneralUtils.getDefaultLocale(context.getUserContext().getAuthenticatedUser());
        if (userLocale != null) {
            context.getUserContext().setLocale(userLocale);
            // these have been taken from the core login servlet, not sure if they are necessary
            request.getResponse().setLocale(userLocale);
            new CookieLocaleResolver().setDefaultLocale(userLocale);
        }
        return "redirect:" + ui.pageLink("mirebalais", "home");
    } catch (ContextAuthenticationException ex) {
        httpSession.setAttribute(EmrConstants.SESSION_ATTRIBUTE_ERROR_MESSAGE, ui.message("mirebalais.login.error.authentication"));
        return "redirect:" + ui.pageLink("mirebalais", "login");
    }
}
Also used : Locale(java.util.Locale) ContextAuthenticationException(org.openmrs.api.context.ContextAuthenticationException) CookieLocaleResolver(org.springframework.web.servlet.i18n.CookieLocaleResolver) HttpSession(javax.servlet.http.HttpSession) Location(org.openmrs.Location)

Aggregations

ContextAuthenticationException (org.openmrs.api.context.ContextAuthenticationException)4 User (org.openmrs.User)2 FileNotFoundException (java.io.FileNotFoundException)1 IOException (java.io.IOException)1 SQLException (java.sql.SQLException)1 Locale (java.util.Locale)1 Properties (java.util.Properties)1 HttpSession (javax.servlet.http.HttpSession)1 DatabaseUnitException (org.dbunit.DatabaseUnitException)1 DatabaseUnitRuntimeException (org.dbunit.DatabaseUnitRuntimeException)1 DataSetException (org.dbunit.dataset.DataSetException)1 HibernateException (org.hibernate.HibernateException)1 Session (org.hibernate.Session)1 FullTextSession (org.hibernate.search.FullTextSession)1 Test (org.junit.Test)1 Location (org.openmrs.Location)1 BaseContextSensitiveTest (org.openmrs.test.BaseContextSensitiveTest)1 Transactional (org.springframework.transaction.annotation.Transactional)1 CookieLocaleResolver (org.springframework.web.servlet.i18n.CookieLocaleResolver)1