diff --git a/LaunchServer/build.gradle b/LaunchServer/build.gradle index 47d6de15..67a0704f 100644 --- a/LaunchServer/build.gradle +++ b/LaunchServer/build.gradle @@ -86,6 +86,9 @@ pack project(':LauncherAPI') bundle group: 'com.guardsquare', name: 'proguard-base', version: rootProject['verProguard'] bundle group: 'org.apache.logging.log4j', name: 'log4j-core', version: rootProject['verLog4j'] bundle group: 'org.apache.logging.log4j', name: 'log4j-slf4j-impl', version: rootProject['verLog4j'] + bundle group: 'io.jsonwebtoken', name: 'jjwt-api', version: rootProject['verJwt'] + bundle group: 'io.jsonwebtoken', name: 'jjwt-impl', version: rootProject['verJwt'] + bundle group: 'io.jsonwebtoken', name: 'jjwt-gson', version: rootProject['verJwt'] testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter', version: rootProject['verJunit'] hikari 'io.micrometer:micrometer-core:1.5.10' diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java index c2388814..3cfc6ead 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java @@ -20,6 +20,7 @@ import pro.gravit.launchserver.modules.events.*; import pro.gravit.launchserver.modules.impl.LaunchServerModulesManager; import pro.gravit.launchserver.socket.handlers.NettyServerSocketHandler; +import pro.gravit.launchserver.socket.response.auth.RestoreResponse; import pro.gravit.utils.command.Command; import pro.gravit.utils.command.CommandHandler; import pro.gravit.utils.command.SubCommand; @@ -171,6 +172,7 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La pingServerManager = new PingServerManager(this); featuresManager = new FeaturesManager(this); authManager = new AuthManager(this); + RestoreResponse.registerProviders(this); //Generate or set new Certificate API certificateManager.orgName = config.projectName; config.init(ReloadType.FULL); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/ClientsCommand.java b/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/ClientsCommand.java index 62efdfc2..695c88bf 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/ClientsCommand.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/ClientsCommand.java @@ -45,6 +45,7 @@ public void invoke(String... args) { else { logger.info("Client name {} | ip {} | connectUUID {}", client.username == null ? "null" : client.username, ip, frameHandler.getConnectUUID()); logger.info("userUUID: {} | session {}", client.uuid == null ? "null" : client.uuid.toString(), client.session == null ? "null" : client.session); + logger.info("OAuth {} | session {}", client.useOAuth, client.sessionObject == null ? "null" : client.sessionObject); logger.info("Data: checkSign {} | auth_id {}", client.checkSign ? "true" : "false", client.auth_id); if (client.trustLevel != null) { diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/WebSocketService.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/WebSocketService.java index 4c616421..eb44da8c 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/WebSocketService.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/WebSocketService.java @@ -166,7 +166,7 @@ void process(ChannelHandlerContext ctx, WebSocketServerResponse response, Client try { response.execute(ctx, client); } catch (Exception e) { - logger.error(e); + logger.error("WebSocket request processing failed", e); RequestEvent event; if (server.config.netty.sendExceptionEnabled) { event = new ExceptionEvent(e); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/RefreshTokenResponse.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/RefreshTokenResponse.java index 79c27ace..5d3d97aa 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/RefreshTokenResponse.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/RefreshTokenResponse.java @@ -25,13 +25,13 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception { } AuthProviderPair pair; if(!client.isAuth) { - if(authId == null || !client.useOAuth) { + if(authId == null) { pair = server.config.getAuthProviderPair(); } else { - pair = client.auth; + pair = server.config.getAuthProviderPair(authId); } } else { - pair = server.config.getAuthProviderPair(authId); + pair = client.auth; } if(pair == null || !pair.isUseCore()) { sendError("Invalid request"); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/RestoreResponse.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/RestoreResponse.java index caea76b4..400c7a3c 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/RestoreResponse.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/RestoreResponse.java @@ -2,23 +2,35 @@ import io.netty.channel.ChannelHandlerContext; import pro.gravit.launcher.events.request.AuthRequestEvent; +import pro.gravit.launcher.events.request.LauncherRequestEvent; import pro.gravit.launcher.events.request.RestoreRequestEvent; +import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.auth.AuthProviderPair; import pro.gravit.launchserver.auth.core.AuthCoreProvider; import pro.gravit.launchserver.auth.core.User; import pro.gravit.launchserver.auth.core.UserSession; import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.response.SimpleResponse; +import pro.gravit.launchserver.socket.response.update.LauncherResponse; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; public class RestoreResponse extends SimpleResponse { @FunctionalInterface public interface ExtendedTokenProvider { - void accept(Client client, AuthProviderPair pair, String extendedToken); + boolean accept(Client client, AuthProviderPair pair, String extendedToken); } public static Map providers = new HashMap<>(); + private static boolean registeredProviders = false; + public static void registerProviders(LaunchServer server) { + if(!registeredProviders) { + providers.put(LauncherRequestEvent.LAUNCHER_EXTENDED_TOKEN_NAME, new LauncherResponse.LauncherTokenVerifier(server)); + registeredProviders = true; + } + } public String authId; public String accessToken; public Map extended; @@ -37,16 +49,16 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception { } AuthProviderPair pair; if(!client.isAuth) { - if(authId == null || !client.useOAuth) { + if(authId == null) { pair = server.config.getAuthProviderPair(); } else { - pair = client.auth; + pair = server.config.getAuthProviderPair(authId); } } else { - pair = server.config.getAuthProviderPair(authId); + pair = client.auth; } if(pair == null || !pair.isUseCore()) { - sendError("Invalid request"); + sendError("Invalid authId"); return; } if(accessToken != null) { @@ -66,17 +78,20 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception { client.sessionObject = session; server.authManager.internalAuth(client, client.type == null ? AuthResponse.ConnectTypes.API : client.type, pair, user.getUsername(), user.getUUID(), user.getPermissions(), true); } + List invalidTokens = new ArrayList<>(4); if(extended != null) { extended.forEach((k,v) -> { ExtendedTokenProvider provider = providers.get(k); if(provider == null) return; - provider.accept(client, pair, v); + if(!provider.accept(client, pair, v)) { + invalidTokens.add(k); + } }); } if(needUserInfo && client.isAuth) { - sendResult(new RestoreRequestEvent(CurrentUserResponse.collectUserInfoFromClient(client))); + sendResult(new RestoreRequestEvent(CurrentUserResponse.collectUserInfoFromClient(client), invalidTokens)); } else { - sendResult(new RestoreRequestEvent()); + sendResult(new RestoreRequestEvent(invalidTokens)); } } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/profile/BatchProfileByUsername.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/profile/BatchProfileByUsername.java index 007a1cfa..f2334526 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/profile/BatchProfileByUsername.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/profile/BatchProfileByUsername.java @@ -4,6 +4,7 @@ import pro.gravit.launcher.events.request.BatchProfileByUsernameRequestEvent; import pro.gravit.launcher.profiles.PlayerProfile; import pro.gravit.launchserver.auth.AuthProviderPair; +import pro.gravit.launchserver.auth.core.User; import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.response.SimpleResponse; @@ -31,7 +32,13 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception { if (pair == null) { pair = server.config.getAuthProviderPair(); } - uuid = pair.handler.usernameToUUID(list[i].username); + if(pair.isUseCore()) { + User user = pair.core.getUserByUsername(list[i].username); + if(user == null) uuid = null; + else uuid = user.getUUID(); + } else { + uuid = pair.handler.usernameToUUID(list[i].username); + } result.playerProfiles[i] = ProfileByUUIDResponse.getProfile(uuid, list[i].username, list[i].client, pair.textureProvider); } sendResult(result); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/profile/ProfileByUUIDResponse.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/profile/ProfileByUUIDResponse.java index 3a9c476b..fc123551 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/profile/ProfileByUUIDResponse.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/profile/ProfileByUUIDResponse.java @@ -5,6 +5,7 @@ import pro.gravit.launcher.profiles.PlayerProfile; import pro.gravit.launcher.profiles.Texture; import pro.gravit.launchserver.auth.AuthProviderPair; +import pro.gravit.launchserver.auth.core.User; import pro.gravit.launchserver.auth.texture.TextureProvider; import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.response.SimpleResponse; @@ -55,10 +56,19 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception { sendError("ProfileByUUIDResponse: AuthProviderPair is null"); return; } - username = pair.handler.uuidToUsername(uuid); - if (username == null) { - sendError(String.format("ProfileByUUIDResponse: User with uuid %s not found or AuthProvider#uuidToUsername returned null", uuid)); - return; + if(pair.isUseCore()) { + User user = pair.core.getUserByUUID(uuid); + if(user == null) { + sendError("User not found"); + return; + } + else username = user.getUsername(); + } else { + username = pair.handler.uuidToUsername(uuid); + if (username == null) { + sendError(String.format("ProfileByUUIDResponse: User with uuid %s not found or AuthProvider#uuidToUsername returned null", uuid)); + return; + } } sendResult(new ProfileByUUIDRequestEvent(getProfile(uuid, username, this.client, pair.textureProvider))); } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/profile/ProfileByUsername.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/profile/ProfileByUsername.java index 506b0c92..832b5b84 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/profile/ProfileByUsername.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/profile/ProfileByUsername.java @@ -3,6 +3,7 @@ import io.netty.channel.ChannelHandlerContext; import pro.gravit.launcher.events.request.ProfileByUsernameRequestEvent; import pro.gravit.launchserver.auth.AuthProviderPair; +import pro.gravit.launchserver.auth.core.User; import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.response.SimpleResponse; @@ -22,7 +23,13 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception { UUID uuid; AuthProviderPair pair = client.auth; if (pair == null) pair = server.config.getAuthProviderPair(); - uuid = pair.handler.usernameToUUID(username); + if(pair.isUseCore()) { + User user = pair.core.getUserByUsername(username); + if(user == null) uuid = null; + else uuid = user.getUUID(); + } else { + uuid = pair.handler.usernameToUUID(username); + } if (uuid == null) { sendError("User not found"); return; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/update/LauncherResponse.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/update/LauncherResponse.java index c018d78f..d97dd1f9 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/update/LauncherResponse.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/update/LauncherResponse.java @@ -1,14 +1,24 @@ package pro.gravit.launchserver.socket.response.update; +import io.jsonwebtoken.*; import io.netty.channel.ChannelHandlerContext; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import pro.gravit.launcher.events.request.LauncherRequestEvent; +import pro.gravit.launchserver.LaunchServer; +import pro.gravit.launchserver.auth.AuthProviderPair; import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.response.SimpleResponse; +import pro.gravit.launchserver.socket.response.auth.AuthResponse; +import pro.gravit.launchserver.socket.response.auth.RestoreResponse; import pro.gravit.utils.Version; import pro.gravit.utils.helper.SecurityHelper; +import java.time.LocalDateTime; +import java.time.ZoneOffset; import java.util.Arrays; import java.util.Base64; +import java.util.Date; public class LauncherResponse extends SimpleResponse { public Version version; @@ -38,9 +48,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)); + sendResult(new LauncherRequestEvent(false, server.config.netty.launcherURL, createLauncherExtendedToken())); } else { - sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherURL)); + sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherURL, createLauncherExtendedToken())); } } else if (launcher_type == 2) //EXE { @@ -48,13 +58,50 @@ 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)); + sendResult(new LauncherRequestEvent(false, server.config.netty.launcherEXEURL, createLauncherExtendedToken())); } else { - sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL)); + sendResultAndClose(new LauncherRequestEvent(true, server.config.netty.launcherEXEURL, createLauncherExtendedToken())); } } else sendError("Request launcher type error"); } + public String createLauncherExtendedToken() { + return Jwts.builder() + .setIssuer("LaunchServer") + .claim("checkSign", true) + .setExpiration(Date.from(LocalDateTime.now().plusHours(8).toInstant(ZoneOffset.UTC))) + .signWith(server.keyAgreementManager.ecdsaPrivateKey, SignatureAlgorithm.ES256) + .compact(); + } + + public static class LauncherTokenVerifier implements RestoreResponse.ExtendedTokenProvider { + private final LaunchServer server; + private final JwtParser parser; + private final Logger logger = LogManager.getLogger(); + + public LauncherTokenVerifier(LaunchServer server) { + this.server = server; + parser = Jwts.parserBuilder() + .setSigningKey(server.keyAgreementManager.ecdsaPublicKey) + .requireIssuer("LaunchServer") + .build(); + } + + @Override + public boolean accept(Client client, AuthProviderPair pair, String extendedToken) { + try { + var jwt = parser.parseClaimsJws(extendedToken); + client.checkSign = jwt.getBody().get("checkSign", Boolean.class); + client.type = AuthResponse.ConnectTypes.CLIENT; + return true; + } catch (Exception e) { + logger.error("JWT check failed", e); + return false; + } + + } + } + private boolean checkSecure(String hash, String salt) { if (hash == null || salt == null) return false; byte[] normal_hash = SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA256, diff --git a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java index 8c06feaf..9c1d438b 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java +++ b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java @@ -91,9 +91,8 @@ public static void main(String[] args) throws Throwable { Launcher.profile = profile; AuthService.profile = profile; LauncherEngine.clientParams = params; - if(params.session != null) { - Request.setSession(params.session); - } else if(params.oauth != null) { + if(params.oauth != null) { + LogHelper.info("Using OAuth"); if(params.oauthExpiredTime != 0) { Request.setOAuth(params.authId, params.oauth, params.oauthExpiredTime); } else { @@ -102,6 +101,9 @@ public static void main(String[] args) throws Throwable { if(params.extendedTokens != null) { Request.addAllExtendedToken(params.extendedTokens); } + } else if(params.session != null) { + LogHelper.info("Using Sessions"); + Request.setSession(params.session); } checkJVMBitsAndVersion(params.profile.getMinJavaVersion(), params.profile.getRecommendJavaVersion(), params.profile.getMaxJavaVersion(), params.profile.isWarnMissJavaVersion()); LauncherEngine.modulesManager.invokeEvent(new ClientProcessInitPhase(engine, params)); diff --git a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java index cc1ab9d4..7df14c63 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java +++ b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java @@ -90,6 +90,9 @@ public ClientLauncherProcess(Path clientDir, Path assetDir, Path javaDir, Path r javaVersion = ClientLauncherWrapper.JavaVersion.getByPath(javaDir); } catch (IOException e) { LogHelper.error(e); + javaVersion = null; + } + if(javaVersion == null) { javaVersion = ClientLauncherWrapper.JavaVersion.getCurrentJavaVersion(); } this.bits = JVMHelper.JVM_BITS; @@ -120,6 +123,7 @@ private void applyClientProfile() { if(this.params.oauth == null) { this.params.session = Request.getSession(); } else { + this.params.authId = Request.getAuthId(); this.params.oauthExpiredTime = Request.getTokenExpiredTime(); this.params.extendedTokens = Request.getExtendedTokens(); } diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/LauncherRequestEvent.java b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/LauncherRequestEvent.java index 3eaf31c0..4703fe85 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/LauncherRequestEvent.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/LauncherRequestEvent.java @@ -9,6 +9,7 @@ public class LauncherRequestEvent extends RequestEvent { @SuppressWarnings("unused") private static final UUID uuid = UUID.fromString("d54cc12a-4f59-4f23-9b10-f527fdd2e38f"); + public static final String LAUNCHER_EXTENDED_TOKEN_NAME = "launcher"; @LauncherNetworkAPI public String url; @LauncherNetworkAPI @@ -17,6 +18,7 @@ public class LauncherRequestEvent extends RequestEvent { public byte[] binary; @LauncherNetworkAPI public boolean needUpdate; + public String launcherExtendedToken; public LauncherRequestEvent(boolean needUpdate, String url) { this.needUpdate = needUpdate; @@ -28,6 +30,12 @@ public LauncherRequestEvent(boolean b, byte[] digest) { this.digest = digest; } + public LauncherRequestEvent(boolean needUpdate, String url, String launcherExtendedToken) { + this.url = url; + this.needUpdate = needUpdate; + this.launcherExtendedToken = launcherExtendedToken; + } + public LauncherRequestEvent(byte[] binary, byte[] digest) { //Legacy support constructor this.binary = binary; this.digest = digest; diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/RestoreRequestEvent.java b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/RestoreRequestEvent.java index 0d8cac4a..6c9dd5a0 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/RestoreRequestEvent.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/RestoreRequestEvent.java @@ -2,8 +2,11 @@ import pro.gravit.launcher.events.RequestEvent; +import java.util.List; + public class RestoreRequestEvent extends RequestEvent { public CurrentUserRequestEvent.UserInfo userInfo; + public List invalidTokens; public RestoreRequestEvent() { } @@ -12,6 +15,15 @@ public RestoreRequestEvent(CurrentUserRequestEvent.UserInfo userInfo) { this.userInfo = userInfo; } + public RestoreRequestEvent(CurrentUserRequestEvent.UserInfo userInfo, List invalidTokens) { + this.userInfo = userInfo; + this.invalidTokens = invalidTokens; + } + + public RestoreRequestEvent(List invalidTokens) { + this.invalidTokens = invalidTokens; + } + @Override public String getType() { return "restore"; diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java index 77146c8e..c346ccf2 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java @@ -10,12 +10,12 @@ import pro.gravit.launcher.request.auth.RestoreSessionRequest; import pro.gravit.launcher.request.websockets.StdWebSocketService; import pro.gravit.launcher.request.websockets.WebSocketRequest; +import pro.gravit.utils.helper.LogHelper; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Function; +import java.util.stream.Collectors; public abstract class Request implements WebSocketRequest { public static StdWebSocketService service; @@ -24,6 +24,10 @@ public abstract class Request implements WebSocketRequ private static Map extendedTokens; private static String authId; private static long tokenExpiredTime; + private static List extendedTokenCallbacks = new ArrayList<>(4); + public interface ExtendedTokenCallback { + String tryGetNewToken(String name); + } @LauncherNetworkAPI public final UUID requestUUID = UUID.randomUUID(); private transient final AtomicBoolean started = new AtomicBoolean(false); @@ -46,10 +50,18 @@ public static void setOAuth(String authId, AuthRequestEvent.OAuthRequestEvent ev } } + public void addExtendedTokenCallback(ExtendedTokenCallback cb) { + extendedTokenCallbacks.add(cb); + } + public static AuthRequestEvent.OAuthRequestEvent getOAuth() { return oauth; } + public static String getAuthId() { + return authId; + } + public static Map getExtendedTokens() { if(extendedTokens != null) { return Collections.unmodifiableMap(extendedTokens); @@ -108,17 +120,37 @@ public static void reconnect() throws Exception { } public static void restore() throws Exception { - if(session != null) { - RestoreSessionRequest request = new RestoreSessionRequest(session); - request.request(); - } - else if(oauth != null) { + 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); + RestoreRequestEvent event = request.request(); + if(event.invalidTokens != null && event.invalidTokens.size() > 0) { + boolean needRequest = false; + Map tokens = new HashMap<>(); + for(ExtendedTokenCallback cb : extendedTokenCallbacks) { + for(String tokenName : event.invalidTokens) { + String newToken = cb.tryGetNewToken(tokenName); + if(newToken != null) { + needRequest = true; + tokens.put(tokenName, newToken); + addExtendedToken(tokenName, newToken); + } + } + } + if(needRequest) { + request = new RestoreRequest(authId, null, tokens, false); + event = request.request(); + if(event.invalidTokens != null && event.invalidTokens.size() > 0) { + LogHelper.warning("Tokens %s not restored", String.join(",", event.invalidTokens)); + } + } + } + } else if(session != null) { + RestoreSessionRequest request = new RestoreSessionRequest(session); request.request(); } } diff --git a/modules b/modules index 7efafab8..d7d34954 160000 --- a/modules +++ b/modules @@ -1 +1 @@ -Subproject commit 7efafab83a169da634a28b9f0aadb14f512c8f58 +Subproject commit d7d34954f68deb77a1d7d0b170008e6573d3475f diff --git a/props.gradle b/props.gradle index fbe4303f..f7f1f918 100644 --- a/props.gradle +++ b/props.gradle @@ -6,6 +6,7 @@ verGuavaC = '30.1-jre' verJansi = '2.3.2' verJline = '3.19.0' + verJwt = '0.11.2' verBcprov = '1.68' verGson = '2.8.6' verBcpkix = '1.68'