diff --git a/LaunchServer/source/auth/handler/AuthHandler.java b/LaunchServer/source/auth/handler/AuthHandler.java index bca0496..f578748 100644 --- a/LaunchServer/source/auth/handler/AuthHandler.java +++ b/LaunchServer/source/auth/handler/AuthHandler.java @@ -27,6 +27,7 @@ registerHandler("textFile", TextFileAuthHandler::new); registerHandler("mysql", MySQLAuthHandler::new); registerHandler("postgresql", PostgreSQLAuthHandler::new); + registerHandler("json", JsonAuthHandler::new); } @LauncherAPI diff --git a/LaunchServer/source/auth/handler/CachedAuthHandler.java b/LaunchServer/source/auth/handler/CachedAuthHandler.java index f4c24c5..c2c714a 100644 --- a/LaunchServer/source/auth/handler/CachedAuthHandler.java +++ b/LaunchServer/source/auth/handler/CachedAuthHandler.java @@ -25,7 +25,7 @@ } @Override - public final synchronized UUID auth(AuthProviderResult result) throws IOException + public synchronized UUID auth(AuthProviderResult result) throws IOException { Entry entry = getEntry(result.username); if (entry == null || !updateAuth(entry.uuid, entry.username, result.accessToken)) @@ -41,7 +41,7 @@ } @Override - public final synchronized UUID checkServer(String username, String serverID) throws IOException + public synchronized UUID checkServer(String username, String serverID) throws IOException { Entry entry = getEntry(username); return entry != null && username.equals(entry.username) && @@ -49,7 +49,7 @@ } @Override - public final synchronized boolean joinServer(String username, String accessToken, String serverID) throws IOException + public synchronized boolean joinServer(String username, String accessToken, String serverID) throws IOException { Entry entry = getEntry(username); if (entry == null || !username.equals(entry.username) || !accessToken.equals(entry.accessToken) || @@ -64,14 +64,14 @@ } @Override - public final synchronized UUID usernameToUUID(String username) throws IOException + public synchronized UUID usernameToUUID(String username) throws IOException { Entry entry = getEntry(username); return entry == null ? null : entry.uuid; } @Override - public final synchronized String uuidToUsername(UUID uuid) throws IOException + public synchronized String uuidToUsername(UUID uuid) throws IOException { Entry entry = getEntry(uuid); return entry == null ? null : entry.username; diff --git a/LaunchServer/source/auth/handler/JsonAuthHandler.java b/LaunchServer/source/auth/handler/JsonAuthHandler.java new file mode 100644 index 0000000..14fd7e1 --- /dev/null +++ b/LaunchServer/source/auth/handler/JsonAuthHandler.java @@ -0,0 +1,177 @@ +package launchserver.auth.handler; + +import com.eclipsesource.json.Json; +import com.eclipsesource.json.JsonObject; +import com.eclipsesource.json.JsonValue; +import launcher.helper.IOHelper; +import launcher.helper.VerifyHelper; +import launcher.serialize.config.entry.BlockConfigEntry; +import launcher.serialize.config.entry.StringConfigEntry; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.util.UUID; + +public class JsonAuthHandler extends CachedAuthHandler +{ + + private static final int TIMEOUT = 10; + private final URL url; + private final URL urlCheckServer; + private final URL urlJoinServer; + private final URL urlUsernameToUUID; + private final URL urlUUIDToUsername; + private final String userKeyName; + private final String serverIDKeyName; + private final String accessTokenKeyName; + private final String uuidKeyName; + private final String responseUserKeyName; + private final String responseErrorKeyName; + + protected JsonAuthHandler(BlockConfigEntry block) + { + super(block); + String configUrl = block.getEntryValue("url", StringConfigEntry.class); + String configUrlCheckServer = block.getEntryValue("urlCheckServer", StringConfigEntry.class); + String configUrlJoinServer = block.getEntryValue("urlJoinServer", StringConfigEntry.class); + String configUrlUsernameUUID = block.getEntryValue("urlUsernameToUUID", StringConfigEntry.class); + String configUrlUUIDUsername = block.getEntryValue("urlUUIDToUsername", StringConfigEntry.class); + userKeyName = VerifyHelper.verify(block.getEntryValue("userKeyName", StringConfigEntry.class), + VerifyHelper.NOT_EMPTY, "Username key name can't be empty"); + serverIDKeyName = VerifyHelper.verify(block.getEntryValue("serverIDKeyName", StringConfigEntry.class), + VerifyHelper.NOT_EMPTY, "ServerID key name can't be empty"); + uuidKeyName = VerifyHelper.verify(block.getEntryValue("UUIDKeyName", StringConfigEntry.class), + VerifyHelper.NOT_EMPTY, "UUID key name can't be empty"); + accessTokenKeyName = VerifyHelper.verify(block.getEntryValue("accessTokenKeyName", StringConfigEntry.class), + VerifyHelper.NOT_EMPTY, "AccessToken key name can't be empty"); + responseUserKeyName = VerifyHelper.verify(block.getEntryValue("responseUserKeyName", StringConfigEntry.class), + VerifyHelper.NOT_EMPTY, "Response username key can't be empty"); + responseErrorKeyName = VerifyHelper.verify(block.getEntryValue("responseErrorKeyName", StringConfigEntry.class), + VerifyHelper.NOT_EMPTY, "Response error key can't be empty"); + url = IOHelper.convertToURL(configUrl); + urlCheckServer = IOHelper.convertToURL(configUrlCheckServer); + urlJoinServer = IOHelper.convertToURL(configUrlJoinServer); + urlUsernameToUUID = IOHelper.convertToURL(configUrlUsernameUUID); + urlUUIDToUsername = IOHelper.convertToURL(configUrlUUIDUsername); + } + + @Override + public UUID checkServer(String username, String serverID) throws IOException + { + JsonObject request = Json.object().add(userKeyName, username).add(serverIDKeyName, serverID); + JsonObject result = jsonRequest(request, urlCheckServer); + String value; + if ((value = result.getString(uuidKeyName, null)) != null) + { + return UUID.fromString(value); + } + return super.checkServer(username, serverID); + } + + @Override + public void close() + { + + } + + @Override + protected Entry fetchEntry(String username) throws IOException + { + JsonObject request = Json.object().add(userKeyName, username); + JsonObject result = jsonRequest(request, urlCheckServer); + UUID uuid = UUID.fromString(result.getString(uuidKeyName, null)); + String accessToken = result.getString(accessTokenKeyName, null); + String serverID = result.getString(serverIDKeyName, null); + if (accessToken == null || serverID == null) + { + return null; + } + + return new Entry(uuid, username, accessToken, serverID); + } + + @Override + protected Entry fetchEntry(UUID uuid) throws IOException + { + JsonObject request = Json.object().add(uuidKeyName, uuid.toString()); + JsonObject result = jsonRequest(request, urlCheckServer); + String username = result.getString(userKeyName, null); + String accessToken = result.getString(accessTokenKeyName, null); + String serverID = result.getString(serverIDKeyName, null); + if (username == null || accessToken == null || serverID == null) + { + return null; + } + + return new Entry(uuid, username, accessToken, serverID); + } + + @Override + public boolean joinServer(String username, String accessToken, String serverID) throws IOException + { + JsonObject request = Json.object().add(userKeyName, username).add(serverIDKeyName, serverID).add(accessTokenKeyName, accessToken); + jsonRequest(request, urlJoinServer); + return super.joinServer(username, accessToken, serverID); + } + + public JsonObject jsonRequest(JsonObject request, URL url) throws IOException + { + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoInput(true); + connection.setDoOutput(true); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8"); + connection.setRequestProperty("Accept", "application/json"); + if (TIMEOUT > 0) + { + connection.setConnectTimeout(TIMEOUT); + } + + OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), StandardCharsets.UTF_8); + writer.write(request.toString()); + writer.flush(); + writer.close(); + + InputStreamReader reader; + int statusCode = connection.getResponseCode(); + + if (200 <= statusCode && statusCode < 300) + { + reader = new InputStreamReader(connection.getInputStream(), StandardCharsets.UTF_8); + } + else + { + reader = new InputStreamReader(connection.getErrorStream(), StandardCharsets.UTF_8); + } + JsonValue content = Json.parse(reader); + if (!content.isObject()) + { + authError("Authentication server response is malformed"); + } + + JsonObject response = content.asObject(); + String value; + + if ((value = response.getString(responseErrorKeyName, null)) != null) + { + authError(value); + } + return response; + } + + @Override + protected boolean updateAuth(UUID uuid, String username, String accessToken) + { + return false; + } + + @Override + protected boolean updateServerID(UUID uuid, String serverID) + { + return false; + } +} \ No newline at end of file