[FEATURE] AuthCoreProvider: OAuth Support Part 4

This commit is contained in:
Gravita 2021-05-23 18:13:30 +07:00
parent ea3310b738
commit b7a7156408
7 changed files with 190 additions and 58 deletions

View file

@ -54,7 +54,6 @@ public void execute(ChannelHandlerContext ctx, Client client) {
support.clearSessionsByUser(client.getUser()); support.clearSessionsByUser(client.getUser());
} }
} }
sendResult(new ExitRequestEvent(ExitRequestEvent.ExitReason.CLIENT));
} else { } else {
if (client.session == null && exitAll) { if (client.session == null && exitAll) {
sendError("Session invalid"); sendError("Session invalid");
@ -80,8 +79,8 @@ public void execute(ChannelHandlerContext ctx, Client client) {
exit(server, webSocketFrameHandler, channel, ExitRequestEvent.ExitReason.SERVER); exit(server, webSocketFrameHandler, channel, ExitRequestEvent.ExitReason.SERVER);
})); }));
} }
sendResult(new ExitRequestEvent(ExitRequestEvent.ExitReason.CLIENT));
} }
sendResult(new ExitRequestEvent(ExitRequestEvent.ExitReason.CLIENT));
} else { } else {
service.forEachActiveChannels(((channel, webSocketFrameHandler) -> { service.forEachActiveChannels(((channel, webSocketFrameHandler) -> {
Client client1 = webSocketFrameHandler.getClient(); Client client1 = webSocketFrameHandler.getClient();

View file

@ -187,17 +187,10 @@ public void start(String... args) throws Throwable {
{ {
LogHelper.debug("WebSocket connect closed. Try reconnect"); LogHelper.debug("WebSocket connect closed. Try reconnect");
try { try {
Request.service.open(); Request.reconnect();
LogHelper.debug("Connect to %s", Launcher.getConfig().address);
} catch (Exception e) {
LogHelper.error(e);
throw new RequestException(String.format("Connect error: %s", e.getMessage() != null ? e.getMessage() : "null"));
}
try {
RestoreSessionRequest request1 = new RestoreSessionRequest(Request.getSession());
request1.request();
} catch (Exception e) { } catch (Exception e) {
LogHelper.error(e); LogHelper.error(e);
throw new RequestException("Connection failed", e);
} }
}; };
} }

View file

@ -91,7 +91,18 @@ public static void main(String[] args) throws Throwable {
Launcher.profile = profile; Launcher.profile = profile;
AuthService.profile = profile; AuthService.profile = profile;
LauncherEngine.clientParams = params; LauncherEngine.clientParams = params;
Request.setSession(params.session); if(params.session != null) {
Request.setSession(params.session);
} else if(params.oauth != null) {
if(params.oauthExpiredTime != 0) {
Request.setOAuth(params.authId, params.oauth, params.oauthExpiredTime);
} else {
Request.setOAuth(params.authId, params.oauth);
}
if(params.extendedTokens != null) {
Request.addAllExtendedToken(params.extendedTokens);
}
}
checkJVMBitsAndVersion(params.profile.getMinJavaVersion(), params.profile.getRecommendJavaVersion(), params.profile.getMaxJavaVersion(), params.profile.isWarnMissJavaVersion()); checkJVMBitsAndVersion(params.profile.getMinJavaVersion(), params.profile.getRecommendJavaVersion(), params.profile.getMaxJavaVersion(), params.profile.isWarnMissJavaVersion());
LauncherEngine.modulesManager.invokeEvent(new ClientProcessInitPhase(engine, params)); LauncherEngine.modulesManager.invokeEvent(new ClientProcessInitPhase(engine, params));
@ -110,23 +121,15 @@ public static void main(String[] args) throws Throwable {
// Start client with WatchService monitoring // Start client with WatchService monitoring
boolean digest = !profile.isUpdateFastCheck(); boolean digest = !profile.isUpdateFastCheck();
LogHelper.debug("Restore sessions"); LogHelper.debug("Restore sessions");
RestoreSessionRequest request = new RestoreSessionRequest(Request.getSession()); Request.restore();
request.request();
Request.service.reconnectCallback = () -> Request.service.reconnectCallback = () ->
{ {
LogHelper.debug("WebSocket connect closed. Try reconnect"); LogHelper.debug("WebSocket connect closed. Try reconnect");
try { try {
Request.service.open(); Request.reconnect();
LogHelper.debug("Connect to %s", Launcher.getConfig().address);
} catch (Exception e) {
LogHelper.error(e);
throw new RequestException(String.format("Connect error: %s", e.getMessage() != null ? e.getMessage() : "null"));
}
try {
RestoreSessionRequest request1 = new RestoreSessionRequest(Request.getSession());
request1.request();
} catch (Exception e) { } catch (Exception e) {
LogHelper.error(e); LogHelper.error(e);
throw new RequestException("Connection failed", e);
} }
}; };
if (params.profile.getClassLoaderConfig() == ClientProfile.ClassLoaderConfig.LAUNCHER) { if (params.profile.getClassLoaderConfig() == ClientProfile.ClassLoaderConfig.LAUNCHER) {

View file

@ -8,6 +8,7 @@
import pro.gravit.launcher.client.events.client.ClientProcessBuilderLaunchedEvent; import pro.gravit.launcher.client.events.client.ClientProcessBuilderLaunchedEvent;
import pro.gravit.launcher.client.events.client.ClientProcessBuilderParamsWrittedEvent; import pro.gravit.launcher.client.events.client.ClientProcessBuilderParamsWrittedEvent;
import pro.gravit.launcher.client.events.client.ClientProcessBuilderPreLaunchEvent; import pro.gravit.launcher.client.events.client.ClientProcessBuilderPreLaunchEvent;
import pro.gravit.launcher.events.request.AuthRequestEvent;
import pro.gravit.launcher.hasher.HashedDir; import pro.gravit.launcher.hasher.HashedDir;
import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launcher.profiles.PlayerProfile; import pro.gravit.launcher.profiles.PlayerProfile;
@ -115,7 +116,13 @@ private void applyClientProfile() {
if (params.ram > 0) { if (params.ram > 0) {
this.jvmArgs.add("-Xmx" + params.ram + 'M'); this.jvmArgs.add("-Xmx" + params.ram + 'M');
} }
this.params.session = Request.getSession(); this.params.oauth = Request.getOAuth();
if(this.params.oauth == null) {
this.params.session = Request.getSession();
} else {
this.params.oauthExpiredTime = Request.getTokenExpiredTime();
this.params.extendedTokens = Request.getExtendedTokens();
}
if(this.params.profile.getRuntimeInClientConfig() != ClientProfile.RuntimeInClientConfig.NONE) { if(this.params.profile.getRuntimeInClientConfig() != ClientProfile.RuntimeInClientConfig.NONE) {
jvmModules.add("javafx.base"); jvmModules.add("javafx.base");
@ -258,6 +265,14 @@ public static class ClientParams {
public UUID session; public UUID session;
public AuthRequestEvent.OAuthRequestEvent oauth;
public String authId;
public long oauthExpiredTime;
public Map<String, String> extendedTokens;
public transient HashedDir assetHDir; public transient HashedDir assetHDir;
public transient HashedDir clientHDir; public transient HashedDir clientHDir;

View file

@ -2,15 +2,28 @@
import pro.gravit.launcher.Launcher; import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.LauncherNetworkAPI; import pro.gravit.launcher.LauncherNetworkAPI;
import pro.gravit.launcher.events.request.AuthRequestEvent;
import pro.gravit.launcher.events.request.RefreshTokenRequestEvent;
import pro.gravit.launcher.events.request.RestoreRequestEvent;
import pro.gravit.launcher.request.auth.RefreshTokenRequest;
import pro.gravit.launcher.request.auth.RestoreRequest;
import pro.gravit.launcher.request.auth.RestoreSessionRequest;
import pro.gravit.launcher.request.websockets.StdWebSocketService; import pro.gravit.launcher.request.websockets.StdWebSocketService;
import pro.gravit.launcher.request.websockets.WebSocketRequest; import pro.gravit.launcher.request.websockets.WebSocketRequest;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
public abstract class Request<R extends WebSocketEvent> implements WebSocketRequest { public abstract class Request<R extends WebSocketEvent> implements WebSocketRequest {
public static StdWebSocketService service; public static StdWebSocketService service;
private static UUID session = UUID.randomUUID(); private static UUID session = UUID.randomUUID();
private static AuthRequestEvent.OAuthRequestEvent oauth;
private static Map<String, String> extendedTokens;
private static String authId;
private static long tokenExpiredTime;
@LauncherNetworkAPI @LauncherNetworkAPI
public final UUID requestUUID = UUID.randomUUID(); public final UUID requestUUID = UUID.randomUUID();
private transient final AtomicBoolean started = new AtomicBoolean(false); private transient final AtomicBoolean started = new AtomicBoolean(false);
@ -23,6 +36,93 @@ public static void setSession(UUID session) {
Request.session = session; Request.session = session;
} }
public static void setOAuth(String authId, AuthRequestEvent.OAuthRequestEvent event) {
oauth = event;
Request.authId = authId;
if(oauth != null && oauth.expire != 0) {
tokenExpiredTime = System.currentTimeMillis() + oauth.expire;
} else {
tokenExpiredTime = 0;
}
}
public static AuthRequestEvent.OAuthRequestEvent getOAuth() {
return oauth;
}
public static Map<String, String> getExtendedTokens() {
if(extendedTokens != null) {
return Collections.unmodifiableMap(extendedTokens);
} else {
return null;
}
}
public static void clearExtendedTokens() {
if(extendedTokens != null) {
extendedTokens.clear();
}
}
public static void addExtendedToken(String name, String token) {
if(extendedTokens == null) {
extendedTokens = new HashMap<>();
}
extendedTokens.put(name, token);
}
public static void addAllExtendedToken(Map<String, String> map) {
if(extendedTokens == null) {
extendedTokens = new HashMap<>();
}
extendedTokens.putAll(map);
}
public static void setOAuth(String authId, AuthRequestEvent.OAuthRequestEvent event, long tokenExpiredTime) {
oauth = event;
Request.authId = authId;
Request.tokenExpiredTime = tokenExpiredTime;
}
public static boolean isTokenExpired() {
if(oauth == null) return true;
if(tokenExpiredTime == 0) return false;
return System.currentTimeMillis() > tokenExpiredTime;
}
public static long getTokenExpiredTime() {
return tokenExpiredTime;
}
public static String getAccessToken() {
return oauth == null ? null : oauth.accessToken;
}
public static String getRefreshToken() {
return oauth == null ? null : oauth.refreshToken;
}
public static void reconnect() throws Exception {
service.open();
restore();
}
public static void restore() throws Exception {
if(session != null) {
RestoreSessionRequest request = new RestoreSessionRequest(session);
request.request();
}
else if(oauth != null) {
if(isTokenExpired() || oauth.accessToken == null) {
RefreshTokenRequest request = new RefreshTokenRequest(authId, oauth.refreshToken);
RefreshTokenRequestEvent event = request.request();
setOAuth(authId, event.oauth);
}
RestoreRequest request = new RestoreRequest(authId, oauth.accessToken, extendedTokens, false);
request.request();
}
}
public static void requestError(String message) throws RequestException { public static void requestError(String message) throws RequestException {
throw new RequestException(message); throw new RequestException(message);
} }

View file

@ -35,12 +35,12 @@
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.UUID;
public class ServerWrapper extends JsonConfigurable<ServerWrapper.Config> { public class ServerWrapper extends JsonConfigurable<ServerWrapper.Config> {
public static final Path modulesDir = Paths.get(System.getProperty("serverwrapper.modulesDir", "modules")); public static final Path modulesDir = Paths.get(System.getProperty("serverwrapper.modulesDir", "modules"));
public static final Path modulesConfigDir = Paths.get(System.getProperty("serverwrapper.modulesConfigDir", "modules-config")); public static final Path modulesConfigDir = Paths.get(System.getProperty("serverwrapper.modulesConfigDir", "modules-config"));
public static final Path configFile = Paths.get(System.getProperty("serverwrapper.configFile", "ServerWrapperConfig.json")); public static final Path configFile = Paths.get(System.getProperty("serverwrapper.configFile", "ServerWrapperConfig.json"));
public static final Path publicKeyFile = Paths.get(System.getProperty("serverwrapper.publicKeyFile", "public.key"));
public static final boolean disableSetup = Boolean.parseBoolean(System.getProperty("serverwrapper.disableSetup", "false")); public static final boolean disableSetup = Boolean.parseBoolean(System.getProperty("serverwrapper.disableSetup", "false"));
public static ServerWrapperModulesManager modulesManager; public static ServerWrapperModulesManager modulesManager;
public static ServerWrapper wrapper; public static ServerWrapper wrapper;
@ -76,8 +76,28 @@ public boolean auth() {
Launcher.getConfig(); Launcher.getConfig();
AuthRequest request = new AuthRequest(config.login, config.password, config.auth_id, AuthRequest.ConnectTypes.API); AuthRequest request = new AuthRequest(config.login, config.password, config.auth_id, AuthRequest.ConnectTypes.API);
AuthRequestEvent authResult = request.request(); AuthRequestEvent authResult = request.request();
if(config.saveSession) {
if(authResult.oauth != null) {
Request.setOAuth(config.auth_id, authResult.oauth);
config.oauth = authResult.oauth;
config.oauthExpireTime = Request.getTokenExpiredTime();
} else {
Request.setSession(authResult.session);
}
saveConfig();
}
permissions = authResult.permissions; permissions = authResult.permissions;
playerProfile = authResult.playerProfile; playerProfile = authResult.playerProfile;
return true;
} catch (Throwable e) {
LogHelper.error(e);
if (config.stopOnError) System.exit(-1);
return false;
}
}
public ProfilesRequestEvent getProfiles() {
try {
ProfilesRequestEvent result = new ProfilesRequest().request(); ProfilesRequestEvent result = new ProfilesRequest().request();
for (ClientProfile p : result.profiles) { for (ClientProfile p : result.profiles) {
LogHelper.debug("Get profile: %s", p.getTitle()); LogHelper.debug("Get profile: %s", p.getTitle());
@ -97,32 +117,12 @@ public boolean auth() {
if (profile == null) { if (profile == null) {
LogHelper.warning("Not connected to ServerProfile. May be serverName incorrect?"); LogHelper.warning("Not connected to ServerProfile. May be serverName incorrect?");
} }
return true; return result;
} catch (Throwable e) { } catch (Throwable e) {
LogHelper.error(e); LogHelper.error(e);
if (config.stopOnError) System.exit(-1); if (config.stopOnError) System.exit(-1);
return false; return null;
} }
}
public boolean loopAuth(int count, int sleeptime) {
if (count == 0) {
while (true) {
if (auth()) return true;
}
}
for (int i = 0; i < count; ++i) {
if (auth()) return true;
try {
Thread.sleep(sleeptime);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
LogHelper.error(e);
return false;
}
}
return false;
} }
public void run(String... args) throws Throwable { public void run(String... args) throws Throwable {
@ -144,9 +144,24 @@ public void run(String... args) throws Throwable {
if (config.env != null) Launcher.applyLauncherEnv(config.env); if (config.env != null) Launcher.applyLauncherEnv(config.env);
else Launcher.applyLauncherEnv(LauncherConfig.LauncherEnvironment.STD); else Launcher.applyLauncherEnv(LauncherConfig.LauncherEnvironment.STD);
if (config.logFile != null) LogHelper.addOutput(IOHelper.newWriter(Paths.get(config.logFile), true)); if (config.logFile != null) LogHelper.addOutput(IOHelper.newWriter(Paths.get(config.logFile), true));
if (config.syncAuth) auth(); {
else if(config.saveSession) {
CommonHelper.newThread("Server Auth Thread", true, () -> loopAuth(config.reconnectCount, config.reconnectSleep)); if(config.oauth != null) {
Request.setOAuth(config.auth_id, config.oauth, config.oauthExpireTime);
} else {
Request.setSession(config.session);
}
try {
Request.restore();
} catch (Exception e) {
LogHelper.error(e);
auth();
}
} else {
auth();
}
getProfiles();
}
modulesManager.invokeEvent(new ServerWrapperInitPhase(this)); modulesManager.invokeEvent(new ServerWrapperInitPhase(this));
String classname = (config.mainclass == null || config.mainclass.isEmpty()) ? args[0] : config.mainclass; String classname = (config.mainclass == null || config.mainclass.isEmpty()) ? args[0] : config.mainclass;
if (classname.length() == 0) { if (classname.length() == 0) {
@ -187,14 +202,16 @@ public void run(String... args) throws Throwable {
Request.service.reconnectCallback = () -> Request.service.reconnectCallback = () ->
{ {
LogHelper.debug("WebSocket connect closed. Try reconnect"); LogHelper.debug("WebSocket connect closed. Try reconnect");
try { if(config.saveSession) {
Request.service.open(); try {
LogHelper.debug("Connect to %s", config.address); Request.restore();
} catch (Exception e) { } catch (Exception e) {
LogHelper.error(e); auth();
throw new RequestException(String.format("Connect error: %s", e.getMessage() != null ? e.getMessage() : "null")); }
} else {
auth();
} }
auth(); getProfiles();
}; };
LogHelper.info("ServerWrapper: Project %s, LaunchServer address: %s. Title: %s", config.projectname, config.address, Launcher.profile != null ? Launcher.profile.getTitle() : "unknown"); LogHelper.info("ServerWrapper: Project %s, LaunchServer address: %s. Title: %s", config.projectname, config.address, Launcher.profile != null ? Launcher.profile.getTitle() : "unknown");
LogHelper.info("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name); LogHelper.info("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name);
@ -239,6 +256,7 @@ public Config getDefaultConfig() {
newConfig.mainclass = ""; newConfig.mainclass = "";
newConfig.syncAuth = true; newConfig.syncAuth = true;
newConfig.stopOnError = true; newConfig.stopOnError = true;
newConfig.saveSession = true;
newConfig.reconnectCount = 10; newConfig.reconnectCount = 10;
newConfig.reconnectSleep = 1000; newConfig.reconnectSleep = 1000;
newConfig.address = "ws://localhost:9274/api"; newConfig.address = "ws://localhost:9274/api";
@ -266,6 +284,10 @@ public static final class Config {
public String[] args; public String[] args;
public String password; public String password;
public String auth_id = ""; public String auth_id = "";
public boolean saveSession;
public AuthRequestEvent.OAuthRequestEvent oauth;
public long oauthExpireTime;
public UUID session;
public LauncherConfig.LauncherEnvironment env; public LauncherConfig.LauncherEnvironment env;
} }

View file

@ -67,7 +67,7 @@ public void run() throws IOException {
wrapper.config.password = password; wrapper.config.password = password;
wrapper.config.stopOnError = false; wrapper.config.stopOnError = false;
wrapper.updateLauncherConfig(); wrapper.updateLauncherConfig();
if (wrapper.auth()) { if (wrapper.auth() && wrapper.getProfiles() != null) {
break; break;
} else { } else {
LogHelper.error("Auth error. Recheck account params"); LogHelper.error("Auth error. Recheck account params");