Add token-based authentication (without rejection handling)

This commit is contained in:
2020-09-19 11:37:42 +02:00
parent 31cb22035b
commit f21d077522
10 changed files with 178 additions and 35 deletions

View File

@ -5,26 +5,18 @@ import static envoy.data.User.UserStatus.ONLINE;
import static envoy.event.HandshakeRejection.*;
import java.time.Instant;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.logging.Logger;
import javax.persistence.NoResultException;
import envoy.data.LoginCredentials;
import envoy.event.GroupMessageStatusChange;
import envoy.event.HandshakeRejection;
import envoy.event.MessageStatusChange;
import envoy.server.data.GroupMessage;
import envoy.server.data.PersistenceManager;
import envoy.server.data.User;
import envoy.server.net.ConnectionManager;
import envoy.server.net.ObjectWriteProxy;
import envoy.server.util.PasswordUtil;
import envoy.server.util.VersionUtil;
import envoy.util.Bounds;
import envoy.util.EnvoyLog;
import envoy.event.*;
import envoy.server.data.*;
import envoy.server.net.*;
import envoy.server.util.*;
import envoy.util.*;
/**
* This {@link ObjectProcessor} handles {@link LoginCredentials}.<br>
@ -62,17 +54,31 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
try {
user = persistenceManager.getUserByName(credentials.getIdentifier());
// Checking if user is already online
// Check if the user is already online
if (connectionManager.isOnline(user.getID())) {
logger.warning(user + " is already online!");
writeProxy.write(socketID, new HandshakeRejection(INTERNAL_ERROR));
return;
}
// Evaluating the correctness of the password hash
if (!PasswordUtil.validate(credentials.getPassword(), user.getPasswordHash())) {
logger.info(user + " has entered the wrong password.");
writeProxy.write(socketID, new HandshakeRejection(WRONG_PASSWORD_OR_USER));
return;
// Authenticate with password or token
if (credentials.usesToken()) {
// Check the token
if (user.getAuthToken() == null || user.getAuthTokenExpiration().isBefore(Instant.now())
|| !user.getAuthToken().equals(credentials.getPassword())) {
logger.info(user + " tried to use an invalid token.");
writeProxy.write(socketID, new HandshakeRejection(INVALID_TOKEN));
return;
}
} else {
// Check the password hash
if (!PasswordUtil.validate(credentials.getPassword(), user.getPasswordHash())) {
logger.info(user + " has entered the wrong password.");
writeProxy.write(socketID, new HandshakeRejection(WRONG_PASSWORD_OR_USER));
return;
}
}
} catch (NoResultException e) {
logger.info("The requested user does not exist.");
@ -80,6 +86,7 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
return;
}
} else {
// Validate user name
if (!Bounds.isValidContactName(credentials.getIdentifier())) {
logger.info("The requested user name is not valid.");
@ -87,7 +94,8 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
return;
}
try {
// Checking that no user already has this identifier
// Check if the name is taken
PersistenceManager.getInstance().getUserByName(credentials.getIdentifier());
// This code only gets executed if this user already exists
@ -114,6 +122,15 @@ public final class LoginCredentialProcessor implements ObjectProcessor<LoginCred
user.setStatus(ONLINE);
UserStatusChangeProcessor.updateUserStatus(user);
// Generate a new token if requested
if (credentials.requestToken()) {
String token = AuthTokenGenerator.nextToken();
user.setAuthToken(token);
user.setAuthTokenExpiration(Instant.now().plus(ServerConfig.getInstance().getAuthTokenExpiration().longValue(), ChronoUnit.DAYS));
persistenceManager.updateContact(user);
writeProxy.write(socketID, new NewAuthToken(token));
}
final var pendingMessages = PersistenceManager.getInstance().getPendingMessages(user, credentials.getLastSync());
pendingMessages.removeIf(GroupMessage.class::isInstance);
logger.fine("Sending " + pendingMessages.size() + " pending messages to " + user + "...");