diff --git a/src/main/java/net/elytrium/limboauth/LimboAuth.java b/src/main/java/net/elytrium/limboauth/LimboAuth.java index a0d66330..2151d01b 100644 --- a/src/main/java/net/elytrium/limboauth/LimboAuth.java +++ b/src/main/java/net/elytrium/limboauth/LimboAuth.java @@ -773,6 +773,27 @@ public PremiumResponse isPremiumInternal(String nickname) { } if (this.playerDao.countOf(premiumCountQuery.prepare()) != 0) { + if (Settings.IMP.MAIN.ALWAYS_CHECK_PREMIUM_PLAYERS) { + RegisteredPlayer player = AuthSessionHandler.fetchInfo(this.playerDao, nickname); + if (player == null) { + // Database got broken? + return new PremiumResponse(PremiumState.ERROR); + } + + if (!player.getPremiumUuid().isEmpty()) { + PremiumResponse response = this.isPremiumExternal(nickname); + if (response.uuid == null) { + // Got rate-limited or something failed. + return new PremiumResponse(PremiumState.ERROR); + } + + if (!response.uuid.toString().equals(player.getPremiumUuid())) { + // Something got broken or account is being hijacked. + return new PremiumResponse(PremiumState.ERROR); + } + } + } + return new PremiumResponse(PremiumState.PREMIUM); } diff --git a/src/main/java/net/elytrium/limboauth/Settings.java b/src/main/java/net/elytrium/limboauth/Settings.java index e19fff0b..baf3b519 100644 --- a/src/main/java/net/elytrium/limboauth/Settings.java +++ b/src/main/java/net/elytrium/limboauth/Settings.java @@ -108,6 +108,10 @@ public static class MAIN { "Can be disabled to reduce the size of stored data in the database" }) public boolean SAVE_PREMIUM_ACCOUNTS = true; + @Comment({ + "Always checks if current premium account is actually used by saved user" + }) + public boolean ALWAYS_CHECK_PREMIUM_PLAYERS = true; public boolean ENABLE_TOTP = true; public boolean TOTP_NEED_PASSWORD = true; public boolean REGISTER_NEED_REPEAT_PASSWORD = true; @@ -397,6 +401,7 @@ public static class STRINGS { public String WRONG_PASSWORD = "{PRFX} &cPassword is wrong!"; public String NICKNAME_INVALID_KICK = "{PRFX}{NL}&cYour nickname contains forbidden characters. Please, change your nickname!"; + public String FAILED_TO_VERIFY_USERNAME = "{PRFX} &cFailed to verify your username!"; public String RECONNECT_KICK = "{PRFX}{NL}&cReconnect to the server to verify your account!"; @Comment("6 hours by default in ip-limit-valid-time") diff --git a/src/main/java/net/elytrium/limboauth/listener/AuthListener.java b/src/main/java/net/elytrium/limboauth/listener/AuthListener.java index 6ea55a4d..f668f0ab 100644 --- a/src/main/java/net/elytrium/limboauth/listener/AuthListener.java +++ b/src/main/java/net/elytrium/limboauth/listener/AuthListener.java @@ -58,6 +58,7 @@ public class AuthListener { private final Dao playerDao; private final FloodgateApiHolder floodgateApi; private final Component errorOccurred; + private final Component failedToVerifyUsername; public AuthListener(LimboAuth plugin, Dao playerDao, FloodgateApiHolder floodgateApi) { this.plugin = plugin; @@ -65,6 +66,7 @@ public AuthListener(LimboAuth plugin, Dao playerDao, F this.floodgateApi = floodgateApi; this.errorOccurred = LimboAuth.getSerializer().deserialize(Settings.IMP.MAIN.STRINGS.ERROR_OCCURRED); + this.failedToVerifyUsername = LimboAuth.getSerializer().deserialize(Settings.IMP.MAIN.STRINGS.FAILED_TO_VERIFY_USERNAME); } @Subscribe(order = PostOrder.LATE) @@ -78,6 +80,12 @@ public void onPreLoginEvent(PreLoginEvent event) { String username = event.getUsername(); if (!event.getResult().isForceOfflineMode()) { if (this.plugin.isPremium(username)) { + if (Settings.IMP.MAIN.ALWAYS_CHECK_PREMIUM_PLAYERS + && this.plugin.isPremiumInternal(username.toLowerCase(Locale.ROOT)).getState() == PremiumState.ERROR) { + event.setResult(PreLoginComponentResult.denied(this.failedToVerifyUsername)); + return; + } + event.setResult(PreLoginEvent.PreLoginComponentResult.forceOnlineMode()); try {