diff --git a/build.gradle b/build.gradle index 1096c25..fc6a9ca 100644 --- a/build.gradle +++ b/build.gradle @@ -10,7 +10,7 @@ sourceCompatibility = 17 targetCompatibility = 17 group 'com.xtaolabs.gcauth_oauth' -version '1.1.3' +version '1.2.0' repositories { mavenCentral() @@ -18,7 +18,7 @@ repositories { dependencies { implementation files('lib/grasscutter-1.1.2-dev.jar') - implementation files('lib/gcauth-2.2.1.jar') + implementation files('lib/gcauth-2.4.0.jar') } test { diff --git a/src/main/java/com/xtaolabs/gcauth_oauth/GCAuth_OAuth.java b/src/main/java/com/xtaolabs/gcauth_oauth/GCAuth_OAuth.java index bb9cf35..66aa581 100644 --- a/src/main/java/com/xtaolabs/gcauth_oauth/GCAuth_OAuth.java +++ b/src/main/java/com/xtaolabs/gcauth_oauth/GCAuth_OAuth.java @@ -14,22 +14,26 @@ import java.io.File; public class GCAuth_OAuth extends Plugin { + public static GCAuth_OAuth getInstance() { + return (GCAuth_OAuth) Grasscutter.getPluginManager().getPlugin("GCAuth_OAuth"); + } + @Override public void onEnable() { String Login_Html_Path = PLUGIN("GCAuth/OAuth/login.html"); File Login_Html = new File(Login_Html_Path); if(!Login_Html.exists()) { - Grasscutter.getLogger().warn(String.format("[GCAuth_OAuth] %s not found", Login_Html_Path)); + getLogger().warn(String.format("%s not found", Login_Html_Path)); } else { loadTwitterLogin(); - Grasscutter.getLogger().info("[GCAuth_OAuth] Enabled"); + getLogger().info("GCAuth_OAuth Enabled"); } } @Override public void onDisable() { Grasscutter.setAuthenticationSystem(new DefaultAuthentication()); - Grasscutter.getLogger().info("[GCAuth_OAuth] Disabled"); + getLogger().info("GCAuth_OAuth Disabled"); } public void loadTwitterLogin() { diff --git a/src/main/java/com/xtaolabs/gcauth_oauth/handler/JsonHandler.java b/src/main/java/com/xtaolabs/gcauth_oauth/handler/DesktopRedirectHandler.java similarity index 88% rename from src/main/java/com/xtaolabs/gcauth_oauth/handler/JsonHandler.java rename to src/main/java/com/xtaolabs/gcauth_oauth/handler/DesktopRedirectHandler.java index d2ae085..423e31c 100644 --- a/src/main/java/com/xtaolabs/gcauth_oauth/handler/JsonHandler.java +++ b/src/main/java/com/xtaolabs/gcauth_oauth/handler/DesktopRedirectHandler.java @@ -10,11 +10,11 @@ import io.javalin.Javalin; import static emu.grasscutter.Configuration.*; -public final class JsonHandler implements Router { +public final class DesktopRedirectHandler implements Router { @Override public void applyRoutes(Express express, Javalin javalin) { - express.get("/Api/twitter_login", JsonHandler::handle); + express.get("/Api/twitter_login", DesktopRedirectHandler::handle); } public static void handle(Request req, Response res) { diff --git a/src/main/java/com/xtaolabs/gcauth_oauth/handler/GCAuthAuthenticationHandler.java b/src/main/java/com/xtaolabs/gcauth_oauth/handler/GCAuthAuthenticationHandler.java index ad7adad..54f04f5 100644 --- a/src/main/java/com/xtaolabs/gcauth_oauth/handler/GCAuthAuthenticationHandler.java +++ b/src/main/java/com/xtaolabs/gcauth_oauth/handler/GCAuthAuthenticationHandler.java @@ -1,11 +1,13 @@ package com.xtaolabs.gcauth_oauth.handler; import emu.grasscutter.auth.*; +import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.Account; import emu.grasscutter.server.http.objects.ComboTokenResJson; import emu.grasscutter.server.http.objects.LoginResultJson; import me.exzork.gcauth.handler.GCAuthExternalAuthenticator; +import me.exzork.gcauth.utils.Authentication; public class GCAuthAuthenticationHandler implements AuthenticationSystem { private final Authenticator gcAuthAuthenticator = new GCAuthenticators.GCAuthAuthenticator(); @@ -16,7 +18,8 @@ public class GCAuthAuthenticationHandler implements AuthenticationSystem { @Override public void createAccount(String username, String password) { - // Unhandled. + password = Authentication.generateHash(password); + DatabaseHelper.createAccountWithPassword(username, password); } @Override @@ -26,8 +29,11 @@ public class GCAuthAuthenticationHandler implements AuthenticationSystem { @Override public Account verifyUser(String s) { - // Unhandled. - return null; + String uid = Authentication.getUsernameFromJwt(s); + if (uid == null) { + return null; + } + return DatabaseHelper.getAccountById(uid); } @Override diff --git a/src/main/java/com/xtaolabs/gcauth_oauth/handler/GCAuthenticators.java b/src/main/java/com/xtaolabs/gcauth_oauth/handler/GCAuthenticators.java index dcc63b8..5066d7f 100644 --- a/src/main/java/com/xtaolabs/gcauth_oauth/handler/GCAuthenticators.java +++ b/src/main/java/com/xtaolabs/gcauth_oauth/handler/GCAuthenticators.java @@ -1,5 +1,6 @@ package com.xtaolabs.gcauth_oauth.handler; +import com.xtaolabs.gcauth_oauth.GCAuth_OAuth; import emu.grasscutter.Grasscutter; import emu.grasscutter.auth.AuthenticationSystem; import emu.grasscutter.auth.Authenticator; @@ -7,11 +8,14 @@ import emu.grasscutter.auth.OAuthAuthenticator; import emu.grasscutter.database.DatabaseHelper; import emu.grasscutter.game.Account; import emu.grasscutter.server.http.objects.LoginResultJson; -import static emu.grasscutter.utils.Language.translate; +import me.exzork.gcauth.GCAuth; import me.exzork.gcauth.utils.Authentication; -public class GCAuthenticators { +import static emu.grasscutter.Configuration.ACCOUNT; +import static emu.grasscutter.utils.Language.translate; + +public final class GCAuthenticators { public static class GCAuthAuthenticator implements Authenticator { @Override @@ -21,11 +25,10 @@ public class GCAuthenticators { var requestData = authenticationRequest.getPasswordRequest(); assert requestData != null; // This should never be null. - Account account = Authentication.getAccountByOneTimeToken(requestData.account); + Account account = Authentication.getAccountByOTP(requestData.account); if(account == null) { - Grasscutter.getLogger().info("[GCAuth] Client " + requestData.account + " tried to login with invalid one time token."); response.retcode = -201; - response.message = "Token is invalid"; + response.message = "OTP invalid"; return response; } @@ -34,9 +37,8 @@ public class GCAuthenticators { response.data.account.uid = account.getId(); response.data.account.token = account.generateSessionKey(); response.data.account.email = account.getEmail(); - response.data.account.twitter_name = account.getUsername(); - Grasscutter.getLogger().info("[GCAuth] Client " + requestData.account + " logged in"); + GCAuth.getInstance().getLogger().info("[GCAuth] Client " + requestData.account + " logged in"); return response; } } @@ -54,34 +56,46 @@ public class GCAuthenticators { boolean successfulLogin; String address = request.getRequest().ip(); + String loggerMessage; + int playerCount = Grasscutter.getGameServer().getPlayers().size(); // Log the attempt. - Grasscutter.getLogger().info(translate("messages.dispatch.account.login_token_attempt", address)); + GCAuth_OAuth.getInstance().getLogger().info(translate("messages.dispatch.account.login_token_attempt", address)); - // Get account from database. - Account account = DatabaseHelper.getAccountById(requestData.uid); + if (ACCOUNT.maxPlayer <= -1 || playerCount < ACCOUNT.maxPlayer) { - // Check if account exists/token is valid. - successfulLogin = account != null && account.getSessionKey().equals(requestData.token); + // Get account from database. + Account account = DatabaseHelper.getAccountById(requestData.uid); - // Set response data. - if(successfulLogin) { - response.message = "OK"; - response.data.account.uid = account.getId(); - response.data.account.token = account.getSessionKey(); - response.data.account.email = account.getEmail(); - response.data.account.twitter_name = account.getUsername(); + // Check if account exists/token is valid. + successfulLogin = account != null && account.getSessionKey().equals(requestData.token); + + // Set response data. + if (successfulLogin) { + response.message = "OK"; + response.data.account.uid = account.getId(); + response.data.account.token = account.getSessionKey(); + response.data.account.email = account.getEmail(); + response.data.account.twitter_name = account.getUsername(); + + // Log the login. + loggerMessage = translate("messages.dispatch.account.login_token_success", address, requestData.uid); + } else { + response.retcode = -201; + response.message = translate("messages.dispatch.account.account_cache_error"); + + // Log the failure. + loggerMessage = translate("messages.dispatch.account.login_token_error", address); + } - // Log the login. - Grasscutter.getLogger().info(translate("messages.dispatch.account.login_token_success", address, requestData.uid)); } else { response.retcode = -201; - response.message = translate("messages.dispatch.account.account_cache_error"); + response.message = translate("messages.dispatch.account.server_max_player_limit"); - // Log the failure. - Grasscutter.getLogger().info(translate("messages.dispatch.account.login_token_error", address)); + loggerMessage = translate("messages.dispatch.account.login_max_player_limit", address); } + GCAuth_OAuth.getInstance().getLogger().info(loggerMessage); return response; } } @@ -95,18 +109,20 @@ public class GCAuthenticators { assert request.getResponse() != null; VerifyHandler.handle(request.getRequest(), request.getResponse()); } - - @Override public void handleDesktopRedirection(AuthenticationSystem.AuthenticationRequest request) { + /** + * The type of the client. + * Used for handling redirection. + */ + @Override + public void handleRedirection(AuthenticationSystem.AuthenticationRequest request, ClientType type) { assert request.getResponse() != null; - JsonHandler.handle(request.getRequest(), request.getResponse()); + switch (type) { + case DESKTOP -> DesktopRedirectHandler.handle(request.getRequest(), request.getResponse()); + case MOBILE -> MobileRedirectHandler.handle(request.getRequest(), request.getResponse()); + } } - - @Override public void handleMobileRedirection(AuthenticationSystem.AuthenticationRequest request) { - assert request.getResponse() != null; - sdkHandler.handle(request.getRequest(), request.getResponse()); - } - - @Override public void handleTokenProcess(AuthenticationSystem.AuthenticationRequest request) { + @Override + public void handleTokenProcess(AuthenticationSystem.AuthenticationRequest request) { assert request.getResponse() != null; request.getResponse().send("Authentication is not available with the default authentication method."); } diff --git a/src/main/java/com/xtaolabs/gcauth_oauth/handler/sdkHandler.java b/src/main/java/com/xtaolabs/gcauth_oauth/handler/MobileRedirectHandler.java similarity index 84% rename from src/main/java/com/xtaolabs/gcauth_oauth/handler/sdkHandler.java rename to src/main/java/com/xtaolabs/gcauth_oauth/handler/MobileRedirectHandler.java index 524d1e3..8321fbc 100644 --- a/src/main/java/com/xtaolabs/gcauth_oauth/handler/sdkHandler.java +++ b/src/main/java/com/xtaolabs/gcauth_oauth/handler/MobileRedirectHandler.java @@ -10,11 +10,11 @@ import express.http.Response; import io.javalin.Javalin; -public final class sdkHandler implements Router { +public final class MobileRedirectHandler implements Router { @Override public void applyRoutes(Express express, Javalin javalin) { - express.get("/sdkTwitterLogin.html", sdkHandler::handle); + express.get("/sdkTwitterLogin.html", MobileRedirectHandler::handle); } public static void handle(Request req, Response res) { diff --git a/src/main/java/com/xtaolabs/gcauth_oauth/handler/VerifyHandler.java b/src/main/java/com/xtaolabs/gcauth_oauth/handler/VerifyHandler.java index ecd9c30..864d973 100644 --- a/src/main/java/com/xtaolabs/gcauth_oauth/handler/VerifyHandler.java +++ b/src/main/java/com/xtaolabs/gcauth_oauth/handler/VerifyHandler.java @@ -2,12 +2,12 @@ package com.xtaolabs.gcauth_oauth.handler; import com.auth0.jwt.interfaces.DecodedJWT; +import com.xtaolabs.gcauth_oauth.GCAuth_OAuth; import com.xtaolabs.gcauth_oauth.json.VerifyJson; import com.xtaolabs.gcauth_oauth.utils.parse; import emu.grasscutter.server.http.Router; import emu.grasscutter.server.http.objects.LoginResultJson; -import emu.grasscutter.Grasscutter; import emu.grasscutter.game.Account; import express.Express; @@ -32,11 +32,11 @@ public final class VerifyHandler implements Router { DecodedJWT jwt = parse.deToken(request.access_token); Account account = null; if (jwt != null) { - account = Authentication.getAccountByOneTimeToken(jwt.getClaim("token").asString()); + account = Authentication.getAccountByOTP(jwt.getClaim("token").asString()); } // Login if(account == null) { - Grasscutter.getLogger().info("[GCAuth] Client " + req.ip() + " failed to log in"); + GCAuth_OAuth.getInstance().getLogger().info("Client " + req.ip() + " failed to log in"); responseData.retcode = -201; responseData.message = "Token is invalid"; res.send(responseData); @@ -50,7 +50,7 @@ public final class VerifyHandler implements Router { responseData.data.account.email = account.getEmail(); responseData.data.account.twitter_name = account.getUsername(); - Grasscutter.getLogger().info(String.format("[GCAuth] Client %s logged in as %s", req.ip(), responseData.data.account.uid)); + GCAuth_OAuth.getInstance().getLogger().info(String.format("Client %s logged in as %s", req.ip(), responseData.data.account.uid)); res.send(responseData); }