diff --git a/build.gradle b/build.gradle index e35d73b..3af8ea4 100644 --- a/build.gradle +++ b/build.gradle @@ -23,7 +23,7 @@ dependencies { modCompile "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" // Argon2 library for password hashing - compile 'de.mkammerer:argon2-jvm-nolibs:2.6' + compile 'de.mkammerer:argon2-jvm:2.6' // IDEA stuff implementation 'org.jetbrains:annotations:15.0' diff --git a/src/main/java/org/samo_lego/simpleauth/SimpleAuth.java b/src/main/java/org/samo_lego/simpleauth/SimpleAuth.java index b76b608..e9e9fed 100644 --- a/src/main/java/org/samo_lego/simpleauth/SimpleAuth.java +++ b/src/main/java/org/samo_lego/simpleauth/SimpleAuth.java @@ -1,5 +1,7 @@ package org.samo_lego.simpleauth; +import de.mkammerer.argon2.Argon2; +import de.mkammerer.argon2.Argon2Factory; import net.fabricmc.api.DedicatedServerModInitializer; import net.fabricmc.fabric.api.event.player.AttackBlockCallback; import net.fabricmc.fabric.api.registry.CommandRegistry; @@ -29,9 +31,9 @@ public class SimpleAuth implements DedicatedServerModInitializer { // Creating data directory (database is stored there) File file = new File("./mods/SimpleAuth"); - if (!file.exists() && !file.mkdir()) { + if (!file.exists() && !file.mkdir()) LOGGER.error("Error creating directory"); - } + // Registering the commands CommandRegistry.INSTANCE.register(false, dispatcher -> { @@ -49,7 +51,7 @@ public class SimpleAuth implements DedicatedServerModInitializer { // Connection to database SimpleAuthDatabase.main(); - } + } public static HashSet authenticatedUsers = new HashSet<>(); public static boolean isAuthenticated(ServerPlayerEntity player) { return authenticatedUsers.contains(player); } diff --git a/src/main/java/org/samo_lego/simpleauth/commands/LoginCommand.java b/src/main/java/org/samo_lego/simpleauth/commands/LoginCommand.java index 044d677..3aa973b 100644 --- a/src/main/java/org/samo_lego/simpleauth/commands/LoginCommand.java +++ b/src/main/java/org/samo_lego/simpleauth/commands/LoginCommand.java @@ -2,6 +2,8 @@ package org.samo_lego.simpleauth.commands; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import de.mkammerer.argon2.Argon2; +import de.mkammerer.argon2.Argon2Factory; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.LiteralText; @@ -15,8 +17,11 @@ import static net.minecraft.server.command.CommandManager.argument; import static net.minecraft.server.command.CommandManager.literal; public class LoginCommand { - private static LiteralText PleaseLogin = new LiteralText("§4Type /login to login."); - private static TranslatableText EnterPassword = new TranslatableText("command.simpleauth.password"); + private static LiteralText pleaseLogin = new LiteralText("§4Type /login to login."); + private static TranslatableText enterPassword = new TranslatableText("command.simpleauth.password"); + private static TranslatableText wrongPassword = new TranslatableText("command.simpleauth.wrongPassword"); + private static TranslatableText alreadyAuthenticated = new TranslatableText("command.simpleauth.alreadyAuthenticated"); + private static Text text = new LiteralText("You have entered login command"); public static void registerCommand(CommandDispatcher dispatcher) { // Registering the "/login" command @@ -25,23 +30,40 @@ public class LoginCommand { .executes(ctx -> login(ctx.getSource(), getString(ctx, "password")) // Tries to authenticate user )) .executes(ctx -> { - ctx.getSource().getPlayer().sendMessage(EnterPassword); + ctx.getSource().getPlayer().sendMessage(enterPassword); return 1; })); } + // Method called for checking the password private static int login(ServerCommandSource source, String pass) throws CommandSyntaxException { - String savedHashed = "judf"; // Hashed password provided upon registration - // Getting the player who send the command ServerPlayerEntity player = source.getPlayer(); - // Comparing hashed password with one from the file - if(true/*BCrypt.checkpw(pass, savedHashed)*/){ //From database - Text text = new LiteralText(source.getName() + ", you have entered login command"); - source.getMinecraftServer().getPlayerManager().broadcastChatMessage(text, false); - SimpleAuth.authenticatedUsers.add(player); - System.out.println(SimpleAuth.authenticatedUsers); + if(SimpleAuth.isAuthenticated(player)) { + player.sendMessage(alreadyAuthenticated); + } + else { + // Create instance + Argon2 argon2 = Argon2Factory.create(); + // Read password from user + char[] password = pass.toCharArray(); + + try { + // Hashed password from DB + String hashed = argon2.hash(10, 65536, 1, password); + + // Verify password + if (argon2.verify(hashed, password)) { + SimpleAuth.authenticatedUsers.add(player); + player.sendMessage(text); + } else { + player.sendMessage(wrongPassword); + } + } finally { + // Wipe confidential data + argon2.wipeArray(password); + } } return 1; // Success } diff --git a/src/main/java/org/samo_lego/simpleauth/commands/RegisterCommand.java b/src/main/java/org/samo_lego/simpleauth/commands/RegisterCommand.java index 651c199..41aae99 100644 --- a/src/main/java/org/samo_lego/simpleauth/commands/RegisterCommand.java +++ b/src/main/java/org/samo_lego/simpleauth/commands/RegisterCommand.java @@ -1,14 +1,16 @@ package org.samo_lego.simpleauth.commands; -import com.google.common.io.Files; import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import de.mkammerer.argon2.Argon2; +import de.mkammerer.argon2.Argon2Factory; import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.LiteralText; import net.minecraft.text.TranslatableText; +import org.samo_lego.simpleauth.SimpleAuth; import org.samo_lego.simpleauth.database.SimpleAuthDatabase; - import java.util.Objects; - import static com.mojang.brigadier.arguments.StringArgumentType.getString; import static com.mojang.brigadier.arguments.StringArgumentType.word; import static net.minecraft.server.command.CommandManager.argument; @@ -16,8 +18,9 @@ import static net.minecraft.server.command.CommandManager.literal; public class RegisterCommand { - private static TranslatableText PleaseRegister = new TranslatableText("§4Type /register to login."); - private static TranslatableText EnterPassword = new TranslatableText("command.simpleauth.passwordTwice"); + private static TranslatableText pleaseRegister = new TranslatableText("§4Type /register to login."); + private static TranslatableText enterPassword = new TranslatableText("command.simpleauth.passwordTwice"); + private static TranslatableText alreadyAuthenticated = new TranslatableText("command.simpleauth.alreadyAuthenticated"); public static void registerCommand(CommandDispatcher dispatcher) { @@ -28,25 +31,42 @@ public class RegisterCommand { .executes( ctx -> register(ctx.getSource(), getString(ctx, "password"), getString(ctx, "passwordAgain"))) )) .executes(ctx -> { - ctx.getSource().getPlayer().sendMessage(EnterPassword); + ctx.getSource().getPlayer().sendMessage(enterPassword); return 1; })); } - // Registering our "register" command (ik, sounds a bit confusing) - private static int register(ServerCommandSource source, String pass1, String pass2) { - if(pass1.equals(pass2)){ - // Hashing the password - SimpleAuthDatabase.insert(Objects.requireNonNull(source.getEntity()).getUuidAsString(), source.getName(), pass1); - source.getMinecraftServer().getPlayerManager().broadcastChatMessage( - new LiteralText(source.getName() + ", you have registered successfully!"), - false - ); + // Method called for hashing the password & writing to DB + private static int register(ServerCommandSource source, String pass1, String pass2) throws CommandSyntaxException { + ServerPlayerEntity player = source.getPlayer(); + if(SimpleAuth.isAuthenticated(player)) { + player.sendMessage(alreadyAuthenticated); + } + else if(pass1.equals(pass2)) { // Hashing the password with the Argon2 power + // Create instance + Argon2 argon2 = Argon2Factory.create(); + + // Read password from user + char[] password = pass1.toCharArray(); + + try { + // Hash password + String hash = argon2.hash(10, 65536, 1, password); + // Writing into database + SimpleAuthDatabase.insert(Objects.requireNonNull(source.getEntity()).getUuidAsString(), source.getName(), hash); + SimpleAuth.authenticatedUsers.add(player); + // Letting the player know it was successful + player.sendMessage( + new LiteralText(source.getName() + ", you have registered successfully!") + ); + } finally { + // Wipe confidential data + argon2.wipeArray(password); + } } else - source.getMinecraftServer().getPlayerManager().broadcastChatMessage( - new LiteralText(source.getName() + ", passwords must match!"), - false + player.sendMessage( + new LiteralText(source.getName() + ", passwords must match!") ); return 1; } diff --git a/src/main/java/org/samo_lego/simpleauth/database/SimpleAuthDatabase.java b/src/main/java/org/samo_lego/simpleauth/database/SimpleAuthDatabase.java index a243247..25e660d 100644 --- a/src/main/java/org/samo_lego/simpleauth/database/SimpleAuthDatabase.java +++ b/src/main/java/org/samo_lego/simpleauth/database/SimpleAuthDatabase.java @@ -56,6 +56,7 @@ public class SimpleAuthDatabase { " `Username` VARCHAR(16) NOT NULL,\n" + " `Password` VARCHAR(64) NOT NULL,\n" + " UNIQUE (`UUID`)\n" + + " UNIQUE (`Username`)\n" + ");"; Statement stmt = conn.createStatement(); stmt.execute(sql); @@ -70,7 +71,7 @@ public class SimpleAuthDatabase { String sql = "INSERT INTO users(uuid, username, password) VALUES(?,?,?)"; try (Connection conn = connect(); - PreparedStatement pstmt = conn.prepareStatement(sql)) { + PreparedStatement pstmt = conn.prepareStatement(sql)) { pstmt.setString(1, uuid); pstmt.setString(2, username); pstmt.setString(3, password); @@ -79,7 +80,23 @@ public class SimpleAuthDatabase { LOGGER.error(e.getMessage()); } } + public void selectAll(){ + String sql = "SELECT id, name, capacity FROM users"; + try (Connection conn = this.connect(); + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(sql)){ + + // loop through the result set + while (rs.next()) { + System.out.println(rs.getInt("id") + "\t" + + rs.getString("name") + "\t" + + rs.getDouble("capacity")); + } + } catch (SQLException e) { + System.out.println(e.getMessage()); + } + } private static void disconnect(Connection conn) { try { if (conn != null) { diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 4471169..1f4b7f2 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -3,14 +3,13 @@ "id": "simpleauth", "version": "${version}", - "name": "Simple Authentication mod", + "name": "Simple Authentication Mod", "description": "A mod that tries to keep authentication for players simple via commands.", "authors": [ "samo_lego" ], "contact": { - "homepage": "https://fabricmc.net/", - "sources": "https://github.com/FabricMC/fabric-example-mod" + "sources": "https://github.com/samolego/SimpleAuth" }, "license": "MIT",