mirror of
https://github.com/exzork/GCAuth.git
synced 2024-11-30 18:58:54 +00:00
commit
6ffcabc1a8
@ -15,7 +15,7 @@ Grasscutter Authentication System
|
|||||||
- To use access control, you need set the `ACCESS_KEY` in config.json inside plugins/GCAuth. (Optional)
|
- To use access control, you need set the `ACCESS_KEY` in config.json inside plugins/GCAuth. (Optional)
|
||||||
- All payload must be send with `application/json` and Compact JSON format ( without unnecessary spaces )
|
- All payload must be send with `application/json` and Compact JSON format ( without unnecessary spaces )
|
||||||
- Auth endpoint is:
|
- Auth endpoint is:
|
||||||
- Authentication Checking : `/authentication/type` (GET) , it'll return `me.exzork.gcauth.handler.GCAuthAuthenticationHandler` if GCAuth is loaded and enabled.
|
- Authentication Checking : `/authentication/type` (GET) , it'll return `me.exzork.gcauth.handler.GCAuthAuthentication` if GCAuth is loaded and enabled.
|
||||||
- Register: `/authentication/register` (POST)
|
- Register: `/authentication/register` (POST)
|
||||||
```
|
```
|
||||||
{"username":"username","password":"password","password_confirmation":"password_confirmation"}
|
{"username":"username","password":"password","password_confirmation":"password_confirmation"}
|
||||||
|
@ -10,14 +10,14 @@ sourceCompatibility = 17
|
|||||||
targetCompatibility = 17
|
targetCompatibility = 17
|
||||||
|
|
||||||
group 'me.exzork.gcauth'
|
group 'me.exzork.gcauth'
|
||||||
version '2.1.6'
|
version '2.2.0'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation files('lib/grasscutter-1.1.1-dev.jar')
|
implementation files('lib/grasscutter-1.1.2-dev.jar')
|
||||||
implementation 'org.springframework.security:spring-security-crypto:5.6.3'
|
implementation 'org.springframework.security:spring-security-crypto:5.6.3'
|
||||||
implementation 'commons-logging:commons-logging:1.2'
|
implementation 'commons-logging:commons-logging:1.2'
|
||||||
implementation 'com.auth0:java-jwt:3.19.1'
|
implementation 'com.auth0:java-jwt:3.19.1'
|
||||||
|
@ -12,6 +12,7 @@ import java.io.FileReader;
|
|||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
|
||||||
public class GCAuth extends Plugin {
|
public class GCAuth extends Plugin {
|
||||||
@ -21,37 +22,32 @@ public class GCAuth extends Plugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
configFile = new File(getDataFolder().toPath()+ "/config.json");
|
configFile = new File(getDataFolder().toPath() + "/config.json");
|
||||||
if (!configFile.exists()) {
|
if (!configFile.exists()) {
|
||||||
try {
|
try {
|
||||||
Files.createDirectories(configFile.toPath().getParent());
|
Files.createDirectories(configFile.toPath().getParent());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Grasscutter.getLogger().error("[GCAuth] Failed to create config.json");
|
getLogger().error("Failed to create config.json");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadConfig();
|
loadConfig();
|
||||||
if(Grasscutter.getDispatchServer().registerAuthHandler(new GCAuthAuthenticationHandler())) {
|
Grasscutter.setAuthenticationSystem(new GCAuthAuthentication());
|
||||||
Grasscutter.getLogger().info("[GCAuth] GCAuth Enabled!");
|
getLogger().info("GCAuth Enabled!");
|
||||||
config.jwtSecret = Authentication.generateRandomString(32);
|
config.jwtSecret = Authentication.generateRandomString(32);
|
||||||
saveConfig();
|
saveConfig();
|
||||||
if(Grasscutter.getConfig().account.autoCreate) {
|
if (Grasscutter.getConfig().account.autoCreate) {
|
||||||
Grasscutter.getLogger().warn("[GCAuth] GCAuth does not support automatic account creation. Please disable in the server's config.json or just ignore this warning.");
|
getLogger().warn("GCAuth does not support automatic account creation. Please disable in the server's config.json or just ignore this warning.");
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Grasscutter.getLogger().error("[GCAuth] GCAuth could not be enabled");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
if(Grasscutter.getDispatchServer().getAuthHandler().getClass().equals(GCAuthAuthenticationHandler.class)) {
|
|
||||||
Grasscutter.getDispatchServer().resetAuthHandler();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadConfig() {
|
public void loadConfig() {
|
||||||
try (FileReader file = new FileReader(configFile)) {
|
try (FileReader file = new FileReader(configFile)) {
|
||||||
config = gson.fromJson(file,Config.class);
|
config = gson.fromJson(file, Config.class);
|
||||||
saveConfig();
|
saveConfig();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
config = new Config();
|
config = new Config();
|
||||||
@ -63,9 +59,15 @@ public class GCAuth extends Plugin {
|
|||||||
try (FileWriter file = new FileWriter(configFile)) {
|
try (FileWriter file = new FileWriter(configFile)) {
|
||||||
file.write(gson.toJson(config));
|
file.write(gson.toJson(config));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Grasscutter.getLogger().error("[GCAuth] Unable to save config file.");
|
getLogger().error("Unable to save config file.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static Config getConfigStatic() {return config;}
|
|
||||||
public Config getConfig() {return config;}
|
public static Config getConfigStatic() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Config getConfig() {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,71 +0,0 @@
|
|||||||
package me.exzork.gcauth.handler;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import emu.grasscutter.Grasscutter;
|
|
||||||
import emu.grasscutter.game.Account;
|
|
||||||
import express.http.HttpContextHandler;
|
|
||||||
import express.http.Request;
|
|
||||||
import express.http.Response;
|
|
||||||
import me.exzork.gcauth.GCAuth;
|
|
||||||
import me.exzork.gcauth.json.AuthResponseJson;
|
|
||||||
import me.exzork.gcauth.json.ChangePasswordAccount;
|
|
||||||
import me.exzork.gcauth.utils.Authentication;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class ChangePasswordHandler implements HttpContextHandler {
|
|
||||||
@Override
|
|
||||||
public void handle(Request request, Response response) throws IOException {
|
|
||||||
AuthResponseJson authResponse = new AuthResponseJson();
|
|
||||||
|
|
||||||
try {
|
|
||||||
String requestBody = request.ctx().body();
|
|
||||||
if (requestBody.isEmpty()) {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "EMPTY_BODY"; // ENG = "No data was sent with the request"
|
|
||||||
authResponse.jwt = "";
|
|
||||||
} else {
|
|
||||||
ChangePasswordAccount changePasswordAccount = new Gson().fromJson(requestBody, ChangePasswordAccount.class);
|
|
||||||
if (!GCAuth.getConfigStatic().ACCESS_KEY.isEmpty() && !GCAuth.getConfigStatic().ACCESS_KEY.equals(changePasswordAccount.access_key)){
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "ERROR_ACCESS_KEY"; // ENG = "Error access key was sent with the request"
|
|
||||||
authResponse.jwt = "";
|
|
||||||
} else {
|
|
||||||
if (changePasswordAccount.new_password.equals(changePasswordAccount.new_password_confirmation)) {
|
|
||||||
Account account = Authentication.getAccountByUsernameAndPassword(changePasswordAccount.username, changePasswordAccount.old_password);
|
|
||||||
if (account == null) {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "INVALID_ACCOUNT"; // ENG = "Invalid username or password"
|
|
||||||
authResponse.jwt = "";
|
|
||||||
} else {
|
|
||||||
if (changePasswordAccount.new_password.length() >= 8) {
|
|
||||||
String newPassword = Authentication.generateHash(changePasswordAccount.new_password);
|
|
||||||
account.setPassword(newPassword);
|
|
||||||
account.save();
|
|
||||||
authResponse.success = true;
|
|
||||||
authResponse.message = "";
|
|
||||||
authResponse.jwt = "";
|
|
||||||
} else {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "PASSWORD_INVALID"; // ENG = "Password must be at least 8 characters long"
|
|
||||||
authResponse.jwt = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "PASSWORD_MISMATCH"; // ENG = "Passwords do not match."
|
|
||||||
authResponse.jwt = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "UNKNOWN"; // ENG = "An unknown error has occurred..."
|
|
||||||
authResponse.jwt = "";
|
|
||||||
Grasscutter.getLogger().error("[Dispatch] Error while changing user password.");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
response.send(authResponse);
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,50 @@
|
|||||||
|
package me.exzork.gcauth.handler;
|
||||||
|
|
||||||
|
import emu.grasscutter.auth.AuthenticationSystem;
|
||||||
|
import emu.grasscutter.auth.Authenticator;
|
||||||
|
import emu.grasscutter.auth.DefaultAuthenticators;
|
||||||
|
import emu.grasscutter.auth.ExternalAuthenticator;
|
||||||
|
import emu.grasscutter.server.http.objects.ComboTokenResJson;
|
||||||
|
import emu.grasscutter.server.http.objects.LoginResultJson;
|
||||||
|
|
||||||
|
public class GCAuthAuthentication implements AuthenticationSystem {
|
||||||
|
private final Authenticator<LoginResultJson> gcAuthAuthenticator = new GCAuthenticators.GCAuthAuthenticator();
|
||||||
|
private final Authenticator<LoginResultJson> tokenAuthenticator = new DefaultAuthenticators.TokenAuthenticator();
|
||||||
|
private final Authenticator<ComboTokenResJson> sessionKeyAuthenticator = new DefaultAuthenticators.SessionKeyAuthenticator();
|
||||||
|
private final GCAuthAuthenticationHandler handler = new GCAuthAuthenticationHandler();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createAccount(String username, String password) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resetPassword(String s) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean verifyUser(String s) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authenticator<LoginResultJson> getPasswordAuthenticator() {
|
||||||
|
return gcAuthAuthenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authenticator<LoginResultJson> getTokenAuthenticator() {
|
||||||
|
return tokenAuthenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Authenticator<ComboTokenResJson> getSessionKeyAuthenticator() {
|
||||||
|
return sessionKeyAuthenticator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExternalAuthenticator getExternalAuthenticator() {
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
}
|
@ -1,75 +1,188 @@
|
|||||||
package me.exzork.gcauth.handler;
|
package me.exzork.gcauth.handler;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
import emu.grasscutter.Grasscutter;
|
import emu.grasscutter.Grasscutter;
|
||||||
|
import emu.grasscutter.auth.AuthenticationSystem;
|
||||||
|
import emu.grasscutter.auth.ExternalAuthenticator;
|
||||||
|
import emu.grasscutter.database.DatabaseHelper;
|
||||||
import emu.grasscutter.game.Account;
|
import emu.grasscutter.game.Account;
|
||||||
import emu.grasscutter.server.dispatch.authentication.AuthenticationHandler;
|
import me.exzork.gcauth.GCAuth;
|
||||||
import emu.grasscutter.server.dispatch.json.LoginAccountRequestJson;
|
import me.exzork.gcauth.json.AuthResponseJson;
|
||||||
import emu.grasscutter.server.dispatch.json.LoginResultJson;
|
import me.exzork.gcauth.json.ChangePasswordAccount;
|
||||||
import express.http.Request;
|
import me.exzork.gcauth.json.LoginGenerateToken;
|
||||||
import express.http.Response;
|
import me.exzork.gcauth.json.RegisterAccount;
|
||||||
import me.exzork.gcauth.utils.Authentication;
|
import me.exzork.gcauth.utils.Authentication;
|
||||||
|
|
||||||
import java.io.IOException;
|
public class GCAuthAuthenticationHandler implements ExternalAuthenticator {
|
||||||
|
|
||||||
public class GCAuthAuthenticationHandler implements AuthenticationHandler {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleLogin(Request req, Response res) {
|
public void handleLogin(AuthenticationSystem.AuthenticationRequest authenticationRequest) {
|
||||||
|
AuthResponseJson authResponse = new AuthResponseJson();
|
||||||
try {
|
try {
|
||||||
new LoginHandler().handle(req, res);
|
String requestBody = authenticationRequest.getRequest().ctx().body();
|
||||||
} catch (IOException e) {
|
if (requestBody.isEmpty()) {
|
||||||
Grasscutter.getLogger().warn("[GCAuth] Unable to handle login request");
|
authResponse.success = false;
|
||||||
|
authResponse.message = "EMPTY_BODY"; // ENG = "No data was sent with the request"
|
||||||
|
authResponse.jwt = "";
|
||||||
|
} else {
|
||||||
|
LoginGenerateToken loginGenerateToken = new Gson().fromJson(requestBody, LoginGenerateToken.class);
|
||||||
|
if (!GCAuth.getConfigStatic().ACCESS_KEY.isEmpty() && !GCAuth.getConfigStatic().ACCESS_KEY.equals(loginGenerateToken.access_key)){
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "ERROR_ACCESS_KEY"; // ENG = "Error access key was sent with the request"
|
||||||
|
authResponse.jwt = "";
|
||||||
|
} else {
|
||||||
|
Account account = Authentication.getAccountByUsernameAndPassword(loginGenerateToken.username, loginGenerateToken.password);
|
||||||
|
if (account == null) {
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "INVALID_ACCOUNT"; // ENG = "Invalid username or password"
|
||||||
|
authResponse.jwt = "";
|
||||||
|
} else {
|
||||||
|
if (account.getPassword() != null && !account.getPassword().isEmpty()) {
|
||||||
|
authResponse.success = true;
|
||||||
|
authResponse.message = "";
|
||||||
|
authResponse.jwt = Authentication.generateJwt(account);
|
||||||
|
} else {
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "NO_PASSWORD"; // ENG = "There is no account password set. Please create a password by resetting it."
|
||||||
|
authResponse.jwt = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "UNKNOWN"; // ENG = "An unknown error has occurred..."
|
||||||
|
authResponse.jwt = "";
|
||||||
|
Grasscutter.getLogger().error("[Dispatch] An error occurred while a user was logging in.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
authenticationRequest.getResponse().send(authResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleRegister(Request req, Response res) {
|
public void handleAccountCreation(AuthenticationSystem.AuthenticationRequest authenticationRequest) {
|
||||||
|
AuthResponseJson authResponse = new AuthResponseJson();
|
||||||
|
Account account = null;
|
||||||
try {
|
try {
|
||||||
new RegisterHandler().handle(req, res);
|
String requestBody = authenticationRequest.getRequest().ctx().body();
|
||||||
} catch (IOException e) {
|
if (requestBody.isEmpty()) {
|
||||||
Grasscutter.getLogger().warn("[GCAuth] Unable to handle register request");
|
authResponse.success = false;
|
||||||
|
authResponse.message = "EMPTY_BODY"; // ENG = "No data was sent with the request"
|
||||||
|
authResponse.jwt = "";
|
||||||
|
} else {
|
||||||
|
RegisterAccount registerAccount = new Gson().fromJson(requestBody, RegisterAccount.class);
|
||||||
|
if (!GCAuth.getConfigStatic().ACCESS_KEY.isEmpty() && !GCAuth.getConfigStatic().ACCESS_KEY.equals(registerAccount.access_key)){
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "ERROR_ACCESS_KEY"; // ENG = "Error access key was sent with the request"
|
||||||
|
authResponse.jwt = "";
|
||||||
|
} else {
|
||||||
|
if (registerAccount.password.equals(registerAccount.password_confirmation)) {
|
||||||
|
if (registerAccount.password.length() >= 8) {
|
||||||
|
String password = Authentication.generateHash(registerAccount.password);
|
||||||
|
try{
|
||||||
|
account = Authentication.getAccountByUsernameAndPassword(registerAccount.username, "");
|
||||||
|
if (account != null) {
|
||||||
|
account.setPassword(password);
|
||||||
|
account.save();
|
||||||
|
authResponse.success = true;
|
||||||
|
authResponse.message = "";
|
||||||
|
authResponse.jwt = "";
|
||||||
|
} else {
|
||||||
|
account = DatabaseHelper.createAccountWithPassword(registerAccount.username, password);
|
||||||
|
if (account == null) {
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "USERNAME_TAKEN"; // ENG = "Username has already been taken by another user."
|
||||||
|
authResponse.jwt = "";
|
||||||
|
} else {
|
||||||
|
authResponse.success = true;
|
||||||
|
authResponse.message = "";
|
||||||
|
authResponse.jwt = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}catch (Exception ignored){
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "UNKNOWN"; // ENG = "Username has already been taken by another user."
|
||||||
|
authResponse.jwt = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "PASSWORD_INVALID"; // ENG = "Password must be at least 8 characters long"
|
||||||
|
authResponse.jwt = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "PASSWORD_MISMATCH"; // ENG = "Passwords do not match."
|
||||||
|
authResponse.jwt = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "UNKNOWN"; // ENG = "An unknown error has occurred..."
|
||||||
|
authResponse.jwt = "";
|
||||||
|
Grasscutter.getLogger().error("[Dispatch] An error occurred while creating an account.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
if (authResponse.success) {
|
||||||
|
if (GCAuth.getConfigStatic().defaultPermissions.length > 0) {
|
||||||
|
for (String permission : GCAuth.getConfigStatic().defaultPermissions) {
|
||||||
|
account.addPermission(permission);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
authenticationRequest.getResponse().send(authResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleChangePassword(Request req, Response res) {
|
public void handlePasswordReset(AuthenticationSystem.AuthenticationRequest authenticationRequest) {
|
||||||
|
AuthResponseJson authResponse = new AuthResponseJson();
|
||||||
try {
|
try {
|
||||||
new ChangePasswordHandler().handle(req, res);
|
String requestBody = authenticationRequest.getRequest().ctx().body();
|
||||||
} catch (IOException e) {
|
if (requestBody.isEmpty()) {
|
||||||
Grasscutter.getLogger().warn("[GCAuth] Unable to handle change password request");
|
authResponse.success = false;
|
||||||
|
authResponse.message = "EMPTY_BODY"; // ENG = "No data was sent with the request"
|
||||||
|
authResponse.jwt = "";
|
||||||
|
} else {
|
||||||
|
ChangePasswordAccount changePasswordAccount = new Gson().fromJson(requestBody, ChangePasswordAccount.class);
|
||||||
|
if (!GCAuth.getConfigStatic().ACCESS_KEY.isEmpty() && !GCAuth.getConfigStatic().ACCESS_KEY.equals(changePasswordAccount.access_key)){
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "ERROR_ACCESS_KEY"; // ENG = "Error access key was sent with the request"
|
||||||
|
authResponse.jwt = "";
|
||||||
|
} else {
|
||||||
|
if (changePasswordAccount.new_password.equals(changePasswordAccount.new_password_confirmation)) {
|
||||||
|
Account account = Authentication.getAccountByUsernameAndPassword(changePasswordAccount.username, changePasswordAccount.old_password);
|
||||||
|
if (account == null) {
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "INVALID_ACCOUNT"; // ENG = "Invalid username or password"
|
||||||
|
authResponse.jwt = "";
|
||||||
|
} else {
|
||||||
|
if (changePasswordAccount.new_password.length() >= 8) {
|
||||||
|
String newPassword = Authentication.generateHash(changePasswordAccount.new_password);
|
||||||
|
account.setPassword(newPassword);
|
||||||
|
account.save();
|
||||||
|
authResponse.success = true;
|
||||||
|
authResponse.message = "";
|
||||||
|
authResponse.jwt = "";
|
||||||
|
} else {
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "PASSWORD_INVALID"; // ENG = "Password must be at least 8 characters long"
|
||||||
|
authResponse.jwt = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "PASSWORD_MISMATCH"; // ENG = "Passwords do not match."
|
||||||
|
authResponse.jwt = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
authResponse.success = false;
|
||||||
|
authResponse.message = "UNKNOWN"; // ENG = "An unknown error has occurred..."
|
||||||
|
authResponse.jwt = "";
|
||||||
|
Grasscutter.getLogger().error("[Dispatch] Error while changing user password.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
authenticationRequest.getResponse().send(authResponse);
|
||||||
public boolean verifyUser(String details) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LoginResultJson handleGameLogin(Request request, LoginAccountRequestJson requestData) {
|
|
||||||
LoginResultJson responseData = new LoginResultJson();
|
|
||||||
|
|
||||||
// Login
|
|
||||||
Account account = Authentication.getAccountByOneTimeToken(requestData.account);
|
|
||||||
if(account == null) {
|
|
||||||
Grasscutter.getLogger().info("[GCAuth] Client " + request.ip() + " failed to log in");
|
|
||||||
responseData.retcode = -201;
|
|
||||||
responseData.message = "Token is invalid";
|
|
||||||
return responseData;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Account was found, log the player in
|
|
||||||
responseData.message = "OK";
|
|
||||||
responseData.data.account.uid = account.getId();
|
|
||||||
responseData.data.account.token = account.generateSessionKey();
|
|
||||||
responseData.data.account.email = account.getEmail();
|
|
||||||
|
|
||||||
Grasscutter.getLogger().info(String.format("[GCAuth] Client %s logged in as %s", request.ip(), responseData.data.account.uid));
|
|
||||||
|
|
||||||
return responseData;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
src/main/java/me/exzork/gcauth/handler/GCAuthenticators.java
Normal file
39
src/main/java/me/exzork/gcauth/handler/GCAuthenticators.java
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package me.exzork.gcauth.handler;
|
||||||
|
|
||||||
|
import emu.grasscutter.Grasscutter;
|
||||||
|
import emu.grasscutter.auth.AuthenticationSystem;
|
||||||
|
import emu.grasscutter.auth.Authenticator;
|
||||||
|
import emu.grasscutter.database.DatabaseHelper;
|
||||||
|
import emu.grasscutter.game.Account;
|
||||||
|
import emu.grasscutter.server.http.objects.LoginResultJson;
|
||||||
|
import me.exzork.gcauth.utils.Authentication;
|
||||||
|
|
||||||
|
public class GCAuthenticators {
|
||||||
|
|
||||||
|
public static class GCAuthAuthenticator implements Authenticator<LoginResultJson> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LoginResultJson authenticate(AuthenticationSystem.AuthenticationRequest authenticationRequest) {
|
||||||
|
var response = new LoginResultJson();
|
||||||
|
|
||||||
|
var requestData = authenticationRequest.getPasswordRequest();
|
||||||
|
assert requestData != null;
|
||||||
|
Account account = Authentication.getAccountByOneTimeToken(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";
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Account was found, log the player in
|
||||||
|
response.message = "OK";
|
||||||
|
response.data.account.uid = account.getId();
|
||||||
|
response.data.account.token = account.generateSessionKey();
|
||||||
|
response.data.account.email = account.getEmail();
|
||||||
|
|
||||||
|
Grasscutter.getLogger().info("[GCAuth] Client " + requestData.account + " logged in");
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,63 +0,0 @@
|
|||||||
package me.exzork.gcauth.handler;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import emu.grasscutter.Grasscutter;
|
|
||||||
import emu.grasscutter.game.Account;
|
|
||||||
import express.http.HttpContextHandler;
|
|
||||||
import express.http.Request;
|
|
||||||
import express.http.Response;
|
|
||||||
import me.exzork.gcauth.GCAuth;
|
|
||||||
import me.exzork.gcauth.json.AuthResponseJson;
|
|
||||||
import me.exzork.gcauth.json.LoginGenerateToken;
|
|
||||||
import me.exzork.gcauth.utils.Authentication;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class LoginHandler implements HttpContextHandler {
|
|
||||||
@Override
|
|
||||||
public void handle(Request request, Response response) throws IOException {
|
|
||||||
AuthResponseJson authResponse = new AuthResponseJson();
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
String requestBody = request.ctx().body();
|
|
||||||
if (requestBody.isEmpty()) {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "EMPTY_BODY"; // ENG = "No data was sent with the request"
|
|
||||||
authResponse.jwt = "";
|
|
||||||
} else {
|
|
||||||
LoginGenerateToken loginGenerateToken = new Gson().fromJson(requestBody, LoginGenerateToken.class);
|
|
||||||
if (!GCAuth.getConfigStatic().ACCESS_KEY.isEmpty() && !GCAuth.getConfigStatic().ACCESS_KEY.equals(loginGenerateToken.access_key)){
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "ERROR_ACCESS_KEY"; // ENG = "Error access key was sent with the request"
|
|
||||||
authResponse.jwt = "";
|
|
||||||
} else {
|
|
||||||
Account account = Authentication.getAccountByUsernameAndPassword(loginGenerateToken.username, loginGenerateToken.password);
|
|
||||||
if (account == null) {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "INVALID_ACCOUNT"; // ENG = "Invalid username or password"
|
|
||||||
authResponse.jwt = "";
|
|
||||||
} else {
|
|
||||||
if (account.getPassword() != null && !account.getPassword().isEmpty()) {
|
|
||||||
authResponse.success = true;
|
|
||||||
authResponse.message = "";
|
|
||||||
authResponse.jwt = Authentication.generateJwt(account);
|
|
||||||
} else {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "NO_PASSWORD"; // ENG = "There is no account password set. Please create a password by resetting it."
|
|
||||||
authResponse.jwt = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "UNKNOWN"; // ENG = "An unknown error has occurred..."
|
|
||||||
authResponse.jwt = "";
|
|
||||||
Grasscutter.getLogger().error("[Dispatch] An error occurred while a user was logging in.");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
response.send(authResponse);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
package me.exzork.gcauth.handler;
|
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import emu.grasscutter.Grasscutter;
|
|
||||||
import emu.grasscutter.database.DatabaseHelper;
|
|
||||||
import emu.grasscutter.game.Account;
|
|
||||||
import express.http.HttpContextHandler;
|
|
||||||
import express.http.Request;
|
|
||||||
import express.http.Response;
|
|
||||||
import me.exzork.gcauth.GCAuth;
|
|
||||||
import me.exzork.gcauth.json.AuthResponseJson;
|
|
||||||
import me.exzork.gcauth.json.RegisterAccount;
|
|
||||||
import me.exzork.gcauth.utils.Authentication;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class RegisterHandler implements HttpContextHandler {
|
|
||||||
@Override
|
|
||||||
public void handle(Request request, Response response) throws IOException {
|
|
||||||
AuthResponseJson authResponse = new AuthResponseJson();
|
|
||||||
Account account = null;
|
|
||||||
try {
|
|
||||||
String requestBody = request.ctx().body();
|
|
||||||
if (requestBody.isEmpty()) {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "EMPTY_BODY"; // ENG = "No data was sent with the request"
|
|
||||||
authResponse.jwt = "";
|
|
||||||
} else {
|
|
||||||
RegisterAccount registerAccount = new Gson().fromJson(requestBody, RegisterAccount.class);
|
|
||||||
if (!GCAuth.getConfigStatic().ACCESS_KEY.isEmpty() && !GCAuth.getConfigStatic().ACCESS_KEY.equals(registerAccount.access_key)){
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "ERROR_ACCESS_KEY"; // ENG = "Error access key was sent with the request"
|
|
||||||
authResponse.jwt = "";
|
|
||||||
} else {
|
|
||||||
if (registerAccount.password.equals(registerAccount.password_confirmation)) {
|
|
||||||
if (registerAccount.password.length() >= 8) {
|
|
||||||
String password = Authentication.generateHash(registerAccount.password);
|
|
||||||
try{
|
|
||||||
account = Authentication.getAccountByUsernameAndPassword(registerAccount.username, "");
|
|
||||||
if (account != null) {
|
|
||||||
account.setPassword(password);
|
|
||||||
account.save();
|
|
||||||
authResponse.success = true;
|
|
||||||
authResponse.message = "";
|
|
||||||
authResponse.jwt = "";
|
|
||||||
} else {
|
|
||||||
account = DatabaseHelper.createAccountWithPassword(registerAccount.username, password);
|
|
||||||
if (account == null) {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "USERNAME_TAKEN"; // ENG = "Username has already been taken by another user."
|
|
||||||
authResponse.jwt = "";
|
|
||||||
} else {
|
|
||||||
authResponse.success = true;
|
|
||||||
authResponse.message = "";
|
|
||||||
authResponse.jwt = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}catch (Exception ignored){
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "UNKNOWN"; // ENG = "Username has already been taken by another user."
|
|
||||||
authResponse.jwt = "";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "PASSWORD_INVALID"; // ENG = "Password must be at least 8 characters long"
|
|
||||||
authResponse.jwt = "";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "PASSWORD_MISMATCH"; // ENG = "Passwords do not match."
|
|
||||||
authResponse.jwt = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
authResponse.success = false;
|
|
||||||
authResponse.message = "UNKNOWN"; // ENG = "An unknown error has occurred..."
|
|
||||||
authResponse.jwt = "";
|
|
||||||
Grasscutter.getLogger().error("[Dispatch] An error occurred while creating an account.");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
if (authResponse.success) {
|
|
||||||
if (GCAuth.getConfigStatic().defaultPermissions.length > 0) {
|
|
||||||
for (String permission : GCAuth.getConfigStatic().defaultPermissions) {
|
|
||||||
account.addPermission(permission);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
response.send(authResponse);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user