[FEATURE] New Core Auth System

This commit is contained in:
Gravita 2021-05-16 20:07:44 +07:00
parent 97faf5ef79
commit b647f49390
19 changed files with 429 additions and 109 deletions

View file

@ -108,6 +108,7 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab
public final LaunchServerModulesManager modulesManager;
// Launcher binary
public final MirrorManager mirrorManager;
public final AuthManager authManager;
public final ReconfigurableManager reconfigurableManager;
public final ConfigManager configManager;
public final PingServerManager pingServerManager;
@ -169,6 +170,7 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La
configManager = new ConfigManager();
pingServerManager = new PingServerManager(this);
featuresManager = new FeaturesManager(this);
authManager = new AuthManager(this);
//Generate or set new Certificate API
certificateManager.orgName = config.projectName;
config.init(ReloadType.FULL);

View file

@ -9,6 +9,7 @@
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
import pro.gravit.launcher.request.auth.AuthRequest;
import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest;
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
import pro.gravit.launchserver.auth.handler.AuthHandler;
import pro.gravit.launchserver.auth.protect.ProtectHandler;
import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider;
@ -199,8 +200,9 @@ public static void initGson(LaunchServerModulesManager modulesManager) {
Launcher.gsonManager.initGson();
}
@SuppressWarnings("deprecation")
public static void registerAll() {
AuthCoreProvider.registerProviders();
AuthHandler.registerHandlers();
AuthProvider.registerProviders();
TextureProvider.registerProviders();

View file

@ -1,6 +1,7 @@
package pro.gravit.launchserver.auth;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
import pro.gravit.launchserver.auth.handler.AuthHandler;
import pro.gravit.launchserver.auth.provider.AuthProvider;
import pro.gravit.launchserver.auth.texture.TextureProvider;
@ -13,6 +14,7 @@ public class AuthProviderPair {
public AuthProvider provider;
public AuthHandler handler;
public TextureProvider textureProvider;
public AuthCoreProvider core;
public Map<String, String> links;
public transient String name;
public String displayName;
@ -26,12 +28,18 @@ public AuthProviderPair(AuthProvider provider, AuthHandler handler, TextureProvi
public void init(LaunchServer srv, String name) {
this.name = name;
if (links != null) link(srv);
if (provider == null) throw new NullPointerException(String.format("Auth %s provider null", name));
if (handler == null) throw new NullPointerException(String.format("Auth %s handler null", name));
if(core == null) {
if (provider == null) throw new NullPointerException(String.format("Auth %s provider null", name));
if (handler == null) throw new NullPointerException(String.format("Auth %s handler null", name));
provider.init(srv);
handler.init(srv);
} else {
if (provider != null) throw new IllegalArgumentException(String.format("Auth %s provider not null", name));
if (handler != null) throw new IllegalArgumentException(String.format("Auth %s handler not null", name));
core.init(srv);
}
if (textureProvider == null)
throw new NullPointerException(String.format("Auth %s textureProvider null", name));
provider.init(srv);
handler.init(srv);
}
public void link(LaunchServer srv) {
@ -57,8 +65,20 @@ public void link(LaunchServer srv) {
}
public void close() throws IOException {
provider.close();
handler.close();
if(core == null) {
provider.close();
handler.close();
} else {
core.close();
}
textureProvider.close();
}
public boolean isUseCore() {
return core != null;
}
public boolean isUseProviderAndHandler() {
return !isUseCore();
}
}

View file

@ -0,0 +1,95 @@
package pro.gravit.launchserver.auth.core;
import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent;
import pro.gravit.launcher.request.auth.AuthRequest;
import pro.gravit.launcher.request.auth.details.AuthPasswordDetails;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.AuthException;
import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
import pro.gravit.utils.ProviderMap;
import pro.gravit.utils.helper.SecurityHelper;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
/*
All-In-One provider
*/
public abstract class AuthCoreProvider implements AutoCloseable {
public static final ProviderMap<AuthCoreProvider> providers = new ProviderMap<>("AuthCoreProvider");
private static boolean registredProviders = false;
public static void registerProviders() {
if (!registredProviders) {
registredProviders = true;
}
}
public abstract User getUserByUsername(String username);
public abstract User getUserByUUID(UUID uuid);
public abstract void verifyAuth(AuthResponse.AuthContext context) throws AuthException;
public abstract PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordInterface password);
public abstract void init(LaunchServer server);
// Auth Handler methods
protected abstract boolean updateAuth(User user) throws IOException;
protected abstract boolean updateServerID(User user, String serverID) throws IOException;
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
return List.of(new AuthPasswordDetails());
}
public UUID checkServer(Client client, String username, String serverID) throws IOException {
User user = getUserByUsername(username);
if(user.getUsername().equals(username) && user.getServerId().equals(serverID)) {
return user.getUUID();
}
return null;
}
public boolean joinServer(Client client, String username, String accessToken, String serverID) throws IOException {
User user = client.getUser();
if(user == null) return false;
return user.getUsername().equals(username) && user.getAccessToken().equals(accessToken) && updateServerID(user, serverID);
}
@Override
public abstract void close() throws IOException;
public static class PasswordVerifyReport {
public final boolean success;
public final boolean needMoreFactor;
public final List<Integer> factors;
public final String accessToken;
public static final PasswordVerifyReport REQUIRED_2FA = new PasswordVerifyReport(-1);
public static final PasswordVerifyReport FAILED = new PasswordVerifyReport(false);
public PasswordVerifyReport(boolean success) {
this.success = success;
this.needMoreFactor = false;
this.factors = List.of();
this.accessToken = SecurityHelper.randomStringToken();
}
public PasswordVerifyReport(String accessToken) {
this.success = true;
this.needMoreFactor = false;
this.factors = List.of();
this.accessToken = accessToken;
}
public PasswordVerifyReport(int nextFactor) {
this.success = false;
this.needMoreFactor = true;
this.factors = List.of(nextFactor);
this.accessToken = null;
}
public PasswordVerifyReport(List<Integer> factors) {
this.success = false;
this.needMoreFactor = false;
this.factors = Collections.unmodifiableList(factors);
this.accessToken = null;
}
}
}

View file

@ -0,0 +1,13 @@
package pro.gravit.launchserver.auth.core;
import pro.gravit.launcher.ClientPermissions;
import java.util.UUID;
public interface User {
String getUsername();
UUID getUUID();
String getServerId();
String getAccessToken();
ClientPermissions getPermissions();
}

View file

@ -0,0 +1,10 @@
package pro.gravit.launchserver.auth.core.interfaces.provider;
import pro.gravit.launcher.request.auth.AuthRequest;
import pro.gravit.launchserver.auth.core.User;
import java.util.Map;
public interface AuthSupportRegistration {
User registration(String login, AuthRequest.AuthPasswordInterface password, Map<String, String> properties);
}

View file

@ -0,0 +1,6 @@
package pro.gravit.launchserver.auth.core.interfaces.user;
public interface UserSupportMoney {
long getMoney();
long getDonateMoney();
}

View file

@ -4,6 +4,7 @@
import java.util.UUID;
@Deprecated
public interface User {
String getUsername();

View file

@ -3,6 +3,7 @@
import java.util.List;
import java.util.UUID;
@Deprecated
public interface UserDAO {
User findById(int id);

View file

@ -4,6 +4,7 @@
import pro.gravit.launchserver.dao.UserDAO;
import pro.gravit.utils.ProviderMap;
@Deprecated
public abstract class DaoProvider {
public static final ProviderMap<DaoProvider> providers = new ProviderMap<>("DaoProvider");
public transient UserDAO userDAO;

View file

@ -0,0 +1,228 @@
package pro.gravit.launchserver.manangers;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import pro.gravit.launcher.ClientPermissions;
import pro.gravit.launcher.events.request.AuthRequestEvent;
import pro.gravit.launcher.request.auth.AuthRequest;
import pro.gravit.launcher.request.auth.password.*;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.AuthException;
import pro.gravit.launchserver.auth.AuthProviderPair;
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
import pro.gravit.launchserver.auth.core.User;
import pro.gravit.launchserver.auth.provider.AuthProvider;
import pro.gravit.launchserver.auth.provider.AuthProviderDAOResult;
import pro.gravit.launchserver.auth.provider.AuthProviderResult;
import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
import pro.gravit.launchserver.socket.response.profile.ProfileByUUIDResponse;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.SecurityHelper;
import javax.crypto.Cipher;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.stream.Collectors;
public class AuthManager {
private transient final LaunchServer server;
private transient final Logger logger = LogManager.getLogger();
public AuthManager(LaunchServer server) {
this.server = server;
}
/**
* Create AuthContext
* @return AuthContext instance
*/
public AuthResponse.AuthContext makeAuthContext(Client client, AuthResponse.ConnectTypes authType, AuthProviderPair pair, String login, String profileName, String ip) {
Objects.requireNonNull(client, "Client must be not null");
Objects.requireNonNull(authType, "authType must be not null");
Objects.requireNonNull(pair, "AuthProviderPair must be not null");
return new AuthResponse.AuthContext(client, login, profileName, ip, authType, pair);
}
/**
* Validate auth params ans state
* @param context Auth context
* @throws AuthException auth not possible
*/
public void check(AuthResponse.AuthContext context) throws AuthException {
if (context.authType == AuthResponse.ConnectTypes.CLIENT && !context.client.checkSign) {
AuthProvider.authError("Don't skip Launcher Update");
return;
}
if (context.client.isAuth) {
AuthProvider.authError("You are already logged in");
return;
}
}
/**
* Full client authorization with password verification
* @param context AuthContext
* @param password User password
* @return Access token
*/
public String auth(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException {
AuthProviderPair pair = context.pair;
String accessToken;
if(pair.core == null) {
try {
accessToken = authWithProviderAndHandler(context, password);
} catch (Exception e) {
if(e instanceof AuthException) throw (AuthException) e;
throw new AuthException("Internal Auth Error. Please contact administrator");
}
} else {
accessToken = authWithCore(context, password);
}
return accessToken;
}
@SuppressWarnings("deprecation")
private String authWithProviderAndHandler(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws Exception {
String accessToken;
context.pair.provider.preAuth(context.login, password, context.ip);
AuthProviderResult aresult = context.pair.provider.auth(context.login, password, context.ip);
UUID uuid;
String username = aresult.username != null ? aresult.username : context.login;
if (aresult instanceof AuthProviderDAOResult) {
context.client.daoObject = ((AuthProviderDAOResult) aresult).daoObject;
}
if(context.authType == AuthResponse.ConnectTypes.CLIENT && server.config.protectHandler.allowGetAccessToken(context)) {
uuid = context.pair.handler.auth(aresult);
accessToken = aresult.accessToken;
} else {
uuid = context.pair.handler.usernameToUUID(aresult.username);
accessToken = null;
}
internalAuth(context.client, context.authType, context.pair, username, uuid, aresult.permissions);
return accessToken;
}
private String authWithCore(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException {
AuthCoreProvider provider = context.pair.core;
provider.verifyAuth(context);
User user = provider.getUserByUsername(context.login);
if(user == null) {
throw new AuthException(AuthRequestEvent.USER_NOT_FOUND_ERROR_MESSAGE);
}
AuthCoreProvider.PasswordVerifyReport report = provider.verifyPassword(user, password);
if(report.success) {
String accessToken;
UUID uuid = user.getUUID();
if(context.authType == AuthResponse.ConnectTypes.CLIENT && server.config.protectHandler.allowGetAccessToken(context)) {
provider.verifyAuth(context);
accessToken = report.accessToken;
} else {
accessToken = null;
}
context.client.coreObject = user;
internalAuth(context.client, context.authType, context.pair, user.getUsername(), uuid, user.getPermissions());
return accessToken;
}
else {
if(report.needMoreFactor) {
if(report.factors.size() == 1 && report.factors.get(0) == -1) {
throw new AuthException(AuthRequestEvent.TWO_FACTOR_NEED_ERROR_MESSAGE);
}
String message = AuthRequestEvent.ONE_FACTOR_NEED_ERROR_MESSAGE_PREFIX
.concat(report.factors.stream().map(String::valueOf).collect(Collectors.joining(".")));
throw new AuthException(message);
}
throw new AuthException(AuthRequestEvent.WRONG_PASSWORD_ERROR_MESSAGE);
}
}
/**
* Writing authorization information to the Client object
*/
public void internalAuth(Client client, AuthResponse.ConnectTypes authType, AuthProviderPair pair, String username, UUID uuid, ClientPermissions permissions) {
client.isAuth = true;
client.permissions = permissions;
client.auth_id = pair.name;
client.auth = pair;
client.username = username;
client.type = authType;
client.uuid = uuid;
if(pair.isUseCore() && client.coreObject == null) {
client.coreObject = pair.core.getUserByUUID(uuid);
}
}
public UUID checkServer(Client client, String username, String serverID) throws IOException {
if(client.auth == null) return null;
if(client.auth.isUseCore()) {
return client.auth.core.checkServer(client, username, serverID);
}
else {
return client.auth.handler.checkServer(username, serverID);
}
}
public boolean joinServer(Client client, String username, String accessToken, String serverID) throws IOException {
if(client.auth == null) return false;
if(client.auth.isUseCore()) {
return client.auth.core.joinServer(client, username, accessToken, serverID);
} else {
return client.auth.handler.joinServer(username, accessToken, serverID);
}
}
public AuthRequest.AuthPasswordInterface decryptPassword(AuthRequest.AuthPasswordInterface password) throws AuthException {
if(password instanceof Auth2FAPassword) {
Auth2FAPassword auth2FAPassword = (Auth2FAPassword) password;
auth2FAPassword.firstPassword = tryDecryptPasswordPlain(auth2FAPassword.firstPassword);
auth2FAPassword.secondPassword = tryDecryptPasswordPlain(auth2FAPassword.secondPassword);
}
else if(password instanceof AuthMultiPassword) {
AuthMultiPassword multiPassword = (AuthMultiPassword) password;
List<AuthRequest.AuthPasswordInterface> list = new ArrayList<>(multiPassword.list.size());
for(AuthRequest.AuthPasswordInterface p : multiPassword.list) {
list.add(tryDecryptPasswordPlain(p));
}
multiPassword.list = list;
}
else {
password = tryDecryptPasswordPlain(password);
}
return password;
}
@SuppressWarnings("deprecation")
private AuthRequest.AuthPasswordInterface tryDecryptPasswordPlain(AuthRequest.AuthPasswordInterface password) throws AuthException {
if (password instanceof AuthECPassword) {
try {
return new AuthPlainPassword(IOHelper.decode(SecurityHelper.decrypt(server.runtime.passwordEncryptKey
, ((AuthECPassword) password).password)));
} catch (Exception ignored) {
throw new AuthException("Password decryption error");
}
}
if (password instanceof AuthAESPassword) {
try {
return new AuthPlainPassword(IOHelper.decode(SecurityHelper.decrypt(server.runtime.passwordEncryptKey
, ((AuthAESPassword) password).password)));
} catch (Exception ignored) {
throw new AuthException("Password decryption error");
}
}
if(password instanceof AuthRSAPassword) {
try {
Cipher cipher = SecurityHelper.newRSADecryptCipher(server.keyAgreementManager.rsaPrivateKey);
return new AuthPlainPassword(
IOHelper.decode(cipher.doFinal(((AuthRSAPassword) password).password))
);
} catch (Exception ignored) {
throw new AuthException("Password decryption error");
}
}
return password;
}
}

View file

@ -9,6 +9,7 @@
import pro.gravit.launcher.request.WebSocketEvent;
import pro.gravit.launcher.request.auth.AuthRequest;
import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest;
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
import pro.gravit.launchserver.auth.handler.AuthHandler;
import pro.gravit.launchserver.auth.protect.ProtectHandler;
import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider;
@ -31,11 +32,13 @@ public LaunchServerGsonManager(LaunchServerModulesManager modulesManager) {
}
@Override
@SuppressWarnings("deprecation")
public void registerAdapters(GsonBuilder builder) {
super.registerAdapters(builder);
builder.registerTypeAdapter(AuthProvider.class, new UniversalJsonAdapter<>(AuthProvider.providers));
builder.registerTypeAdapter(TextureProvider.class, new UniversalJsonAdapter<>(TextureProvider.providers));
builder.registerTypeAdapter(AuthHandler.class, new UniversalJsonAdapter<>(AuthHandler.providers));
builder.registerTypeAdapter(AuthCoreProvider.class, new UniversalJsonAdapter<>(AuthCoreProvider.providers));
builder.registerTypeAdapter(Component.class, new UniversalJsonAdapter<>(Component.providers));
builder.registerTypeAdapter(ProtectHandler.class, new UniversalJsonAdapter<>(ProtectHandler.providers));
builder.registerTypeAdapter(DaoProvider.class, new UniversalJsonAdapter<>(DaoProvider.providers));

View file

@ -53,12 +53,17 @@ private Client decompressClient(byte[] client) {
return Launcher.gsonManager.gson.fromJson(new String(client, StandardCharsets.UTF_8), Client.class); //Compress using later
}
@SuppressWarnings("deprecation")
private Client restoreFromString(byte[] data) {
Client result = decompressClient(data);
result.updateAuth(server);
if (result.auth != null && (result.username != null)) {
if (result.auth.handler instanceof RequiredDAO || result.auth.provider instanceof RequiredDAO || result.auth.textureProvider instanceof RequiredDAO) {
result.daoObject = server.config.dao.userDAO.findByUsername(result.username);
if(result.auth.isUseCore()) {
result.coreObject = result.auth.core.getUserByUUID(result.uuid);
} else {
if (result.auth.handler instanceof RequiredDAO || result.auth.provider instanceof RequiredDAO || result.auth.textureProvider instanceof RequiredDAO) {
result.daoObject = server.config.dao.userDAO.findByUsername(result.username);
}
}
}
if (result.refCount == null) result.refCount = new AtomicInteger(1);

View file

@ -28,8 +28,11 @@ public class Client {
public transient AuthProviderPair auth;
@Deprecated
public transient User daoObject;
public transient pro.gravit.launchserver.auth.core.User coreObject;
public transient Map<String, Object> properties;
public Map<String, String> serializableProperties;
@ -78,6 +81,14 @@ public void setSerializableProperty(String name, String value) {
properties.put(name, value);
}
public pro.gravit.launchserver.auth.core.User getUser() {
if(coreObject != null) return coreObject;
if(auth != null && uuid != null && auth.isUseCore()) {
coreObject = auth.core.getUserByUUID(uuid);
}
return coreObject;
}
@Deprecated
public enum Type {
SERVER,

View file

@ -221,6 +221,7 @@ public void sendObjectToUUID(UUID userUuid, Object obj, Type type) {
}
}
@Deprecated
public void updateDaoObject(UUID userUuid, User daoObject, Consumer<Channel> callback) {
for (Channel ch : channels) {
if (ch == null || ch.pipeline() == null) continue;
@ -252,7 +253,7 @@ public boolean kickByUserUUID(UUID userUuid, boolean isClose) {
WebSocketFrameHandler wsHandler = ch.pipeline().get(WebSocketFrameHandler.class);
if (wsHandler == null) continue;
Client client = wsHandler.getClient();
if (client == null || client.daoObject == null || !userUuid.equals(client.uuid)) continue;
if (client == null || !userUuid.equals(client.uuid)) continue;
ExitResponse.exit(server, wsHandler, ch, ExitRequestEvent.ExitReason.SERVER);
if (isClose) ch.close();
result = true;

View file

@ -48,15 +48,6 @@ public String getType() {
public void execute(ChannelHandlerContext ctx, Client clientData) throws Exception {
try {
AuthRequestEvent result = new AuthRequestEvent();
if ((authType == null || authType == ConnectTypes.CLIENT) && (clientData == null || !clientData.checkSign)) {
AuthProvider.authError("Don't skip Launcher Update");
return;
}
if (clientData.isAuth) {
sendError("You are already logged in");
return;
}
AuthProviderPair pair;
if (auth_id == null || auth_id.isEmpty()) pair = server.config.getAuthProviderPair();
else pair = server.config.getAuthProviderPair(auth_id);
@ -64,45 +55,12 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
sendError("auth_id incorrect");
return;
}
AuthContext context = new AuthContext(clientData, login, client, ip, authType);
AuthProvider provider = pair.provider;
AuthContext context = server.authManager.makeAuthContext(clientData, authType, pair, login, client, ip);
server.authManager.check(context);
password = server.authManager.decryptPassword(password);
server.authHookManager.preHook.hook(context, clientData);
provider.preAuth(login, password, ip);
if(password instanceof Auth2FAPassword) {
AuthPlainPassword first = decryptPassword(server, ((Auth2FAPassword) password).firstPassword);
AuthPlainPassword second = decryptPassword(server, ((Auth2FAPassword) password).secondPassword);
if(first != null) {
((Auth2FAPassword) password).firstPassword = first;
}
if(second != null) {
((Auth2FAPassword) password).secondPassword = second;
}
}
else {
AuthPlainPassword passwd = decryptPassword(server, password);
if(passwd != null) {
password = passwd;
}
}
AuthProviderResult aresult = provider.auth(login, password, ip);
if (!VerifyHelper.isValidUsername(aresult.username)) {
AuthProvider.authError(String.format("Illegal result: '%s'", aresult.username));
return;
}
server.authManager.auth(context, password);
server.authHookManager.postHook.hook(context, clientData);
clientData.isAuth = true;
clientData.permissions = aresult.permissions;
clientData.auth_id = auth_id;
clientData.updateAuth(server);
if (aresult.username != null)
clientData.username = aresult.username;
else
clientData.username = login;
if (aresult instanceof AuthProviderDAOResult) {
clientData.daoObject = ((AuthProviderDAOResult) aresult).daoObject;
}
result.accessToken = aresult.accessToken;
result.permissions = clientData.permissions;
if (getSession) {
if (clientData.session == null) {
clientData.session = UUID.randomUUID();
@ -110,56 +68,13 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
}
result.session = clientData.session;
}
if (authType == ConnectTypes.CLIENT && server.config.protectHandler.allowGetAccessToken(context)) {
clientData.uuid = pair.handler.auth(aresult);
if (logger.isDebugEnabled()) {
logger.debug("Auth: {} accessToken {} uuid: {}", login, result.accessToken, clientData.uuid.toString());
}
} else {
clientData.uuid = pair.handler.usernameToUUID(aresult.username);
result.accessToken = null;
}
result.playerProfile = ProfileByUUIDResponse.getProfile(clientData.uuid, aresult.username, client, clientData.auth.textureProvider);
clientData.type = authType;
result.playerProfile = ProfileByUUIDResponse.getProfile(clientData.uuid, clientData.username, client, clientData.auth.textureProvider);
sendResult(result);
} catch (AuthException | HookException e) {
sendError(e.getMessage());
}
}
@SuppressWarnings("deprecation")
public static AuthPlainPassword decryptPassword(LaunchServer server, AuthRequest.AuthPasswordInterface password) throws Exception {
if (password instanceof AuthECPassword) {
try {
return new AuthPlainPassword(IOHelper.decode(SecurityHelper.decrypt(server.runtime.passwordEncryptKey
, ((AuthECPassword) password).password)));
} catch (IllegalBlockSizeException | BadPaddingException ignored) {
throw new AuthException("Password decryption error");
}
}
if (password instanceof AuthAESPassword) {
try {
return new AuthPlainPassword(IOHelper.decode(SecurityHelper.decrypt(server.runtime.passwordEncryptKey
, ((AuthAESPassword) password).password)));
} catch (IllegalBlockSizeException | BadPaddingException ignored) {
throw new AuthException("Password decryption error");
}
}
if(password instanceof AuthRSAPassword) {
try {
Cipher cipher = SecurityHelper.newRSADecryptCipher(server.keyAgreementManager.rsaPrivateKey);
return new AuthPlainPassword(
IOHelper.decode(cipher.doFinal(((AuthRSAPassword) password).password))
);
} catch (IllegalBlockSizeException | BadPaddingException ignored) {
throw new AuthException("Password decryption error");
}
}
return null;
}
public enum ConnectTypes {
@Deprecated
SERVER,
@ -173,15 +88,17 @@ public static class AuthContext {
public final String ip;
public final ConnectTypes authType;
public final Client client;
public final AuthProviderPair pair;
@Deprecated
public int password_length; //Use AuthProvider for get password
public AuthContext(Client client, String login, String profileName, String ip, ConnectTypes authType) {
public AuthContext(Client client, String login, String profileName, String ip, ConnectTypes authType, AuthProviderPair pair) {
this.client = client;
this.login = login;
this.profileName = profileName;
this.ip = ip;
this.authType = authType;
this.pair = pair;
}
}
}

View file

@ -31,10 +31,11 @@ public void execute(ChannelHandlerContext ctx, Client pClient) {
CheckServerRequestEvent result = new CheckServerRequestEvent();
try {
server.authHookManager.checkServerHook.hook(this, pClient);
result.uuid = pClient.auth.handler.checkServer(username, serverID);
if (result.uuid != null)
result.uuid = server.authManager.checkServer(pClient, username, serverID);
if (result.uuid != null) {
result.playerProfile = ProfileByUUIDResponse.getProfile(result.uuid, username, client, pClient.auth.textureProvider);
logger.debug("checkServer: {} uuid: {} serverID: {}", result.playerProfile.username, result.uuid, serverID);
logger.debug("checkServer: {} uuid: {} serverID: {}", result.playerProfile.username, result.uuid, serverID);
}
} catch (AuthException | HookException e) {
sendError(e.getMessage());
return;

View file

@ -42,11 +42,10 @@ public void execute(ChannelHandlerContext ctx, Client client) {
return;
}
}
if (client.auth == null) {
logger.warn("Client auth is null. Using default.");
success = server.config.getAuthProviderPair().handler.joinServer(username, accessToken, serverID);
} else success = client.auth.handler.joinServer(username, accessToken, serverID);
logger.debug("joinServer: {} accessToken: {} serverID: {}", username, accessToken, serverID);
success = server.authManager.joinServer(client, username, accessToken, serverID);
if(success) {
logger.debug("joinServer: {} accessToken: {} serverID: {}", username, accessToken, serverID);
}
} catch (AuthException | HookException | SecurityException e) {
sendError(e.getMessage());
return;

View file

@ -9,6 +9,10 @@
public class AuthRequestEvent extends RequestEvent {
public static final String TWO_FACTOR_NEED_ERROR_MESSAGE = "auth.require2fa";
public static final String ONE_FACTOR_NEED_ERROR_MESSAGE_PREFIX = "auth.require.factor.";
public static final String USER_NOT_FOUND_ERROR_MESSAGE = "auth.message.usernotfound";
public static final String WRONG_PASSWORD_ERROR_MESSAGE = "auth.message.wrongpassword";
public static final String ACCOUNT_BLOCKED_ERROR_MESSAGE = "auth.message.blocked";
@LauncherNetworkAPI
public ClientPermissions permissions;
@LauncherNetworkAPI