aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPetr Ilin <hevav@hevav.dev>2022-12-07 03:00:52 +0300
committerPetr Ilin <hevav@hevav.dev>2022-12-07 03:00:52 +0300
commit6229032bfa9567cee72764ebf0edd8a2351385f4 (patch)
treea9808d8f1abdeba1ee583ed236cdfb085754b41c /src
parentc5301be88a029611d481db5b435fb07578e2e620 (diff)
downloadLimboAuth-6229032bfa9567cee72764ebf0edd8a2351385f4.tar.gz
LimboAuth-6229032bfa9567cee72764ebf0edd8a2351385f4.tar.bz2
LimboAuth-6229032bfa9567cee72764ebf0edd8a2351385f4.zip
Improved check of whether player is premium
Diffstat (limited to 'src')
-rw-r--r--src/main/java/net/elytrium/limboauth/LimboAuth.java42
-rw-r--r--src/main/java/net/elytrium/limboauth/Settings.java31
2 files changed, 62 insertions, 11 deletions
diff --git a/src/main/java/net/elytrium/limboauth/LimboAuth.java b/src/main/java/net/elytrium/limboauth/LimboAuth.java
index b52c32f..ed04f3a 100644
--- a/src/main/java/net/elytrium/limboauth/LimboAuth.java
+++ b/src/main/java/net/elytrium/limboauth/LimboAuth.java
@@ -17,6 +17,8 @@
package net.elytrium.limboauth;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
import com.google.inject.Inject;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.dao.DaoManager;
@@ -565,6 +567,19 @@ public class LimboAuth {
}
}
+ private boolean validateScheme(String json, List<String> scheme) {
+ if (!scheme.isEmpty()) {
+ JsonObject object = (JsonObject) JsonParser.parseString(json);
+ for (String field : scheme) {
+ if (!object.has(field)) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
public boolean isPremiumExternal(String nickname) {
String lowercaseNickname = nickname.toLowerCase(Locale.ROOT);
if (this.premiumCache.containsKey(lowercaseNickname)) {
@@ -572,26 +587,35 @@ public class LimboAuth {
}
try {
- int statusCode = this.client.send(
+ HttpResponse<String> response = this.client.send(
HttpRequest.newBuilder()
.uri(URI.create(String.format(Settings.IMP.MAIN.ISPREMIUM_AUTH_URL, URLEncoder.encode(lowercaseNickname, StandardCharsets.UTF_8))))
.build(),
HttpResponse.BodyHandlers.ofString()
- ).statusCode();
+ );
- boolean isPremium = statusCode == 200;
+ int statusCode = response.statusCode();
- // 429 Too Many Requests.
- if (statusCode != 429) {
- this.premiumCache.put(lowercaseNickname, new CachedPremiumUser(System.currentTimeMillis(), isPremium));
- } else {
+ if (statusCode == Settings.IMP.MAIN.STATUS_CODE_RATE_LIMIT) {
return Settings.IMP.MAIN.ON_RATE_LIMIT_PREMIUM;
}
- return isPremium;
+ if (statusCode == Settings.IMP.MAIN.STATUS_CODE_USER_EXISTS
+ && this.validateScheme(response.body(), Settings.IMP.MAIN.USER_EXISTS_JSON_VALIDATOR_FIELDS)) {
+ this.premiumCache.put(lowercaseNickname, new CachedPremiumUser(System.currentTimeMillis(), true));
+ return true;
+ }
+
+ if (statusCode == Settings.IMP.MAIN.STATUS_CODE_USER_NOT_EXISTS
+ && this.validateScheme(response.body(), Settings.IMP.MAIN.USER_NOT_EXISTS_JSON_VALIDATOR_FIELDS)) {
+ this.premiumCache.put(lowercaseNickname, new CachedPremiumUser(System.currentTimeMillis(), false));
+ return false;
+ }
+
+ return Settings.IMP.MAIN.ON_SERVER_ERROR_PREMIUM;
} catch (IOException | InterruptedException e) {
LOGGER.error("Unable to authenticate with Mojang.", e);
- return Settings.IMP.MAIN.ON_RATE_LIMIT_PREMIUM;
+ return Settings.IMP.MAIN.ON_SERVER_ERROR_PREMIUM;
}
}
diff --git a/src/main/java/net/elytrium/limboauth/Settings.java b/src/main/java/net/elytrium/limboauth/Settings.java
index 8a34d3b..99bb2f0 100644
--- a/src/main/java/net/elytrium/limboauth/Settings.java
+++ b/src/main/java/net/elytrium/limboauth/Settings.java
@@ -139,19 +139,46 @@ public class Settings extends YamlConfig {
@Comment({
"Custom isPremium URL",
"You can use Mojang one's API (set by default)",
- "Or CloudFlare one's: https://api.ashcon.app/mojang/v1/user/%s",
+ "Or CloudFlare one's: https://api.ashcon.app/mojang/v2/user/%s",
"Or use this code to make your own API: https://blog.cloudflare.com/minecraft-api-with-workers-coffeescript/",
- "Or implement your own API, it should just respond with HTTP code 200 only if the player is premium"
+ "Or implement your own API, it should just respond with HTTP code 200 (see parameters below) only if the player is premium"
})
public String ISPREMIUM_AUTH_URL = "https://api.mojang.com/users/profiles/minecraft/%s";
@Comment({
+ "Status codes (see the comment above)",
+ "Responses with unlisted status codes will be identified as responses with a server error",
+ "Set 200 if you use using Mojang or CloudFlare API"
+ })
+ public int STATUS_CODE_USER_EXISTS = 200;
+ @Comment("Set 204 if you use Mojang API, 404 if you use CloudFlare API")
+ public int STATUS_CODE_USER_NOT_EXISTS = 204;
+ @Comment("Set 429 if you use Mojang or CloudFlare API")
+ public int STATUS_CODE_RATE_LIMIT = 429;
+
+ @Comment({
+ "Sample Mojang API response: {\"name\":\"hevav\",\"id\":\"9c7024b2a48746b3b3934f397ae5d70f\"}",
+ "Sample CloudFlare API response: {\"uuid\":\"9c7024b2a48746b3b3934f397ae5d70f\",\"username\":\"hevav\", ...}",
+ "Responses with an invalid scheme will be identified as responses with a server error",
+ "Set this parameter to [], to disable JSON scheme validation"
+ })
+ public List<String> USER_EXISTS_JSON_VALIDATOR_FIELDS = List.of("name", "id");
+ public List<String> USER_NOT_EXISTS_JSON_VALIDATOR_FIELDS = List.of();
+
+ @Comment({
"If Mojang rate-limits your server, we cannot determine if the player is premium or not",
"This option allows you to choose whether every player will be defined as premium or as cracked while Mojang is rate-limiting the server",
"True - as premium; False - as cracked"
})
public boolean ON_RATE_LIMIT_PREMIUM = true;
+ @Comment({
+ "If Mojang API is down, we cannot determine if the player is premium or not",
+ "This option allows you to choose whether every player will be defined as premium or as cracked while Mojang API is unavailable",
+ "True - as premium; False - as cracked"
+ })
+ public boolean ON_SERVER_ERROR_PREMIUM = true;
+
public List<String> REGISTER_COMMAND = List.of("/r", "/reg", "/register");
public List<String> LOGIN_COMMAND = List.of("/l", "/log", "/login");
public List<String> TOTP_COMMAND = List.of("/2fa", "/totp");