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++;
}
}
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);
}
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);
}
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");
}
}
Aggregations