[FEATURE] Extended Token Expire, auto refresh

This commit is contained in:
Gravita 2023-08-13 17:57:08 +07:00
parent 647c8dba5c
commit caebd6b5de
16 changed files with 158 additions and 49 deletions

View file

@ -41,7 +41,7 @@ public boolean allowGetSecureLevelInfo(Client client) {
@Override
public void onHardwareReport(HardwareReportResponse response, Client client) {
if (!enableHardwareFeature) {
response.sendResult(new HardwareReportRequestEvent(null));
response.sendResult(new HardwareReportRequestEvent());
return;
}
if (!client.isAuth || client.trustLevel == null || client.trustLevel.publicKey == null) {
@ -63,7 +63,7 @@ public void onHardwareReport(HardwareReportResponse response, Client client) {
throw new SecurityException("Your hardware banned");
}
client.trustLevel.hardwareInfo = hardware.getHardwareInfo();
response.sendResult(new HardwareReportRequestEvent(createHardwareToken(client.username, hardware)));
response.sendResult(new HardwareReportRequestEvent(createHardwareToken(client.username, hardware), SECONDS.toMillis(server.config.netty.security.hardwareTokenExpire)));
} else {
logger.error("AuthCoreProvider not supported hardware");
response.sendError("AuthCoreProvider not supported hardware");
@ -78,18 +78,18 @@ public VerifySecureLevelKeyRequestEvent onSuccessVerify(Client client) {
if (authSupportHardware != null) {
UserHardware hardware = authSupportHardware.getHardwareInfoByPublicKey(client.trustLevel.publicKey);
if (hardware == null) //HWID not found?
return new VerifySecureLevelKeyRequestEvent(true, false, createPublicKeyToken(client.username, client.trustLevel.publicKey));
return new VerifySecureLevelKeyRequestEvent(true, false, createPublicKeyToken(client.username, client.trustLevel.publicKey), SECONDS.toMillis(server.config.netty.security.publicKeyTokenExpire));
if (hardware.isBanned()) {
throw new SecurityException("Your hardware banned");
}
client.trustLevel.hardwareInfo = hardware.getHardwareInfo();
authSupportHardware.connectUserAndHardware(client.sessionObject, hardware);
return new VerifySecureLevelKeyRequestEvent(false, false, createPublicKeyToken(client.username, client.trustLevel.publicKey), createHardwareToken(client.username, hardware));
return new VerifySecureLevelKeyRequestEvent(false, false, createPublicKeyToken(client.username, client.trustLevel.publicKey), SECONDS.toMillis(server.config.netty.security.publicKeyTokenExpire));
} else {
logger.warn("AuthCoreProvider not supported hardware. HardwareInfo not checked!");
}
}
return new VerifySecureLevelKeyRequestEvent(false, false, createPublicKeyToken(client.username, client.trustLevel.publicKey));
return new VerifySecureLevelKeyRequestEvent(false, false, createPublicKeyToken(client.username, client.trustLevel.publicKey), SECONDS.toMillis(server.config.netty.security.publicKeyTokenExpire));
}
@Override

View file

@ -50,9 +50,9 @@ public void execute(ChannelHandlerContext ctx, Client client) {
service.sendObjectAndClose(ctx, new LauncherRequestEvent(true, server.config.netty.launcherURL));
if (Arrays.equals(bytes, hash) && checkSecure(secureHash, secureSalt)) {
client.checkSign = true;
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherURL, createLauncherExtendedToken()));
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherURL, createLauncherExtendedToken(), server.config.netty.security.launcherTokenExpire*1000));
} else {
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherURL, createLauncherExtendedToken()));
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherURL, createLauncherExtendedToken(), server.config.netty.security.launcherTokenExpire*1000));
}
} else if (launcher_type == 2) //EXE
{
@ -60,9 +60,9 @@ public void execute(ChannelHandlerContext ctx, Client client) {
if (hash == null) sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL));
if (Arrays.equals(bytes, hash) && checkSecure(secureHash, secureSalt)) {
client.checkSign = true;
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherEXEURL, createLauncherExtendedToken()));
sendResult(new LauncherRequestEvent(false, server.config.netty.launcherEXEURL, createLauncherExtendedToken(), server.config.netty.security.launcherTokenExpire*1000));
} else {
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL, createLauncherExtendedToken()));
sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL, createLauncherExtendedToken(), server.config.netty.security.launcherTokenExpire*1000));
}
} else sendError("Request launcher type error");
}

