Skip to content

Commit

Permalink
centralize canLogInAsBuiltinUser method #3338
Browse files Browse the repository at this point in the history
  • Loading branch information
pdurbin committed Nov 22, 2016
1 parent fb4f5e4 commit 30afb24
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 92 deletions.
2 changes: 1 addition & 1 deletion src/main/java/edu/harvard/iq/dataverse/Shib.java
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ public String confirmAndConvertAccount() {
String lookupStringPerAuthProvider = userPersistentId;
UserIdentifier userIdentifier = new UserIdentifier(lookupStringPerAuthProvider, internalUserIdentifer);
logger.fine("builtin username: " + builtinUsername);
AuthenticatedUser builtInUserToConvert = shibService.canLogInAsBuiltinUser(builtinUsername, builtinPassword);
AuthenticatedUser builtInUserToConvert = authSvc.canLogInAsBuiltinUser(builtinUsername, builtinPassword);
if (builtInUserToConvert != null) {
AuthenticatedUser au = authSvc.convertBuiltInToShib(builtInUserToConvert, shibAuthProvider.getId(), userIdentifier);
if (au != null) {
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/edu/harvard/iq/dataverse/api/Admin.java
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ public Response builtin2shib(String content) {
if (oldBuiltInUser != null) {
String usernameOfBuiltinAccountToConvert = oldBuiltInUser.getUserName();
response.add("old username", usernameOfBuiltinAccountToConvert);
AuthenticatedUser authenticatedUser = shibService.canLogInAsBuiltinUser(usernameOfBuiltinAccountToConvert, password);
AuthenticatedUser authenticatedUser = authSvc.canLogInAsBuiltinUser(usernameOfBuiltinAccountToConvert, password);
if (authenticatedUser != null) {
knowsExistingPassword = true;
AuthenticatedUser convertedUser = authSvc.convertBuiltInToShib(builtInUserToConvert, shibProviderId, newUserIdentifierInLookupTable);
Expand Down Expand Up @@ -597,7 +597,7 @@ public Response builtin2oauth(String content) {
if (oldBuiltInUser != null) {
String usernameOfBuiltinAccountToConvert = oldBuiltInUser.getUserName();
response.add("old username", usernameOfBuiltinAccountToConvert);
AuthenticatedUser authenticatedUser = shibService.canLogInAsBuiltinUser(usernameOfBuiltinAccountToConvert, password);
AuthenticatedUser authenticatedUser = authSvc.canLogInAsBuiltinUser(usernameOfBuiltinAccountToConvert, password);
if (authenticatedUser != null) {
knowsExistingPassword = true;
AuthenticatedUser convertedUser = authSvc.convertBuiltInUserToRemoteUser(builtInUserToConvert, newProviderId, newUserIdentifierInLookupTable);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import edu.harvard.iq.dataverse.authorization.providers.builtin.BuiltinAuthenticationProviderFactory;
import edu.harvard.iq.dataverse.authorization.providers.builtin.BuiltinUser;
import edu.harvard.iq.dataverse.authorization.providers.builtin.BuiltinUserServiceBean;
import edu.harvard.iq.dataverse.authorization.providers.builtin.PasswordEncryption;
import edu.harvard.iq.dataverse.authorization.providers.echo.EchoAuthenticationProviderFactory;
import edu.harvard.iq.dataverse.authorization.providers.oauth2.AbstractOAuth2AuthenticationProvider;
import edu.harvard.iq.dataverse.authorization.providers.oauth2.OAuth2AuthenticationProviderFactory;
Expand All @@ -23,6 +24,7 @@
import edu.harvard.iq.dataverse.confirmemail.ConfirmEmailServiceBean;
import edu.harvard.iq.dataverse.passwordreset.PasswordResetData;
import edu.harvard.iq.dataverse.passwordreset.PasswordResetServiceBean;
import edu.harvard.iq.dataverse.util.BundleUtil;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Collection;
Expand Down Expand Up @@ -624,7 +626,7 @@ public AuthenticatedUser convertBuiltInToShib(AuthenticatedUser builtInUserToCon
String builtinUsername = builtInUserIdentifier.replaceFirst(AuthenticatedUser.IDENTIFIER_PREFIX, "");
BuiltinUser builtin = builtinUserServiceBean.findByUserName(builtinUsername);
if (builtin != null) {
// These were created by AuthenticationResponse.Status.BREAKOUT in ShibServiceBean.canLogInAsBuiltinUser
// These were created by AuthenticationResponse.Status.BREAKOUT in canLogInAsBuiltinUser
List<PasswordResetData> oldTokens = passwordResetServiceBean.findPasswordResetDataByDataverseUser(builtin);
for (PasswordResetData oldToken : oldTokens) {
em.remove(oldToken);
Expand Down Expand Up @@ -662,8 +664,8 @@ public AuthenticatedUser convertBuiltInUserToRemoteUser(AuthenticatedUser builtI
authuserLookup.setAuthenticationProviderId(newProviderId);
String oldUserLookupIdentifier = authuserLookup.getPersistentUserId();
logger.info("this should be 'pete' or whatever the old builtin username was: " + oldUserLookupIdentifier);
String perUserShibIdentifier = newUserIdentifierInLookupTable.getLookupStringPerAuthProvider();
authuserLookup.setPersistentUserId(perUserShibIdentifier);
String perUserIdentifier = newUserIdentifierInLookupTable.getLookupStringPerAuthProvider();
authuserLookup.setPersistentUserId(perUserIdentifier);
/**
* @todo this should be a transaction of some kind. We want to update
* the authenticateduserlookup and also delete the row from the
Expand All @@ -673,7 +675,7 @@ public AuthenticatedUser convertBuiltInUserToRemoteUser(AuthenticatedUser builtI
String builtinUsername = builtInUserIdentifier.replaceFirst(AuthenticatedUser.IDENTIFIER_PREFIX, "");
BuiltinUser builtin = builtinUserServiceBean.findByUserName(builtinUsername);
if (builtin != null) {
// These were created by AuthenticationResponse.Status.BREAKOUT in ShibServiceBean.canLogInAsBuiltinUser
// These were created by AuthenticationResponse.Status.BREAKOUT in canLogInAsBuiltinUser
List<PasswordResetData> oldTokens = passwordResetServiceBean.findPasswordResetDataByDataverseUser(builtin);
for (PasswordResetData oldToken : oldTokens) {
em.remove(oldToken);
Expand All @@ -682,16 +684,16 @@ public AuthenticatedUser convertBuiltInUserToRemoteUser(AuthenticatedUser builtI
} else {
logger.info("Couldn't delete builtin user because could find it based on username " + builtinUsername);
}
AuthenticatedUser nonBuiltinUser = lookupUser(newProviderId, perUserShibIdentifier);
AuthenticatedUser nonBuiltinUser = lookupUser(newProviderId, perUserIdentifier);
if (nonBuiltinUser != null) {
return nonBuiltinUser;
}
return null;
}

/**
* @param idOfAuthUserToConvert The id of the AuthenticatedUser (Shibboleth
* user) to convert to a BuiltinUser.
* @param idOfAuthUserToConvert The id of the remote AuthenticatedUser
* (Shibboleth user or OAuth user) to convert to a BuiltinUser.
* @param newEmailAddress The new email address that will be used instead of
* the user's old email address from the institution that they have left.
* @return BuiltinUser
Expand Down Expand Up @@ -750,4 +752,86 @@ public BuiltinUser convertRemoteToBuiltIn(Long idOfAuthUserToConvert, String new
return builtinUser;
}

public AuthenticatedUser canLogInAsBuiltinUser(String username, String password) {
logger.fine("checking to see if " + username + " knows the password...");
if (password == null) {
logger.info("password was null");
return null;
}

AuthenticationRequest authReq = new AuthenticationRequest();
/**
* @todo Should this really be coming from a bundle like this? Added
* because that's what BuiltinAuthenticationProvider does.
*/
authReq.putCredential(BundleUtil.getStringFromBundle("login.builtin.credential.usernameOrEmail"), username);
authReq.putCredential(BundleUtil.getStringFromBundle("login.builtin.credential.password"), password);
/**
* @todo Should probably set IP address here.
*/
// authReq.setIpAddress(session.getUser().getRequestMetadata().getIpAddress());

String credentialsAuthProviderId = BuiltinAuthenticationProvider.PROVIDER_ID;
try {
AuthenticatedUser au = authenticate(credentialsAuthProviderId, authReq);
logger.fine("User authenticated:" + au.getEmail());
return au;
} catch (AuthenticationFailedException ex) {
logger.info("The username and/or password entered is invalid: " + ex.getResponse().getMessage());
if (AuthenticationResponse.Status.BREAKOUT.equals(ex.getResponse().getStatus())) {
/**
* Note that this "BREAKOUT" status creates PasswordResetData!
* We'll delete it just before blowing away the BuiltinUser in
* AuthenticationServiceBean.convertBuiltInToShib
*/
logger.info("AuthenticationFailedException caught in canLogInAsBuiltinUser: The username and/or password entered is invalid: " + ex.getResponse().getMessage() + " - Maybe the user (" + username + ") hasn't upgraded their password? Checking the old password...");
BuiltinUser builtinUser = builtinUserServiceBean.findByUsernameOrEmail(username);
if (builtinUser != null) {
boolean userAuthenticated = PasswordEncryption.getVersion(builtinUser.getPasswordEncryptionVersion()).check(password, builtinUser.getEncryptedPassword());
if (userAuthenticated == true) {
AuthenticatedUser authUser = lookupUser(BuiltinAuthenticationProvider.PROVIDER_ID, builtinUser.getUserName());
if (authUser != null) {
return authUser;
} else {
logger.info("canLogInAsBuiltinUser: Couldn't find AuthenticatedUser based on BuiltinUser username " + builtinUser.getUserName());
}
} else {
logger.info("canLogInAsBuiltinUser: User doesn't know old pre-bcrypt password either.");
}
} else {
logger.info("canLogInAsBuiltinUser: Couldn't run `check` because no BuiltinUser found with username " + username);
}
}
return null;
} catch (EJBException ex) {
Throwable cause = ex;
StringBuilder sb = new StringBuilder();
sb.append(ex + " ");
while (cause.getCause() != null) {
cause = cause.getCause();
sb.append(cause.getClass().getCanonicalName() + " ");
sb.append(cause.getMessage()).append(" ");
/**
* @todo Investigate why authSvc.authenticate is throwing
* NullPointerException. If you convert a Shib user or an OAuth
* user to a Builtin user, the password will be null.
*/
if (cause instanceof NullPointerException) {
for (int i = 0; i < 2; i++) {
StackTraceElement stacktrace = cause.getStackTrace()[i];
if (stacktrace != null) {
String classCanonicalName = stacktrace.getClass().getCanonicalName();
String methodName = stacktrace.getMethodName();
int lineNumber = stacktrace.getLineNumber();
String error = "at " + stacktrace.getClassName() + "." + stacktrace.getMethodName() + "(" + stacktrace.getFileName() + ":" + lineNumber + ") ";
sb.append(error);
}
}
}
}
logger.info("When trying to validate password, exception calling authSvc.authenticate: " + sb.toString());
return null;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -160,88 +160,6 @@ public BuiltinUser findBuiltInUserByAuthUserIdentifier(String authUserIdentifier
return builtinUserService.findByUserName(authUserIdentifier);
}

public AuthenticatedUser canLogInAsBuiltinUser(String username, String password) {
logger.fine("checking to see if " + username + " knows the password...");
if (password == null) {
logger.info("password was null");
return null;
}

AuthenticationRequest authReq = new AuthenticationRequest();
/**
* @todo Should this really be coming from a bundle like this? Added
* because that's what BuiltinAuthenticationProvider does.
*/
authReq.putCredential(BundleUtil.getStringFromBundle("login.builtin.credential.usernameOrEmail"), username);
authReq.putCredential(BundleUtil.getStringFromBundle("login.builtin.credential.password"), password);
/**
* @todo Should probably set IP address here.
*/
// authReq.setIpAddress(session.getUser().getRequestMetadata().getIpAddress());

String credentialsAuthProviderId = BuiltinAuthenticationProvider.PROVIDER_ID;
try {
AuthenticatedUser au = authSvc.authenticate(credentialsAuthProviderId, authReq);
logger.fine("User authenticated:" + au.getEmail());
return au;
} catch (AuthenticationFailedException ex) {
logger.info("The username and/or password entered is invalid: " + ex.getResponse().getMessage());
if (AuthenticationResponse.Status.BREAKOUT.equals(ex.getResponse().getStatus())) {
/**
* Note that this "BREAKOUT" status creates PasswordResetData!
* We'll delete it just before blowing away the BuiltinUser in
* AuthenticationServiceBean.convertBuiltInToShib
*/
logger.info("AuthenticationFailedException caught in canLogInAsBuiltinUser: The username and/or password entered is invalid: " + ex.getResponse().getMessage() + " - Maybe the user (" + username + ") hasn't upgraded their password? Checking the old password...");
BuiltinUser builtinUser = builtinUserService.findByUsernameOrEmail(username);
if (builtinUser != null) {
boolean userAuthenticated = PasswordEncryption.getVersion(builtinUser.getPasswordEncryptionVersion()).check(password, builtinUser.getEncryptedPassword());
if (userAuthenticated == true) {
AuthenticatedUser authUser = authSvc.lookupUser(BuiltinAuthenticationProvider.PROVIDER_ID, builtinUser.getUserName());
if (authUser != null) {
return authUser;
} else {
logger.info("canLogInAsBuiltinUser: Couldn't find AuthenticatedUser based on BuiltinUser username " + builtinUser.getUserName());
}
} else {
logger.info("canLogInAsBuiltinUser: User doesn't know old pre-bcrypt password either.");
}
} else {
logger.info("canLogInAsBuiltinUser: Couldn't run `check` because no BuiltinUser found with username " + username);
}
}
return null;
} catch (EJBException ex) {
Throwable cause = ex;
StringBuilder sb = new StringBuilder();
sb.append(ex + " ");
while (cause.getCause() != null) {
cause = cause.getCause();
sb.append(cause.getClass().getCanonicalName() + " ");
sb.append(cause.getMessage()).append(" ");
/**
* @todo Investigate why authSvc.authenticate is throwing
* NullPointerException. If you convert a Shib user to a Builtin
* user, the password may be null.
*/
if (cause instanceof NullPointerException) {
for (int i = 0; i < 2; i++) {
StackTraceElement stacktrace = cause.getStackTrace()[i];
if (stacktrace != null) {
String classCanonicalName = stacktrace.getClass().getCanonicalName();
String methodName = stacktrace.getMethodName();
int lineNumber = stacktrace.getLineNumber();
String error = "at " + stacktrace.getClassName() + "." + stacktrace.getMethodName() + "(" + stacktrace.getFileName() + ":" + lineNumber + ") ";
sb.append(error);
}
}
}
}
logger.info("When trying to validate password, exception calling authSvc.authenticate: " + sb.toString());
return null;
}
}

public String getAffiliation(String shibIdp, DevShibAccountType devShibAccountType) {
JsonArray emptyJsonArray = new JsonArray();
String discoFeedJson = emptyJsonArray.toString();
Expand Down

0 comments on commit 30afb24

Please sign in to comment.