View file

@ -43,7 +43,7 @@ public void run(String[] args) {
}
if(accessToken != null) {
Request.setOAuth(authId, new AuthRequestEvent.OAuthRequestEvent(accessToken, refreshToken, expire));
Request.RequestRestoreReport report = Request.restore(true);
Request.RequestRestoreReport report = Request.restore(true, false);
permissions = report.userInfo.permissions;
username = report.userInfo.playerProfile.username;
uuid = report.userInfo.playerProfile.uuid.toString();

View file

@ -29,6 +29,7 @@ public class DebugMain {
public static String projectName = System.getProperty("launcherdebug.projectname", "Minecraft");
public static String unlockSecret = System.getProperty("launcherdebug.unlocksecret", "");
public static boolean offlineMode = Boolean.getBoolean("launcherdebug.offlinemode");
public static boolean autoRefresh = Boolean.getBoolean("launcherdebug.autorefresh");
public static String[] moduleClasses = System.getProperty("launcherdebug.modules", "").split(",");
public static String[] moduleFiles = System.getProperty("launcherdebug.modulefiles", "").split(",");
public static LauncherConfig.LauncherEnvironment environment = LauncherConfig.LauncherEnvironment.valueOf(System.getProperty("launcherdebug.env", "STD"));
@ -68,6 +69,9 @@ public static void main(String[] args) throws Throwable {
service = StdWebSocketService.initWebSockets(webSocketURL).get();
}
Request.setRequestService(service);
if(autoRefresh) {
Request.startAutoRefresh();
}
LogHelper.debug("Initialization LauncherEngine");
LauncherEngine instance = LauncherEngine.newInstance(false, ClientRuntimeProvider.class);
instance.start(args);

View file

@ -4,4 +4,6 @@ public interface ExtendedTokenRequestEvent {
String getExtendedTokenName();
String getExtendedToken();
long getExtendedTokenExpire();
}

View file

@ -1,19 +1,37 @@
package pro.gravit.launcher.events.request;
import pro.gravit.launcher.events.ExtendedTokenRequestEvent;
import pro.gravit.launcher.events.RequestEvent;
public class HardwareReportRequestEvent extends RequestEvent {
public class HardwareReportRequestEvent extends RequestEvent implements ExtendedTokenRequestEvent {
public String extendedToken;
public long expire;
public HardwareReportRequestEvent() {
}
public HardwareReportRequestEvent(String extendedToken) {
public HardwareReportRequestEvent(String extendedToken, long expire) {
this.extendedToken = extendedToken;
this.expire = expire;
}
@Override
public String getType() {
return "hardwareReport";
}
@Override
public String getExtendedTokenName() {
return "hardware";
}
@Override
public String getExtendedToken() {
return extendedToken;
}
@Override
public long getExtendedTokenExpire() {
return expire;
}
}

View file

@ -1,12 +1,13 @@
package pro.gravit.launcher.events.request;
import pro.gravit.launcher.LauncherNetworkAPI;
import pro.gravit.launcher.events.ExtendedTokenRequestEvent;
import pro.gravit.launcher.events.RequestEvent;
import java.util.UUID;
public class LauncherRequestEvent extends RequestEvent {
public class LauncherRequestEvent extends RequestEvent implements ExtendedTokenRequestEvent {
public static final String LAUNCHER_EXTENDED_TOKEN_NAME = "launcher";
@SuppressWarnings("unused")
private static final UUID uuid = UUID.fromString("d54cc12a-4f59-4f23-9b10-f527fdd2e38f");
@ -19,6 +20,7 @@ public class LauncherRequestEvent extends RequestEvent {
@LauncherNetworkAPI
public boolean needUpdate;
public String launcherExtendedToken;
public long launcherExtendedTokenExpire;
public LauncherRequestEvent(boolean needUpdate, String url) {
this.needUpdate = needUpdate;
@ -30,10 +32,11 @@ public LauncherRequestEvent(boolean b, byte[] digest) {
this.digest = digest;
}
public LauncherRequestEvent(boolean needUpdate, String url, String launcherExtendedToken) {
public LauncherRequestEvent(boolean needUpdate, String url, String launcherExtendedToken, long expire) {
this.url = url;
this.needUpdate = needUpdate;
this.launcherExtendedToken = launcherExtendedToken;
this.launcherExtendedTokenExpire = expire;
}
public LauncherRequestEvent(byte[] binary, byte[] digest) { //Legacy support constructor
@ -45,4 +48,19 @@ public LauncherRequestEvent(byte[] binary, byte[] digest) { //Legacy support con
public String getType() {
return "launcher";
}
@Override
public String getExtendedTokenName() {
return "launcher";
}
@Override
public String getExtendedToken() {
return launcherExtendedToken;
}
@Override
public long getExtendedTokenExpire() {
return launcherExtendedTokenExpire;
}
}

View file

@ -1,12 +1,13 @@
package pro.gravit.launcher.events.request;
import pro.gravit.launcher.events.ExtendedTokenRequestEvent;
import pro.gravit.launcher.events.RequestEvent;
public class VerifySecureLevelKeyRequestEvent extends RequestEvent {
public class VerifySecureLevelKeyRequestEvent extends RequestEvent implements ExtendedTokenRequestEvent {
public boolean needHardwareInfo;
public boolean onlyStatisticInfo;
public String extendedToken;
public String hardwareExtendedToken;
public long expire;
public VerifySecureLevelKeyRequestEvent() {
}
@ -15,21 +16,30 @@ public VerifySecureLevelKeyRequestEvent(boolean needHardwareInfo) {
this.needHardwareInfo = needHardwareInfo;
}
public VerifySecureLevelKeyRequestEvent(boolean needHardwareInfo, boolean onlyStatisticInfo, String extendedToken) {
public VerifySecureLevelKeyRequestEvent(boolean needHardwareInfo, boolean onlyStatisticInfo, String extendedToken, long expire) {
this.needHardwareInfo = needHardwareInfo;
this.onlyStatisticInfo = onlyStatisticInfo;
this.extendedToken = extendedToken;
}
public VerifySecureLevelKeyRequestEvent(boolean needHardwareInfo, boolean onlyStatisticInfo, String extendedToken, String hardwareExtendedToken) {
this.needHardwareInfo = needHardwareInfo;
this.onlyStatisticInfo = onlyStatisticInfo;
this.extendedToken = extendedToken;
this.hardwareExtendedToken = hardwareExtendedToken;
this.expire = expire;
}
@Override
public String getType() {
return "verifySecureLevelKey";
}
@Override
public String getExtendedTokenName() {
return "publicKey";
}
@Override
public String getExtendedToken() {
return extendedToken;
}
@Override
public long getExtendedTokenExpire() {
return expire;
}
}

View file

@ -12,32 +12,43 @@
import pro.gravit.utils.helper.LogHelper;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
public abstract class Request<R extends WebSocketEvent> implements WebSocketRequest {
private static final List<ExtendedTokenCallback> extendedTokenCallbacks = new ArrayList<>(4);
private static final List<BiConsumer<String, AuthRequestEvent.OAuthRequestEvent>> oauthChangeHandlers = new ArrayList<>(4);
@Deprecated
public static StdWebSocketService service;
private static RequestService requestService;
private static AuthRequestEvent.OAuthRequestEvent oauth;
private static Map<String, String> extendedTokens;
private static Map<String, ExtendedToken> extendedTokens;
private static String authId;
private static long tokenExpiredTime;
private static ScheduledExecutorService executorService;
@LauncherNetworkAPI
public final UUID requestUUID = UUID.randomUUID();
private transient final AtomicBoolean started = new AtomicBoolean(false);
public static void startAutoRefresh() {
executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleAtFixedRate(() -> {
try {
restore(false, true);
} catch (Exception e) {
LogHelper.error(e);
}
}, 60, 60, TimeUnit.SECONDS);
}
public static RequestService getRequestService() {
return requestService;
}
public static void setRequestService(RequestService service) {
requestService = service;
if (service instanceof StdWebSocketService) {
Request.service = (StdWebSocketService) service;
}
}
public static boolean isAvailable() {
@ -65,7 +76,7 @@ public static String getAuthId() {
return authId;
}
public static Map<String, String> getExtendedTokens() {
public static Map<String, ExtendedToken> getExtendedTokens() {
if (extendedTokens != null) {
return Collections.unmodifiableMap(extendedTokens);
} else {
@ -73,20 +84,32 @@ public static Map<String, String> getExtendedTokens() {
}
}
public static Map<String, String> getStringExtendedTokens() {
if(extendedTokens != null) {
Map<String, String> map = new HashMap<>();
for(Map.Entry<String, ExtendedToken> e : extendedTokens.entrySet()) {
map.put(e.getKey(), e.getValue().token);
}
return map;
} else {
return null;
}
}
public static void clearExtendedTokens() {
if (extendedTokens != null) {
extendedTokens.clear();
}
}
public static void addExtendedToken(String name, String token) {
public static void addExtendedToken(String name, ExtendedToken token) {
if (extendedTokens == null) {
extendedTokens = new HashMap<>();
}
extendedTokens.put(name, token);
}
public static void addAllExtendedToken(Map<String, String> map) {
public static void addAllExtendedToken(Map<String, ExtendedToken> map) {
if (extendedTokens == null) {
extendedTokens = new HashMap<>();
}
@ -118,15 +141,26 @@ public static String getRefreshToken() {
}
public static void reconnect() throws Exception {
service.open();
getRequestService().open();
restore();
}
public static RequestRestoreReport restore() throws Exception {
return restore(false);
return restore(false, false);
}
public static RequestRestoreReport restore(boolean needUserInfo) throws Exception {
private static Map<String, String> getExpiredExtendedTokens() {
Map<String, String> map = new HashMap<>();
for(Map.Entry<String, ExtendedToken> e : extendedTokens.entrySet()) {
if(e.getValue().expire != 0 && e.getValue().expire < System.currentTimeMillis()) {
map.put(e.getKey(), e.getValue().token);
}
}
return map;
}
public static synchronized RequestRestoreReport restore(boolean needUserInfo, boolean refreshOnly) throws Exception {
boolean refreshed = false;
RestoreRequest request;
if (oauth != null) {
@ -136,9 +170,12 @@ public static RequestRestoreReport restore(boolean needUserInfo) throws Exceptio
setOAuth(authId, event.oauth);
refreshed = true;
}
request = new RestoreRequest(authId, oauth.accessToken, extendedTokens, needUserInfo);
request = new RestoreRequest(authId, oauth.accessToken, refreshOnly ? getExpiredExtendedTokens() : getStringExtendedTokens(), needUserInfo);
} else {
request = new RestoreRequest(authId, null, extendedTokens, false);
request = new RestoreRequest(authId, null, refreshOnly ? getExpiredExtendedTokens() : getStringExtendedTokens(), false);
}
if(refreshOnly && (request.extended == null || request.extended.isEmpty())) {
return new RequestRestoreReport(refreshed, null, null);
}
RestoreRequestEvent event = request.request();
List<String> invalidTokens = null;
@ -147,10 +184,10 @@ public static RequestRestoreReport restore(boolean needUserInfo) throws Exceptio
Map<String, String> tokens = new HashMap<>();
for (ExtendedTokenCallback cb : extendedTokenCallbacks) {
for (String tokenName : event.invalidTokens) {
String newToken = cb.tryGetNewToken(tokenName);
ExtendedToken newToken = cb.tryGetNewToken(tokenName);
if (newToken != null) {
needRequest = true;
tokens.put(tokenName, newToken);
tokens.put(tokenName, newToken.token);
addExtendedToken(tokenName, newToken);
}
}
@ -164,7 +201,7 @@ public static RequestRestoreReport restore(boolean needUserInfo) throws Exceptio
}
invalidTokens = event.invalidTokens;
}
return new RequestRestoreReport(false, refreshed, invalidTokens, event.userInfo);
return new RequestRestoreReport(refreshed, invalidTokens, event.userInfo);
}
public static void requestError(String message) throws RequestException {
@ -214,21 +251,29 @@ protected R requestDo(RequestService service) throws Exception {
}
public interface ExtendedTokenCallback {
String tryGetNewToken(String name);
ExtendedToken tryGetNewToken(String name);
}
public static class RequestRestoreReport {
public final boolean legacySession;
public final boolean refreshed;
public final List<String> invalidExtendedTokens;
public final CurrentUserRequestEvent.UserInfo userInfo;
public RequestRestoreReport(boolean legacySession, boolean refreshed, List<String> invalidExtendedTokens, CurrentUserRequestEvent.UserInfo userInfo) {
this.legacySession = legacySession;
public RequestRestoreReport(boolean refreshed, List<String> invalidExtendedTokens, CurrentUserRequestEvent.UserInfo userInfo) {
this.refreshed = refreshed;
this.invalidExtendedTokens = invalidExtendedTokens;
this.userInfo = userInfo;
}
}
public static class ExtendedToken {
public final String token;
public final long expire;
public ExtendedToken(String token, long expire) {
this.token = token;
this.expire = expire;
}
}
}

View file

@ -6,6 +6,7 @@
public interface RequestService {
<T extends WebSocketEvent> CompletableFuture<T> request(Request<T> request) throws IOException;
void open() throws Exception;
void registerEventHandler(EventHandler handler);

View file

@ -44,6 +44,11 @@ public <T extends WebSocketEvent> CompletableFuture<T> request(Request<T> reques
return future;
}
@Override
public void open() {
}
@Override
public void registerEventHandler(EventHandler handler) {
eventHandlers.add(handler);

View file

@ -25,6 +25,11 @@ public <T extends WebSocketEvent> CompletableFuture<T> request(Request<T> reques
return future;
}
@Override
public void open() {
}
@Override
public void registerEventHandler(EventHandler handler) {

View file

@ -26,7 +26,7 @@ public <T extends WebSocketEvent> boolean eventHandle(T event) {
ExtendedTokenRequestEvent event1 = (ExtendedTokenRequestEvent) event;
String token = event1.getExtendedToken();
if (token != null) {
Request.addExtendedToken(event1.getExtendedTokenName(), token);
Request.addExtendedToken(event1.getExtendedTokenName(), new Request.ExtendedToken(event1.getExtendedToken(), event1.getExtendedTokenExpire()));
}
} else if (event instanceof NotificationEvent) {
NotificationEvent n = (NotificationEvent) event;

View file

@ -8,6 +8,7 @@
import pro.gravit.launcher.profiles.PlayerProfile;
import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
import pro.gravit.launcher.profiles.optional.actions.OptionalActionClientArgs;
import pro.gravit.launcher.request.Request;
import pro.gravit.utils.Version;
import java.util.*;
@ -53,7 +54,7 @@ public class ClientParams {
public long oauthExpiredTime;
public Map<String, String> extendedTokens;
public Map<String, Request.ExtendedToken> extendedTokens;
public boolean offlineMode;

View file

@ -231,7 +231,7 @@ public static final class Config {
public String authId;
public AuthRequestEvent.OAuthRequestEvent oauth;
public long oauthExpireTime;
public Map<String, String> extendedTokens;
public Map<String, Request.ExtendedToken> extendedTokens;
public LauncherConfig.LauncherEnvironment env;
public ModuleConf moduleConf = new ModuleConf();

View file

@ -75,7 +75,7 @@ public void run() throws Exception {
}
System.out.println("Print server token:");
String checkServerToken = commands.commandHandler.readLine();
wrapper.config.extendedTokens.put("checkServer", checkServerToken);
wrapper.config.extendedTokens.put("checkServer", new Request.ExtendedToken(checkServerToken, 0));
wrapper.updateLauncherConfig();
try {
wrapper.restore();