mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 03:31:15 +03:00
Merge branch 'release/5.2.5'
This commit is contained in:
commit
0640fc6d60
25 changed files with 846 additions and 661 deletions
|
@ -0,0 +1,94 @@
|
|||
package pro.gravit.launchserver;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launchserver.helper.HttpHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.time.Duration;
|
||||
|
||||
public class HttpRequester {
|
||||
private transient final HttpClient httpClient = HttpClient.newBuilder().build();
|
||||
|
||||
public HttpRequester() {
|
||||
}
|
||||
|
||||
public static class SimpleErrorHandler<T> implements HttpHelper.HttpJsonErrorHandler<T, SimpleError> {
|
||||
private final Type type;
|
||||
|
||||
private SimpleErrorHandler(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHelper.HttpOptional<T, SimpleError> applyJson(JsonElement response, int statusCode) {
|
||||
if(statusCode < 200 || statusCode >= 300) {
|
||||
return new HttpHelper.HttpOptional<>(null, Launcher.gsonManager.gson.fromJson(response, SimpleError.class), statusCode);
|
||||
}
|
||||
return new HttpHelper.HttpOptional<>(Launcher.gsonManager.gson.fromJson(response, type), null, statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> SimpleErrorHandler<T> makeEH(Class<T> clazz) {
|
||||
return new SimpleErrorHandler<>(clazz);
|
||||
}
|
||||
|
||||
public <T> HttpRequest get(String url, String token) {
|
||||
try {
|
||||
var requestBuilder = HttpRequest.newBuilder()
|
||||
.method("GET", HttpRequest.BodyPublishers.noBody())
|
||||
.uri(new URI(url))
|
||||
.header("Content-Type", "application/json; charset=UTF-8")
|
||||
.header("Accept", "application/json")
|
||||
.timeout(Duration.ofMillis(10000));
|
||||
if(token != null) {
|
||||
requestBuilder.header("Authorization", "Bearer ".concat(token));
|
||||
}
|
||||
return requestBuilder.build();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> HttpRequest post(String url, T request, String token) {
|
||||
try {
|
||||
var requestBuilder = HttpRequest.newBuilder()
|
||||
.method("POST", HttpRequest.BodyPublishers.ofString(Launcher.gsonManager.gson.toJson(request)))
|
||||
.uri(new URI(url))
|
||||
.header("Content-Type", "application/json; charset=UTF-8")
|
||||
.header("Accept", "application/json")
|
||||
.timeout(Duration.ofMillis(10000));
|
||||
if(token != null) {
|
||||
requestBuilder.header("Authorization", "Bearer ".concat(token));
|
||||
}
|
||||
return requestBuilder.build();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> HttpHelper.HttpOptional<T, SimpleError> send(HttpRequest request, Class<T> clazz) throws IOException {
|
||||
return HttpHelper.send(httpClient, request, makeEH(clazz));
|
||||
}
|
||||
|
||||
public static class SimpleError {
|
||||
public String error;
|
||||
public int code;
|
||||
|
||||
public SimpleError(String error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SimpleError{" +
|
||||
"error='" + error + '\'' +
|
||||
", code=" + code +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
package pro.gravit.launchserver.auth;
|
||||
|
||||
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class AuthException extends IOException {
|
||||
private static final long serialVersionUID = -2586107832847245863L;
|
||||
|
@ -10,6 +14,24 @@ public AuthException(String message) {
|
|||
super(message);
|
||||
}
|
||||
|
||||
public static AuthException need2FA() {
|
||||
return new AuthException(AuthRequestEvent.TWO_FACTOR_NEED_ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
public static AuthException needMFA(List<Integer> factors) {
|
||||
String message = AuthRequestEvent.ONE_FACTOR_NEED_ERROR_MESSAGE_PREFIX
|
||||
.concat(factors.stream().map(String::valueOf).collect(Collectors.joining(".")));
|
||||
return new AuthException(message);
|
||||
}
|
||||
|
||||
public static AuthException wrongPassword() {
|
||||
return new AuthException(AuthRequestEvent.WRONG_PASSWORD_ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
public static AuthException userNotFound() {
|
||||
return new AuthException(AuthRequestEvent.USER_NOT_FOUND_ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getMessage();
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
|
||||
import pro.gravit.launchserver.auth.core.AuthSocialProvider;
|
||||
import pro.gravit.launchserver.auth.core.MySQLCoreProvider;
|
||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||
|
||||
|
@ -17,7 +16,6 @@ public final class AuthProviderPair {
|
|||
private transient final Logger logger = LogManager.getLogger();
|
||||
public boolean isDefault = true;
|
||||
public AuthCoreProvider core;
|
||||
public AuthSocialProvider social;
|
||||
public TextureProvider textureProvider;
|
||||
public Map<String, String> links;
|
||||
public transient String name;
|
||||
|
@ -25,22 +23,14 @@ public final class AuthProviderPair {
|
|||
public String displayName;
|
||||
private transient boolean warnOAuthShow = false;
|
||||
|
||||
public AuthProviderPair() {
|
||||
}
|
||||
|
||||
public AuthProviderPair(AuthCoreProvider core, TextureProvider textureProvider) {
|
||||
this.core = core;
|
||||
this.textureProvider = textureProvider;
|
||||
}
|
||||
|
||||
public AuthProviderPair(AuthCoreProvider core, AuthSocialProvider social) {
|
||||
this.core = core;
|
||||
this.social = social;
|
||||
}
|
||||
|
||||
public AuthProviderPair(AuthCoreProvider core, AuthSocialProvider social, TextureProvider textureProvider) {
|
||||
this.core = core;
|
||||
this.social = social;
|
||||
this.textureProvider = textureProvider;
|
||||
}
|
||||
|
||||
public static Set<String> getFeatures(Class<?> clazz) {
|
||||
Set<String> list = new HashSet<>();
|
||||
getFeatures(clazz, list);
|
||||
|
@ -76,7 +66,6 @@ public static void getFeatures(Class<?> clazz, Set<String> list) {
|
|||
public final <T> T isSupport(Class<T> clazz) {
|
||||
if (core == null) return null;
|
||||
T result = null;
|
||||
if (social != null) result = social.isSupport(clazz);
|
||||
if (result == null) result = core.isSupport(clazz);
|
||||
return result;
|
||||
}
|
||||
|
@ -87,10 +76,6 @@ public final void init(LaunchServer srv, String name) {
|
|||
core.init(srv);
|
||||
features = new HashSet<>();
|
||||
getFeatures(core.getClass(), features);
|
||||
if (social != null) {
|
||||
social.init(srv, core);
|
||||
getFeatures(social.getClass(), features);
|
||||
}
|
||||
}
|
||||
|
||||
public final void link(LaunchServer srv) {
|
||||
|
@ -108,16 +93,9 @@ public final void link(LaunchServer srv) {
|
|||
}
|
||||
|
||||
public final void close() throws IOException {
|
||||
if (social != null) {
|
||||
social.close();
|
||||
}
|
||||
core.close();
|
||||
if (textureProvider != null) {
|
||||
textureProvider.close();
|
||||
}
|
||||
}
|
||||
|
||||
public final boolean isUseSocial() {
|
||||
return core != null && social != null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,8 @@ public static void registerProviders() {
|
|||
if (!registredProviders) {
|
||||
providers.register("reject", RejectAuthCoreProvider.class);
|
||||
providers.register("mysql", MySQLCoreProvider.class);
|
||||
providers.register("json", JsonCoreProvider.class);
|
||||
providers.register("memory", MemoryAuthCoreProvider.class);
|
||||
providers.register("http", HttpAuthCoreProvider.class);
|
||||
registredProviders = true;
|
||||
}
|
||||
}
|
||||
|
@ -62,16 +63,22 @@ public User getUserByLogin(String login) {
|
|||
|
||||
public abstract AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context /* may be null */);
|
||||
|
||||
public abstract void verifyAuth(AuthResponse.AuthContext context) throws AuthException;
|
||||
public void verifyAuth(AuthResponse.AuthContext context) throws AuthException {
|
||||
// None
|
||||
}
|
||||
|
||||
public abstract PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordInterface password);
|
||||
public abstract AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext context /* may be null */, AuthRequest.AuthPasswordInterface password /* may be null */, boolean minecraftAccess) throws IOException;
|
||||
|
||||
public abstract AuthManager.AuthReport createOAuthSession(User user, AuthResponse.AuthContext context /* may be null */, PasswordVerifyReport report /* may be null */, boolean minecraftAccess) throws IOException;
|
||||
public AuthManager.AuthReport authorize(User user, AuthResponse.AuthContext context /* may be null */, AuthRequest.AuthPasswordInterface password /* may be null */, boolean minecraftAccess) throws IOException {
|
||||
return authorize(user.getUsername(), context, password, minecraftAccess);
|
||||
}
|
||||
|
||||
public abstract void init(LaunchServer server);
|
||||
|
||||
// Auth Handler methods
|
||||
protected abstract boolean updateServerID(User user, String serverID) throws IOException;
|
||||
protected boolean updateServerID(User user, String serverID) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
|
||||
return List.of(new AuthPasswordDetails());
|
||||
|
@ -80,32 +87,28 @@ public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(
|
|||
@Override
|
||||
public Map<String, Command> getCommands() {
|
||||
Map<String, Command> map = defaultCommandsMap();
|
||||
map.put("checkpassword", new SubCommand("[username] [json/plain password data]", "check password") {
|
||||
map.put("auth", new SubCommand("[login] (json/plain password data)", "Test auth") {
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 2);
|
||||
User user = getUserByUsername(args[0]);
|
||||
if (user == null) throw new CommandException("User not found");
|
||||
AuthRequest.AuthPasswordInterface password;
|
||||
if (args[1].startsWith("{")) {
|
||||
password = Launcher.gsonManager.gson.fromJson(args[1], AuthRequest.AuthPasswordInterface.class);
|
||||
} else {
|
||||
password = new AuthPlainPassword(args[1]);
|
||||
}
|
||||
PasswordVerifyReport report = verifyPassword(user, password);
|
||||
if (report.success) {
|
||||
logger.info("Password correct");
|
||||
} else {
|
||||
if (report.needMoreFactors) {
|
||||
if (report.factors.size() == 1 && report.factors.get(0) == -1) {
|
||||
logger.info("Password not correct: Required 2FA");
|
||||
} else {
|
||||
logger.info("Password not correct: Required more factors: {}", report.factors.toString());
|
||||
}
|
||||
verifyArgs(args, 1);
|
||||
AuthRequest.AuthPasswordInterface password = null;
|
||||
if(args.length > 1) {
|
||||
if (args[1].startsWith("{")) {
|
||||
password = Launcher.gsonManager.gson.fromJson(args[1], AuthRequest.AuthPasswordInterface.class);
|
||||
} else {
|
||||
logger.info("Password incorrect");
|
||||
password = new AuthPlainPassword(args[1]);
|
||||
}
|
||||
}
|
||||
var report = authorize(args[0], null, password, false);
|
||||
if (report.isUsingOAuth()) {
|
||||
logger.info("OAuth: AccessToken: {} RefreshToken: {} MinecraftAccessToken: {}", report.oauthAccessToken(), report.oauthRefreshToken(), report.minecraftAccessToken());
|
||||
if (report.session() != null) {
|
||||
logger.info("UserSession: id {} expire {} user {}", report.session().getID(), report.session().getExpireIn(), report.session().getUser() == null ? "null" : "found");
|
||||
logger.info(report.session().toString());
|
||||
}
|
||||
} else {
|
||||
logger.info("Basic: MinecraftAccessToken: {}", report.minecraftAccessToken());
|
||||
}
|
||||
}
|
||||
});
|
||||
map.put("getuserbyusername", new SubCommand("[username]", "get user by username") {
|
||||
|
@ -132,32 +135,6 @@ public void invoke(String... args) throws Exception {
|
|||
}
|
||||
}
|
||||
});
|
||||
map.put("createsession", new SubCommand("[username] (true/false)", "create user session with/without minecraft access") {
|
||||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 1);
|
||||
User user = getUserByUsername(args[0]);
|
||||
if (user == null) {
|
||||
logger.info("User {} not found", args[0]);
|
||||
return;
|
||||
}
|
||||
boolean minecraftAccess = args.length > 1 && Boolean.parseBoolean(args[1]);
|
||||
AuthManager.AuthReport report = createOAuthSession(user, null, null, minecraftAccess);
|
||||
if (report == null) {
|
||||
logger.error("Method createOAuthSession return null");
|
||||
return;
|
||||
}
|
||||
if (report.isUsingOAuth()) {
|
||||
logger.info("OAuth: AccessToken: {} RefreshToken: {} MinecraftAccessToken: {}", report.oauthAccessToken(), report.oauthRefreshToken(), report.minecraftAccessToken());
|
||||
if (report.session() != null) {
|
||||
logger.info("UserSession: id {} expire {} user {}", report.session().getID(), report.session().getExpireIn(), report.session().getUser() == null ? "null" : "found");
|
||||
logger.info(report.session().toString());
|
||||
}
|
||||
} else {
|
||||
logger.info("Basic: MinecraftAccessToken: {}", report.minecraftAccessToken());
|
||||
}
|
||||
}
|
||||
});
|
||||
{
|
||||
var instance = isSupport(AuthSupportGetAllUsers.class);
|
||||
if (instance != null) {
|
||||
|
@ -355,6 +332,12 @@ public PasswordVerifyReport(boolean success) {
|
|||
this.factors = List.of();
|
||||
}
|
||||
|
||||
public PasswordVerifyReport(AuthManager.AuthReport report) {
|
||||
this.success = true;
|
||||
this.needMoreFactors = false;
|
||||
this.factors = List.of();
|
||||
}
|
||||
|
||||
public PasswordVerifyReport(int nextFactor) {
|
||||
this.success = false;
|
||||
this.needMoreFactors = true;
|
||||
|
@ -372,6 +355,10 @@ private PasswordVerifyReport(boolean success, boolean needMoreFactors, List<Inte
|
|||
this.needMoreFactors = needMoreFactors;
|
||||
this.factors = factors;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
public static class OAuthAccessTokenExpired extends Exception {
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.core;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||
import pro.gravit.utils.ProviderMap;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AuthSocialProvider implements AutoCloseable {
|
||||
public static final ProviderMap<AuthSocialProvider> providers = new ProviderMap<>("AuthSocialProvider");
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
private static boolean registredProviders = false;
|
||||
|
||||
public static void registerProviders() {
|
||||
if (!registredProviders) {
|
||||
registredProviders = true;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void init(LaunchServer server, AuthCoreProvider provider);
|
||||
|
||||
public abstract List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client);
|
||||
|
||||
public abstract SocialResult preAuth(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T isSupport(Class<T> clazz) {
|
||||
if (clazz.isAssignableFrom(getClass())) return (T) this;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract void close() throws IOException;
|
||||
|
||||
public static class SocialResult {
|
||||
public String login;
|
||||
public AuthRequest.AuthPasswordInterface password;
|
||||
public User user;
|
||||
|
||||
public SocialResult(String login, AuthRequest.AuthPasswordInterface password, User user) {
|
||||
this.login = login;
|
||||
this.password = password;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public static SocialResult ofLoginAndPassword(String login, AuthRequest.AuthPasswordInterface password) {
|
||||
return new SocialResult(login, password, null);
|
||||
}
|
||||
|
||||
public static SocialResult ofUser(User user) {
|
||||
return new SocialResult(null, null, user);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,333 @@
|
|||
package pro.gravit.launchserver.auth.core;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.events.request.AuthRequestEvent;
|
||||
import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent;
|
||||
import pro.gravit.launcher.profiles.Texture;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launchserver.HttpRequester;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportTextures;
|
||||
import pro.gravit.launchserver.helper.HttpHelper;
|
||||
import pro.gravit.launchserver.manangers.AuthManager;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||
import pro.gravit.utils.helper.CommonHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class HttpAuthCoreProvider extends AuthCoreProvider {
|
||||
private transient final Logger logger = LogManager.getLogger();
|
||||
private transient HttpRequester requester;
|
||||
public String bearerToken;
|
||||
public String getUserByUsernameUrl;
|
||||
public String getUserByLoginUrl;
|
||||
public String getUserByUUIDUrl;
|
||||
public String getUserByTokenUrl;
|
||||
public String getAuthDetails;
|
||||
public String refreshTokenUrl;
|
||||
public String authorizeUrl;
|
||||
public String joinServerUrl;
|
||||
public String checkServerUrl;
|
||||
public String updateServerIdUrl;
|
||||
@Override
|
||||
public User getUserByUsername(String username) {
|
||||
try {
|
||||
return requester.send(requester.get(CommonHelper.replace(getUserByUsernameUrl, "username", username), null), HttpUser.class).getOrThrow();
|
||||
} catch (IOException e) {
|
||||
logger.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUserByLogin(String login) {
|
||||
if(getUserByLoginUrl != null) {
|
||||
try {
|
||||
return requester.send(requester.get(CommonHelper.replace(getUserByLoginUrl, "login", login), null), HttpUser.class).getOrThrow();
|
||||
} catch (IOException e) {
|
||||
logger.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return super.getUserByLogin(login);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUserByUUID(UUID uuid) {
|
||||
try {
|
||||
return requester.send(requester.get(CommonHelper.replace(getUserByUUIDUrl, "uuid", uuid.toString()), null), HttpUser.class).getOrThrow();
|
||||
} catch (IOException e) {
|
||||
logger.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
|
||||
if(getAuthDetails == null) {
|
||||
return super.getDetails(client);
|
||||
}
|
||||
try {
|
||||
var result = requester.send(requester.get(getAuthDetails, bearerToken), GetAuthDetailsResponse.class).getOrThrow();
|
||||
return result.details;
|
||||
} catch (IOException e) {
|
||||
logger.error(e);
|
||||
return super.getDetails(client);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
|
||||
if(getUserByTokenUrl == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
var result = requester.send(requester.get(getUserByTokenUrl, accessToken), HttpUserSession.class);
|
||||
if(!result.isSuccessful()) {
|
||||
var error = result.error().error;
|
||||
if(error.equals(AuthRequestEvent.OAUTH_TOKEN_EXPIRE)) {
|
||||
throw new OAuthAccessTokenExpired();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return result.getOrThrow();
|
||||
} catch (IOException e) {
|
||||
logger.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
|
||||
if(refreshTokenUrl == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return requester.send(requester.post(refreshTokenUrl, new RefreshTokenRequest(refreshToken, context),
|
||||
null), AuthManager.AuthReport.class).getOrThrow();
|
||||
} catch (IOException e) {
|
||||
logger.error(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password, boolean minecraftAccess) throws IOException {
|
||||
var result = requester.send(requester.post(authorizeUrl, new AuthorizeRequest(login, context, password, minecraftAccess),
|
||||
bearerToken), AuthManager.AuthReport.class);
|
||||
if(!result.isSuccessful()) {
|
||||
var error = result.error().error;
|
||||
if(error != null) {
|
||||
throw new AuthException(error);
|
||||
}
|
||||
}
|
||||
return result.getOrThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateServerID(User user, String serverID) throws IOException {
|
||||
var result = requester.send(requester.post(updateServerIdUrl, new UpdateServerIdRequest(user.getUsername(), user.getUUID(), serverID),
|
||||
null), Void.class);
|
||||
return result.isSuccessful();
|
||||
}
|
||||
|
||||
@Override
|
||||
public User checkServer(Client client, String username, String serverID) throws IOException {
|
||||
return requester.send(requester.post(checkServerUrl, new CheckServerRequest(username, serverID), null), HttpUser.class).getOrThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean joinServer(Client client, String username, String accessToken, String serverID) throws IOException {
|
||||
var result = requester.send(requester.post(joinServerUrl, new JoinServerRequest(username, accessToken, serverID), null), Void.class);
|
||||
return result.isSuccessful();
|
||||
}
|
||||
|
||||
public static class UpdateServerIdRequest {
|
||||
public String username;
|
||||
public UUID uuid;
|
||||
public String serverId;
|
||||
|
||||
public UpdateServerIdRequest(String username, UUID uuid, String serverId) {
|
||||
this.username = username;
|
||||
this.uuid = uuid;
|
||||
this.serverId = serverId;
|
||||
}
|
||||
}
|
||||
|
||||
public static class CheckServerRequest {
|
||||
public String username;
|
||||
public String serverId;
|
||||
|
||||
public CheckServerRequest(String username, String serverId) {
|
||||
this.username = username;
|
||||
this.serverId = serverId;
|
||||
}
|
||||
}
|
||||
|
||||
public static class GetAuthDetailsResponse {
|
||||
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> details;
|
||||
}
|
||||
|
||||
public static class JoinServerRequest {
|
||||
public String username;
|
||||
public String accessToken;
|
||||
public String serverId;
|
||||
|
||||
public JoinServerRequest(String username, String accessToken, String serverId) {
|
||||
this.username = username;
|
||||
this.accessToken = accessToken;
|
||||
this.serverId = serverId;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(LaunchServer server) {
|
||||
requester = new HttpRequester();
|
||||
if(getUserByUsernameUrl == null) {
|
||||
throw new IllegalArgumentException("'getUserByUsernameUrl' can't be null");
|
||||
}
|
||||
if(getUserByUUIDUrl == null) {
|
||||
throw new IllegalArgumentException("'getUserByUUIDUrl' can't be null");
|
||||
}
|
||||
if(authorizeUrl == null) {
|
||||
throw new IllegalArgumentException("'authorizeUrl' can't be null");
|
||||
}
|
||||
if((checkServerUrl == null && joinServerUrl == null) || updateServerIdUrl == null) {
|
||||
throw new IllegalArgumentException("Please set 'checkServerUrl' and 'joinServerUrl' or 'updateServerIdUrl'");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
|
||||
}
|
||||
|
||||
public static class AuthorizeRequest {
|
||||
public String login;
|
||||
public AuthResponse.AuthContext context;
|
||||
public AuthRequest.AuthPasswordInterface password;
|
||||
public boolean minecraftAccess;
|
||||
|
||||
public AuthorizeRequest() {
|
||||
}
|
||||
|
||||
public AuthorizeRequest(String login, AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password, boolean minecraftAccess) {
|
||||
this.login = login;
|
||||
this.context = context;
|
||||
this.password = password;
|
||||
this.minecraftAccess = minecraftAccess;
|
||||
}
|
||||
}
|
||||
|
||||
public static class RefreshTokenRequest {
|
||||
public String refreshToken;
|
||||
public AuthResponse.AuthContext context;
|
||||
|
||||
public RefreshTokenRequest(String refreshToken, AuthResponse.AuthContext context) {
|
||||
this.refreshToken = refreshToken;
|
||||
this.context = context;
|
||||
}
|
||||
}
|
||||
|
||||
public static class HttpUser implements User, UserSupportTextures {
|
||||
private String username;
|
||||
private UUID uuid;
|
||||
private String serverId;
|
||||
private String accessToken;
|
||||
private ClientPermissions permissions;
|
||||
private Texture skin;
|
||||
private Texture cloak;
|
||||
|
||||
public HttpUser() {
|
||||
}
|
||||
|
||||
public HttpUser(String username, UUID uuid, String serverId, String accessToken, ClientPermissions permissions) {
|
||||
this.username = username;
|
||||
this.uuid = uuid;
|
||||
this.serverId = serverId;
|
||||
this.accessToken = accessToken;
|
||||
this.permissions = permissions;
|
||||
}
|
||||
|
||||
public HttpUser(String username, UUID uuid, String serverId, String accessToken, ClientPermissions permissions, Texture skin, Texture cloak) {
|
||||
this.username = username;
|
||||
this.uuid = uuid;
|
||||
this.serverId = serverId;
|
||||
this.accessToken = accessToken;
|
||||
this.permissions = permissions;
|
||||
this.skin = skin;
|
||||
this.cloak = cloak;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerId() {
|
||||
return serverId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientPermissions getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Texture getSkinTexture() {
|
||||
return skin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Texture getCloakTexture() {
|
||||
return cloak;
|
||||
}
|
||||
}
|
||||
|
||||
public static class HttpUserSession implements UserSession {
|
||||
private String id;
|
||||
private User user;
|
||||
private long expireIn;
|
||||
|
||||
public HttpUserSession() {
|
||||
}
|
||||
|
||||
public HttpUserSession(String id, User user, long expireIn) {
|
||||
this.id = id;
|
||||
this.user = user;
|
||||
this.expireIn = expireIn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getExpireIn() {
|
||||
return expireIn;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,410 +0,0 @@
|
|||
package pro.gravit.launchserver.auth.core;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.password.AuthPlainPassword;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.launchserver.auth.password.PasswordVerifier;
|
||||
import pro.gravit.launchserver.manangers.AuthManager;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class JsonCoreProvider extends AuthCoreProvider {
|
||||
private static transient final Logger logger = LogManager.getLogger();
|
||||
public String getUserByUsernameUrl;
|
||||
public String getUserByLoginUrl;
|
||||
public String getUserByUUIDUrl;
|
||||
public String getUserSessionByOAuthAccessTokenUrl;
|
||||
public String getAuthDetailsUrl;
|
||||
public String refreshAccessTokenUrl;
|
||||
public String verifyPasswordUrl;
|
||||
public String createOAuthSessionUrl;
|
||||
public String updateServerIdUrl;
|
||||
public String joinServerUrl;
|
||||
public String checkServerUrl;
|
||||
public String bearerToken;
|
||||
public PasswordVerifier passwordVerifier;
|
||||
private transient HttpClient client;
|
||||
|
||||
public static <T, R> R jsonRequest(T request, String url, String bearerToken, Class<R> clazz, HttpClient client) {
|
||||
HttpRequest.BodyPublisher publisher;
|
||||
if (request != null) {
|
||||
publisher = HttpRequest.BodyPublishers.ofString(Launcher.gsonManager.gson.toJson(request));
|
||||
} else {
|
||||
publisher = HttpRequest.BodyPublishers.noBody();
|
||||
}
|
||||
try {
|
||||
HttpRequest.Builder request1 = HttpRequest.newBuilder()
|
||||
.method("POST", publisher)
|
||||
.uri(new URI(url))
|
||||
.header("Content-Type", "application/json; charset=UTF-8")
|
||||
.header("Accept", "application/json")
|
||||
.timeout(Duration.ofMillis(10000));
|
||||
if (bearerToken != null) {
|
||||
request1.header("Authorization", "Bearer ".concat(bearerToken));
|
||||
}
|
||||
HttpResponse<InputStream> response = client.send(request1.build(), HttpResponse.BodyHandlers.ofInputStream());
|
||||
int statusCode = response.statusCode();
|
||||
if (200 > statusCode || statusCode > 300) {
|
||||
if (statusCode >= 500) {
|
||||
logger.error("JsonCoreProvider: {} return {}", url, statusCode);
|
||||
} else if (statusCode >= 300 && statusCode <= 400) {
|
||||
logger.error("JsonCoreProvider: {} return {}, try redirect to {}. Redirects not supported!", url, statusCode, response.headers().firstValue("Location").orElse("Unknown"));
|
||||
} else if (statusCode == 403 || statusCode == 401) {
|
||||
logger.error("JsonCoreProvider: {} return {}. Please set 'bearerToken'!", url, statusCode);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
try (Reader reader = new InputStreamReader(response.body())) {
|
||||
return Launcher.gsonManager.gson.fromJson(reader, clazz);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUserByUsername(String username) {
|
||||
return jsonRequest(new JsonGetUserByUsername(username), getUserByUsernameUrl, JsonUser.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUserByLogin(String login) {
|
||||
if (getUserByLoginUrl != null) {
|
||||
return jsonRequest(new JsonGetUserByUsername(login), getUserByLoginUrl, JsonUser.class);
|
||||
}
|
||||
return super.getUserByLogin(login);
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUserByUUID(UUID uuid) {
|
||||
return jsonRequest(new JsonGetUserByUUID(uuid), getUserByUUIDUrl, JsonUser.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
|
||||
if (getUserSessionByOAuthAccessTokenUrl == null) {
|
||||
return null;
|
||||
}
|
||||
JsonGetUserSessionByOAuthTokenResponse response = jsonRequest(new JsonGetUserSessionByAccessToken(accessToken), getUserSessionByOAuthAccessTokenUrl, JsonGetUserSessionByOAuthTokenResponse.class);
|
||||
if (response == null) return null;
|
||||
if (!response.expired) throw new OAuthAccessTokenExpired();
|
||||
return response.session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
|
||||
if (getAuthDetailsUrl != null) {
|
||||
JsonGetDetailsResponse response = jsonRequest(new JsonGetDetails(), getAuthDetailsUrl, JsonGetDetailsResponse.class);
|
||||
if (response == null) return super.getDetails(client);
|
||||
return response.details;
|
||||
}
|
||||
return super.getDetails(client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
|
||||
JsonAuthReportResponse response = jsonRequest(new JsonRefreshToken(refreshToken, context.ip), this.refreshAccessTokenUrl, JsonAuthReportResponse.class);
|
||||
return response == null ? null : response.toAuthReport();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verifyAuth(AuthResponse.AuthContext context) throws AuthException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordInterface password) {
|
||||
JsonUser jsonUser = (JsonUser) user;
|
||||
if (password instanceof AuthPlainPassword && jsonUser.password != null && passwordVerifier != null) {
|
||||
if (passwordVerifier.check(jsonUser.password, ((AuthPlainPassword) password).password)) {
|
||||
return PasswordVerifyReport.OK;
|
||||
} else {
|
||||
return PasswordVerifyReport.FAILED;
|
||||
}
|
||||
}
|
||||
if (user == null) {
|
||||
return jsonRequest(new JsonPasswordVerify(null, null, password), verifyPasswordUrl, PasswordVerifyReport.class);
|
||||
}
|
||||
return jsonRequest(new JsonPasswordVerify(user.getUsername(), user.getUUID(), password), verifyPasswordUrl, PasswordVerifyReport.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthManager.AuthReport createOAuthSession(User user, AuthResponse.AuthContext context, PasswordVerifyReport report, boolean minecraftAccess) throws IOException {
|
||||
JsonAuthReportResponse response = jsonRequest(new JsonCreateOAuthSession(user == null ? null : user.getUsername(), user == null ? null : user.getUUID(), minecraftAccess), createOAuthSessionUrl, JsonAuthReportResponse.class);
|
||||
if (response == null) return null;
|
||||
if (response.error != null) throw new AuthException(response.error);
|
||||
JsonUser user1 = (JsonUser) user;
|
||||
user1.accessToken = response.minecraftAccessToken;
|
||||
return response.toAuthReport();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(LaunchServer server) {
|
||||
client = HttpClient.newBuilder().build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public User checkServer(Client client, String username, String serverID) throws IOException {
|
||||
if (checkServerUrl == null) {
|
||||
return super.checkServer(client, username, serverID);
|
||||
}
|
||||
return jsonRequest(new JsonCheckServer(username, serverID), checkServerUrl, JsonUser.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean joinServer(Client client, String username, String accessToken, String serverID) throws IOException {
|
||||
if (joinServerUrl == null) {
|
||||
return super.joinServer(client, username, accessToken, serverID);
|
||||
}
|
||||
return jsonRequest(new JsonJoinServer(username, accessToken, serverID), joinServerUrl, JsonSuccessResponse.class).success;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateServerID(User user, String serverID) throws IOException {
|
||||
JsonUser jsonUser = (JsonUser) user;
|
||||
if (updateServerIdUrl == null) {
|
||||
return false;
|
||||
}
|
||||
jsonUser.serverId = serverID;
|
||||
JsonSuccessResponse successResponse = jsonRequest(new JsonUpdateServerId(user.getUsername(), user.getUUID(), serverID), updateServerIdUrl, JsonSuccessResponse.class);
|
||||
if (successResponse == null) return false;
|
||||
return successResponse.success;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
|
||||
}
|
||||
|
||||
public <T, R> R jsonRequest(T request, String url, Class<R> clazz) {
|
||||
return jsonRequest(request, url, bearerToken, clazz, client);
|
||||
}
|
||||
|
||||
public static class JsonGetUserByUsername {
|
||||
public String username;
|
||||
|
||||
public JsonGetUserByUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
|
||||
public static class JsonCheckServer {
|
||||
public String username;
|
||||
public String serverId;
|
||||
|
||||
public JsonCheckServer(String username, String serverId) {
|
||||
this.username = username;
|
||||
this.serverId = serverId;
|
||||
}
|
||||
}
|
||||
|
||||
public static class JsonJoinServer {
|
||||
public String username;
|
||||
public String accessToken;
|
||||
public String serverId;
|
||||
|
||||
public JsonJoinServer(String username, String accessToken, String serverId) {
|
||||
this.username = username;
|
||||
this.accessToken = accessToken;
|
||||
this.serverId = serverId;
|
||||
}
|
||||
}
|
||||
|
||||
public static class JsonGetUserByUUID {
|
||||
public UUID uuid;
|
||||
|
||||
public JsonGetUserByUUID(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
}
|
||||
|
||||
public static class JsonGetUserSessionByAccessToken {
|
||||
public String accessToken;
|
||||
|
||||
public JsonGetUserSessionByAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
}
|
||||
|
||||
public static class JsonRefreshToken {
|
||||
public String refreshToken;
|
||||
public String ip;
|
||||
|
||||
public JsonRefreshToken(String refreshToken, String ip) {
|
||||
this.refreshToken = refreshToken;
|
||||
this.ip = ip;
|
||||
}
|
||||
}
|
||||
|
||||
public static class JsonAuthReportResponse {
|
||||
public String minecraftAccessToken;
|
||||
public String oauthAccessToken;
|
||||
public String oauthRefreshToken;
|
||||
public long oauthExpire;
|
||||
public JsonUserSession session;
|
||||
public String error;
|
||||
|
||||
public AuthManager.AuthReport toAuthReport() {
|
||||
return new AuthManager.AuthReport(minecraftAccessToken, oauthAccessToken, oauthRefreshToken, oauthExpire, session);
|
||||
}
|
||||
}
|
||||
|
||||
public static class JsonPasswordVerify {
|
||||
public String username;
|
||||
public UUID uuid;
|
||||
public AuthRequest.AuthPasswordInterface password;
|
||||
|
||||
public JsonPasswordVerify(String username, UUID uuid, AuthRequest.AuthPasswordInterface password) {
|
||||
this.username = username;
|
||||
this.uuid = uuid;
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
|
||||
public static class JsonCreateOAuthSession {
|
||||
public String username;
|
||||
public UUID uuid;
|
||||
public boolean minecraftAccess;
|
||||
|
||||
public JsonCreateOAuthSession(String username, UUID uuid, boolean minecraftAccess) {
|
||||
this.username = username;
|
||||
this.uuid = uuid;
|
||||
this.minecraftAccess = minecraftAccess;
|
||||
}
|
||||
}
|
||||
|
||||
public static class JsonUpdateServerId {
|
||||
public String username;
|
||||
public UUID uuid;
|
||||
public String serverId;
|
||||
|
||||
public JsonUpdateServerId(String username, UUID uuid, String serverId) {
|
||||
this.username = username;
|
||||
this.uuid = uuid;
|
||||
this.serverId = serverId;
|
||||
}
|
||||
}
|
||||
|
||||
public static class JsonSuccessResponse {
|
||||
public boolean success;
|
||||
}
|
||||
|
||||
public static class JsonGetUserSessionByOAuthTokenResponse {
|
||||
public boolean expired;
|
||||
public JsonUserSession session;
|
||||
|
||||
public JsonGetUserSessionByOAuthTokenResponse() {
|
||||
}
|
||||
}
|
||||
|
||||
public static class JsonGetDetails {
|
||||
|
||||
}
|
||||
|
||||
public static class JsonGetDetailsResponse {
|
||||
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> details;
|
||||
}
|
||||
|
||||
public static class JsonUser implements User {
|
||||
private String username;
|
||||
private UUID uuid;
|
||||
private String serverId;
|
||||
private String accessToken;
|
||||
private ClientPermissions permissions;
|
||||
private String password;
|
||||
|
||||
public JsonUser() {
|
||||
}
|
||||
|
||||
public JsonUser(String username, UUID uuid, String serverId, String accessToken, ClientPermissions permissions, String password) {
|
||||
this.username = username;
|
||||
this.uuid = uuid;
|
||||
this.serverId = serverId;
|
||||
this.accessToken = accessToken;
|
||||
this.permissions = permissions;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerId() {
|
||||
return serverId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientPermissions getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JsonUser{" +
|
||||
"username='" + username + '\'' +
|
||||
", uuid=" + uuid +
|
||||
", permissions=" + permissions +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
public static class JsonUserSession implements UserSession {
|
||||
public String id;
|
||||
public JsonUser user;
|
||||
public long expireIn;
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getExpireIn() {
|
||||
return expireIn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JsonUserSession{" +
|
||||
"id='" + id + '\'' +
|
||||
"user='" + (user == null ? null : user.getUsername()) + '\'' +
|
||||
", expireIn=" + expireIn +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,212 @@
|
|||
package pro.gravit.launchserver.auth.core;
|
||||
|
||||
import pro.gravit.launcher.ClientPermissions;
|
||||
import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent;
|
||||
import pro.gravit.launcher.request.auth.AuthRequest;
|
||||
import pro.gravit.launcher.request.auth.details.AuthLoginOnlyDetails;
|
||||
import pro.gravit.launchserver.LaunchServer;
|
||||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.launchserver.manangers.AuthManager;
|
||||
import pro.gravit.launchserver.socket.Client;
|
||||
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
|
||||
public class MemoryAuthCoreProvider extends AuthCoreProvider {
|
||||
private transient final List<MemoryUser> memory = new ArrayList<>(16);
|
||||
@Override
|
||||
public User getUserByUsername(String username) {
|
||||
synchronized (memory) {
|
||||
for(MemoryUser u : memory) {
|
||||
if(u.username.equals(username)) {
|
||||
return u;
|
||||
}
|
||||
}
|
||||
var result = new MemoryUser(username);
|
||||
memory.add(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
|
||||
return List.of(new AuthLoginOnlyDetails());
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUserByUUID(UUID uuid) {
|
||||
synchronized (memory) {
|
||||
for(MemoryUser u : memory) {
|
||||
if(u.uuid.equals(uuid)) {
|
||||
return u;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
|
||||
synchronized (memory) {
|
||||
for(MemoryUser u : memory) {
|
||||
if(u.accessToken.equals(accessToken)) {
|
||||
return new MemoryUserSession(u);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password, boolean minecraftAccess) throws IOException {
|
||||
if(login == null) {
|
||||
throw AuthException.userNotFound();
|
||||
}
|
||||
MemoryUser user = null;
|
||||
synchronized (memory) {
|
||||
for(MemoryUser u : memory) {
|
||||
if(u.username.equals(login)) {
|
||||
user = u;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(user == null) {
|
||||
user = new MemoryUser(login);
|
||||
memory.add(user);
|
||||
}
|
||||
}
|
||||
if(minecraftAccess) {
|
||||
return AuthManager.AuthReport.ofOAuth(user.accessToken, null, 0, new MemoryUserSession(user));
|
||||
} else {
|
||||
return AuthManager.AuthReport.ofOAuthWithMinecraft(user.accessToken, user.accessToken, null, 0, new MemoryUserSession(user));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateServerID(User user, String serverID) throws IOException {
|
||||
MemoryUser memoryUser = (MemoryUser) user;
|
||||
memoryUser.serverId = serverID;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User checkServer(Client client, String username, String serverID) throws IOException {
|
||||
synchronized (memory) {
|
||||
for(MemoryUser u : memory) {
|
||||
if(u.username.equals(username)) {
|
||||
return u;
|
||||
}
|
||||
}
|
||||
var result = new MemoryUser(username);
|
||||
memory.add(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean joinServer(Client client, String username, String accessToken, String serverID) throws IOException {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(LaunchServer server) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
|
||||
}
|
||||
|
||||
public static class MemoryUser implements User {
|
||||
private String username;
|
||||
private UUID uuid;
|
||||
private String serverId;
|
||||
private String accessToken;
|
||||
private ClientPermissions permissions;
|
||||
|
||||
public MemoryUser(String username) {
|
||||
this.username = username;
|
||||
this.uuid = makeUuidFromUsername(username);
|
||||
this.accessToken = SecurityHelper.randomStringToken();
|
||||
this.permissions = new ClientPermissions();
|
||||
}
|
||||
|
||||
private static UUID makeUuidFromUsername(String username) {
|
||||
return UUID.nameUUIDFromBytes(username.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerId() {
|
||||
return serverId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientPermissions getPermissions() {
|
||||
return permissions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
MemoryUser that = (MemoryUser) o;
|
||||
return uuid.equals(that.uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(uuid);
|
||||
}
|
||||
}
|
||||
|
||||
public static class MemoryUserSession implements UserSession {
|
||||
private String id;
|
||||
private MemoryUser user;
|
||||
private long expireIn;
|
||||
|
||||
public MemoryUserSession(MemoryUser user) {
|
||||
this.id = SecurityHelper.randomStringToken();
|
||||
this.user = user;
|
||||
this.expireIn = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getExpireIn() {
|
||||
return expireIn;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -105,27 +105,27 @@ public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthRespon
|
|||
}
|
||||
|
||||
@Override
|
||||
public void verifyAuth(AuthResponse.AuthContext context) throws AuthException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordInterface password) {
|
||||
if (passwordVerifier.check(((MySQLUser) user).password, ((AuthPlainPassword) password).password)) {
|
||||
return PasswordVerifyReport.OK;
|
||||
} else {
|
||||
return PasswordVerifyReport.FAILED;
|
||||
public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password, boolean minecraftAccess) throws IOException {
|
||||
MySQLUser mySQLUser = (MySQLUser) getUserByLogin(login);
|
||||
if(mySQLUser == null) {
|
||||
throw AuthException.wrongPassword();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthManager.AuthReport createOAuthSession(User user, AuthResponse.AuthContext context, PasswordVerifyReport report, boolean minecraftAccess) throws IOException {
|
||||
if(context != null) {
|
||||
AuthPlainPassword plainPassword = (AuthPlainPassword) password;
|
||||
if(plainPassword == null) {
|
||||
throw AuthException.wrongPassword();
|
||||
}
|
||||
if(!passwordVerifier.check(mySQLUser.password, plainPassword.password)) {
|
||||
throw AuthException.wrongPassword();
|
||||
}
|
||||
}
|
||||
MySQLUserSession session = new MySQLUserSession(mySQLUser);
|
||||
if (minecraftAccess) {
|
||||
String minecraftAccessToken = SecurityHelper.randomStringToken();
|
||||
updateAuth(user, minecraftAccessToken);
|
||||
return AuthManager.AuthReport.ofMinecraftAccessToken(minecraftAccessToken);
|
||||
updateAuth(mySQLUser, minecraftAccessToken);
|
||||
return AuthManager.AuthReport.ofMinecraftAccessToken(minecraftAccessToken, session);
|
||||
} else {
|
||||
return AuthManager.AuthReport.ofMinecraftAccessToken(null);
|
||||
return AuthManager.AuthReport.ofMinecraftAccessToken(null, session);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -333,13 +333,14 @@ public UserHardware createHardwareInfo(HardwareReportRequest.HardwareInfo hardwa
|
|||
}
|
||||
|
||||
@Override
|
||||
public void connectUserAndHardware(User user, UserHardware hardware) {
|
||||
MySQLUser mySQLUser = (MySQLUser) user;
|
||||
public void connectUserAndHardware(UserSession userSession, UserHardware hardware) {
|
||||
MySQLUserSession mySQLUserSession = (MySQLUserSession) userSession;
|
||||
MySQLUser mySQLUser = mySQLUserSession.user;
|
||||
MySQLUserHardware mySQLUserHardware = (MySQLUserHardware) hardware;
|
||||
if (mySQLUser.hwidId == mySQLUserHardware.id) return;
|
||||
mySQLUser.hwidId = mySQLUserHardware.id;
|
||||
try (Connection connection = mySQLHolder.getConnection()) {
|
||||
setUserHardwareId(connection, user.getUUID(), mySQLUserHardware.id);
|
||||
setUserHardwareId(connection, mySQLUser.getUUID(), mySQLUserHardware.id);
|
||||
} catch (SQLException throwables) {
|
||||
logger.error("SQL Error", throwables);
|
||||
}
|
||||
|
@ -513,4 +514,29 @@ public String toString() {
|
|||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
public static class MySQLUserSession implements UserSession {
|
||||
private final MySQLUser user;
|
||||
private final String id;
|
||||
|
||||
public MySQLUserSession(MySQLUser user) {
|
||||
this.user = user;
|
||||
this.id = user.username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getExpireIn() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,13 +36,8 @@ public void verifyAuth(AuthResponse.AuthContext context) throws AuthException {
|
|||
}
|
||||
|
||||
@Override
|
||||
public PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordInterface password) {
|
||||
return PasswordVerifyReport.FAILED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthManager.AuthReport createOAuthSession(User user, AuthResponse.AuthContext context, PasswordVerifyReport report, boolean minecraftAccess) throws IOException {
|
||||
return null;
|
||||
public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password, boolean minecraftAccess) throws IOException {
|
||||
throw new AuthException("Please configure AuthCoreProvider");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import pro.gravit.launcher.request.secure.HardwareReportRequest;
|
||||
import pro.gravit.launchserver.auth.core.User;
|
||||
import pro.gravit.launchserver.auth.core.UserSession;
|
||||
import pro.gravit.launchserver.auth.core.interfaces.UserHardware;
|
||||
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportHardware;
|
||||
import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider;
|
||||
|
@ -18,7 +19,7 @@ public interface AuthSupportHardware extends AuthSupport {
|
|||
|
||||
UserHardware createHardwareInfo(HardwareReportRequest.HardwareInfo info, byte[] publicKey);
|
||||
|
||||
void connectUserAndHardware(User user, UserHardware hardware);
|
||||
void connectUserAndHardware(UserSession userSession, UserHardware hardware);
|
||||
|
||||
void addPublicKeyToHardwareInfo(UserHardware hardware, byte[] publicKey);
|
||||
|
||||
|
|
|
@ -5,4 +5,9 @@ public class AcceptPasswordVerifier extends PasswordVerifier {
|
|||
public boolean check(String encryptedPassword, String password) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encrypt(String password) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,27 @@
|
|||
package pro.gravit.launchserver.auth.password;
|
||||
|
||||
import pro.gravit.launchserver.auth.core.JsonCoreProvider;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
|
||||
public class JsonPasswordVerifier extends PasswordVerifier {
|
||||
private static transient final Logger logger = LogManager.getLogger();
|
||||
private transient final HttpClient client = HttpClient.newBuilder().build();
|
||||
public String url;
|
||||
public String bearerToken;
|
||||
|
||||
@Override
|
||||
public boolean check(String encryptedPassword, String password) {
|
||||
JsonPasswordResponse response = JsonCoreProvider.jsonRequest(new JsonPasswordRequest(encryptedPassword, password), url, bearerToken, JsonPasswordResponse.class, client);
|
||||
JsonPasswordResponse response = jsonRequest(new JsonPasswordRequest(encryptedPassword, password), url, bearerToken, JsonPasswordResponse.class, client);
|
||||
if (response != null) {
|
||||
return response.success;
|
||||
}
|
||||
|
@ -31,4 +41,41 @@ public JsonPasswordRequest(String encryptedPassword, String password) {
|
|||
public static class JsonPasswordResponse {
|
||||
public boolean success;
|
||||
}
|
||||
|
||||
public static <T, R> R jsonRequest(T request, String url, String bearerToken, Class<R> clazz, HttpClient client) {
|
||||
HttpRequest.BodyPublisher publisher;
|
||||
if (request != null) {
|
||||
publisher = HttpRequest.BodyPublishers.ofString(Launcher.gsonManager.gson.toJson(request));
|
||||
} else {
|
||||
publisher = HttpRequest.BodyPublishers.noBody();
|
||||
}
|
||||
try {
|
||||
HttpRequest.Builder request1 = HttpRequest.newBuilder()
|
||||
.method("POST", publisher)
|
||||
.uri(new URI(url))
|
||||
.header("Content-Type", "application/json; charset=UTF-8")
|
||||
.header("Accept", "application/json")
|
||||
.timeout(Duration.ofMillis(10000));
|
||||
if (bearerToken != null) {
|
||||
request1.header("Authorization", "Bearer ".concat(bearerToken));
|
||||
}
|
||||
HttpResponse<InputStream> response = client.send(request1.build(), HttpResponse.BodyHandlers.ofInputStream());
|
||||
int statusCode = response.statusCode();
|
||||
if (200 > statusCode || statusCode > 300) {
|
||||
if (statusCode >= 500) {
|
||||
logger.error("JsonCoreProvider: {} return {}", url, statusCode);
|
||||
} else if (statusCode >= 300 && statusCode <= 400) {
|
||||
logger.error("JsonCoreProvider: {} return {}, try redirect to {}. Redirects not supported!", url, statusCode, response.headers().firstValue("Location").orElse("Unknown"));
|
||||
} else if (statusCode == 403 || statusCode == 401) {
|
||||
logger.error("JsonCoreProvider: {} return {}. Please set 'bearerToken'!", url, statusCode);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
try (Reader reader = new InputStreamReader(response.body())) {
|
||||
return Launcher.gsonManager.gson.fromJson(reader, clazz);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ public void onHardwareReport(HardwareReportResponse response, Client client) {
|
|||
} else {
|
||||
authSupportHardware.addPublicKeyToHardwareInfo(hardware, client.trustLevel.publicKey);
|
||||
}
|
||||
authSupportHardware.connectUserAndHardware(client.getUser(), hardware);
|
||||
authSupportHardware.connectUserAndHardware(client.sessionObject, hardware);
|
||||
if (hardware.isBanned()) {
|
||||
throw new SecurityException("Your hardware banned");
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ public VerifySecureLevelKeyRequestEvent onSuccessVerify(Client client) {
|
|||
throw new SecurityException("Your hardware banned");
|
||||
}
|
||||
client.trustLevel.hardwareInfo = hardware.getHardwareInfo();
|
||||
authSupportHardware.connectUserAndHardware(client.getUser(), hardware);
|
||||
authSupportHardware.connectUserAndHardware(client.sessionObject, hardware);
|
||||
} else if (provider == null) {
|
||||
logger.warn("HWIDProvider null. HardwareInfo not checked!");
|
||||
} else {
|
||||
|
|
|
@ -28,7 +28,7 @@ public void invoke(String... args) throws Exception {
|
|||
AuthProviderPair pair = args.length > 1 ? server.config.getAuthProviderPair(args[1]) : server.config.getAuthProviderPair();
|
||||
ClientProfile profile = null;
|
||||
for(ClientProfile p : server.getProfiles()) {
|
||||
if(p.getTitle().equals(args[0])) {
|
||||
if(p.getTitle().equals(args[0]) || p.getUUID().toString().equals(args[0])) {
|
||||
profile = p;
|
||||
break;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public void invoke(String... args) throws Exception {
|
|||
logger.error("AuthId {} not found", args[1]);
|
||||
return;
|
||||
}
|
||||
String token = server.authManager.newCheckServerToken(args[0], pair.name);
|
||||
String token = server.authManager.newCheckServerToken(profile != null ? profile.getUUID().toString() : args[0], pair.name);
|
||||
logger.info("Server token {} authId {}: {}", args[0], pair.name, token);
|
||||
}
|
||||
});
|
||||
|
@ -48,7 +48,7 @@ public void invoke(String... args) throws Exception {
|
|||
|
||||
@Override
|
||||
public String getArgsDescription() {
|
||||
return "[new/info/token name] [args]";
|
||||
return "[server/info/token name] [args]";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -192,7 +192,6 @@ public void init(LaunchServer.ReloadType type) {
|
|||
if (!type.equals(LaunchServer.ReloadType.NO_AUTH)) {
|
||||
for (AuthProviderPair pair : auth.values()) {
|
||||
server.registerObject("auth.".concat(pair.name).concat(".core"), pair.core);
|
||||
server.registerObject("auth.".concat(pair.name).concat(".social"), pair.social);
|
||||
server.registerObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider);
|
||||
}
|
||||
}
|
||||
|
@ -203,7 +202,6 @@ public void close(LaunchServer.ReloadType type) {
|
|||
try {
|
||||
if (!type.equals(LaunchServer.ReloadType.NO_AUTH)) {
|
||||
for (AuthProviderPair pair : auth.values()) {
|
||||
server.unregisterObject("auth.".concat(pair.name).concat(".social"), pair.social);
|
||||
server.unregisterObject("auth.".concat(pair.name).concat(".core"), pair.core);
|
||||
server.unregisterObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider);
|
||||
pair.close();
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
import pro.gravit.launchserver.auth.AuthException;
|
||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||
import pro.gravit.launchserver.auth.core.AuthCoreProvider;
|
||||
import pro.gravit.launchserver.auth.core.AuthSocialProvider;
|
||||
import pro.gravit.launchserver.auth.core.User;
|
||||
import pro.gravit.launchserver.auth.core.UserSession;
|
||||
import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportTextures;
|
||||
|
@ -31,7 +30,6 @@
|
|||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class AuthManager {
|
||||
private transient final LaunchServer server;
|
||||
|
@ -86,7 +84,7 @@ public boolean accept(Client client, AuthProviderPair pair, String extendedToken
|
|||
client.auth = server.config.getAuthProviderPair(info.authId);
|
||||
if(client.permissions == null) client.permissions = new ClientPermissions();
|
||||
client.permissions.addPerm("launchserver.checkserver");
|
||||
client.permissions.addPerm(String.format("launchserver.profiles.%s.show", info.serverName));
|
||||
client.permissions.addPerm(String.format("launchserver.profile.%s.show", info.serverName));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -143,62 +141,27 @@ public AuthReport auth(AuthResponse.AuthContext context, AuthRequest.AuthPasswor
|
|||
context.client.sessionObject = session;
|
||||
internalAuth(context.client, context.authType, context.pair, user.getUsername(), user.getUUID(), user.getPermissions(), true);
|
||||
if (context.authType == AuthResponse.ConnectTypes.CLIENT && server.config.protectHandler.allowGetAccessToken(context)) {
|
||||
return AuthReport.ofMinecraftAccessToken(user.getAccessToken());
|
||||
return AuthReport.ofMinecraftAccessToken(user.getAccessToken(), session);
|
||||
}
|
||||
return AuthReport.ofMinecraftAccessToken(null);
|
||||
return AuthReport.ofMinecraftAccessToken(null, session);
|
||||
}
|
||||
User user = null;
|
||||
boolean skipPasswordCheck = false;
|
||||
String login = context.login;
|
||||
if (context.pair.social != null) {
|
||||
AuthSocialProvider.SocialResult result = context.pair.social.preAuth(context, password);
|
||||
if (result != null) {
|
||||
if (result.user != null) user = result.user;
|
||||
if (result.login != null) login = result.login;
|
||||
if (result.password != null) password = result.password;
|
||||
if (result.user != null && result.password == null) skipPasswordCheck = true;
|
||||
}
|
||||
}
|
||||
if (user == null && login != null) {
|
||||
user = provider.getUserByLogin(context.login);
|
||||
if (user == null) {
|
||||
throw new AuthException(AuthRequestEvent.USER_NOT_FOUND_ERROR_MESSAGE);
|
||||
}
|
||||
}
|
||||
AuthCoreProvider.PasswordVerifyReport report = null;
|
||||
if (!skipPasswordCheck) {
|
||||
report = provider.verifyPassword(user, password);
|
||||
}
|
||||
if (skipPasswordCheck || report.success) {
|
||||
AuthReport result;
|
||||
try {
|
||||
result = provider.createOAuthSession(user, context, report, context.authType == AuthResponse.ConnectTypes.CLIENT && server.config.protectHandler.allowGetAccessToken(context));
|
||||
} catch (IOException e) {
|
||||
if (e instanceof AuthException) throw (AuthException) e;
|
||||
logger.error(e);
|
||||
try {
|
||||
AuthReport result = provider.authorize(login, context, password, context.authType == AuthResponse.ConnectTypes.CLIENT && server.config.protectHandler.allowGetAccessToken(context));
|
||||
if(result == null || result.session == null || result.session.getUser() == null) {
|
||||
logger.error("AuthCoreProvider {} method 'authorize' return null", context.pair.name);
|
||||
throw new AuthException("Internal Auth Error");
|
||||
}
|
||||
if (user == null) {
|
||||
if (result.session != null) {
|
||||
user = result.session.getUser();
|
||||
} else {
|
||||
logger.error("AuthCoreProvider {} method createOAuthSession returns null session with login null", context.pair.name);
|
||||
throw new AuthException("Internal Auth Error");
|
||||
}
|
||||
}
|
||||
var session = result.session;
|
||||
var user = session.getUser();
|
||||
context.client.coreObject = user;
|
||||
context.client.sessionObject = session;
|
||||
internalAuth(context.client, context.authType, context.pair, user.getUsername(), user.getUUID(), user.getPermissions(), result.isUsingOAuth());
|
||||
return result;
|
||||
} else {
|
||||
if (report.needMoreFactors) {
|
||||
if (report.factors.size() == 1 && report.factors.get(0) == -1) {
|
||||
throw new AuthException(AuthRequestEvent.TWO_FACTOR_NEED_ERROR_MESSAGE);
|
||||
}
|
||||
String message = AuthRequestEvent.ONE_FACTOR_NEED_ERROR_MESSAGE_PREFIX
|
||||
.concat(report.factors.stream().map(String::valueOf).collect(Collectors.joining(".")));
|
||||
throw new AuthException(message);
|
||||
}
|
||||
throw new AuthException(AuthRequestEvent.WRONG_PASSWORD_ERROR_MESSAGE);
|
||||
} catch (IOException e) {
|
||||
if (e instanceof AuthException) throw (AuthException) e;
|
||||
logger.error(e);
|
||||
throw new AuthException("Internal Auth Error");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,7 +180,6 @@ public void internalAuth(Client client, AuthResponse.ConnectTypes authType, Auth
|
|||
client.type = authType;
|
||||
client.uuid = uuid;
|
||||
client.useOAuth = oauth;
|
||||
client.coreObject = pair.core.getUserByUUID(uuid);
|
||||
}
|
||||
|
||||
public CheckServerReport checkServer(Client client, String username, String serverID) throws IOException {
|
||||
|
@ -374,24 +336,16 @@ public record AuthReport(String minecraftAccessToken, String oauthAccessToken,
|
|||
String oauthRefreshToken, long oauthExpire,
|
||||
UserSession session) {
|
||||
|
||||
public static AuthReport ofOAuth(String oauthAccessToken, String oauthRefreshToken, long oauthExpire) {
|
||||
return new AuthReport(null, oauthAccessToken, oauthRefreshToken, oauthExpire, null);
|
||||
}
|
||||
|
||||
public static AuthReport ofOAuth(String oauthAccessToken, String oauthRefreshToken, long oauthExpire, UserSession session) {
|
||||
return new AuthReport(null, oauthAccessToken, oauthRefreshToken, oauthExpire, session);
|
||||
}
|
||||
|
||||
public static AuthReport ofOAuthWithMinecraft(String minecraftAccessToken, String oauthAccessToken, String oauthRefreshToken, long oauthExpire) {
|
||||
return new AuthReport(minecraftAccessToken, oauthAccessToken, oauthRefreshToken, oauthExpire, null);
|
||||
}
|
||||
|
||||
public static AuthReport ofOAuthWithMinecraft(String minecraftAccessToken, String oauthAccessToken, String oauthRefreshToken, long oauthExpire, UserSession session) {
|
||||
return new AuthReport(minecraftAccessToken, oauthAccessToken, oauthRefreshToken, oauthExpire, session);
|
||||
}
|
||||
|
||||
public static AuthReport ofMinecraftAccessToken(String minecraftAccessToken) {
|
||||
return new AuthReport(minecraftAccessToken, null, null, 0, null);
|
||||
public static AuthReport ofMinecraftAccessToken(String minecraftAccessToken, UserSession session) {
|
||||
return new AuthReport(minecraftAccessToken, null, null, 0, session);
|
||||
}
|
||||
|
||||
public boolean isUsingOAuth() {
|
||||
|
|
|
@ -36,9 +36,14 @@ public class Client {
|
|||
|
||||
public Map<String, String> serializableProperties;
|
||||
|
||||
public transient AtomicInteger refCount = new AtomicInteger(1);
|
||||
public transient AtomicInteger refCount;
|
||||
|
||||
public Client(UUID session) {
|
||||
this(session, 1);
|
||||
}
|
||||
|
||||
public Client(UUID session, int initialRefCount) {
|
||||
refCount = new AtomicInteger(initialRefCount);
|
||||
this.session = session;
|
||||
timestamp = System.currentTimeMillis();
|
||||
type = null;
|
||||
|
|
|
@ -76,9 +76,9 @@ public static class AuthContext {
|
|||
public final String profileName;
|
||||
public final String ip;
|
||||
public final ConnectTypes authType;
|
||||
public final Client client;
|
||||
public final AuthProviderPair pair;
|
||||
public AuthManager.AuthReport report;
|
||||
public transient final Client client;
|
||||
public transient final AuthProviderPair pair;
|
||||
public transient AuthManager.AuthReport report;
|
||||
|
||||
public AuthContext(Client client, String login, String profileName, String ip, ConnectTypes authType, AuthProviderPair pair) {
|
||||
this.client = client;
|
||||
|
|
|
@ -45,7 +45,7 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
|||
sendError("Exit internal error");
|
||||
return;
|
||||
}
|
||||
Client newClient = new Client(null);
|
||||
Client newClient = new Client(null, 0);
|
||||
newClient.checkSign = client.checkSign;
|
||||
handler.setClient(newClient);
|
||||
AuthSupportExit supportExit = client.auth.core.isSupport(AuthSupportExit.class);
|
||||
|
|
|
@ -20,7 +20,7 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
|||
List<GetAvailabilityAuthRequestEvent.AuthAvailability> list = new ArrayList<>();
|
||||
for (AuthProviderPair pair : server.config.auth.values()) {
|
||||
list.add(new GetAvailabilityAuthRequestEvent.AuthAvailability(pair.name, pair.displayName,
|
||||
pair.isUseSocial() ? pair.social.getDetails(client) : pair.core.getDetails(client)));
|
||||
pair.core.getDetails(client)));
|
||||
}
|
||||
sendResult(new GetAvailabilityAuthRequestEvent(list));
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ public final class Version implements Comparable<Version> {
|
|||
|
||||
public static final int MAJOR = 5;
|
||||
public static final int MINOR = 2;
|
||||
public static final int PATCH = 4;
|
||||
public static final int BUILD = 2;
|
||||
public static final int PATCH = 5;
|
||||
public static final int BUILD = 1;
|
||||
public static final Version.Type RELEASE = Type.STABLE;
|
||||
public final int major;
|
||||
public final int minor;
|
||||
|
|
|
@ -163,7 +163,7 @@ public void run(String... args) throws Throwable {
|
|||
LogHelper.error(e);
|
||||
}
|
||||
};
|
||||
LogHelper.info("ServerWrapper: Project %s, LaunchServer address: %s. Title: %s", config.projectname, config.address, Launcher.profile != null ? Launcher.profile.getTitle() : "unknown");
|
||||
LogHelper.info("ServerWrapper: LaunchServer address: %s. Title: %s", 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("Start Minecraft Server");
|
||||
LogHelper.debug("Invoke main method %s", mainClass.getName());
|
||||
|
@ -181,8 +181,7 @@ public void run(String... args) throws Throwable {
|
|||
}
|
||||
|
||||
public void updateLauncherConfig() {
|
||||
|
||||
LauncherConfig cfg = new LauncherConfig(config.address, null, null, new HashMap<>(), config.projectname);
|
||||
LauncherConfig cfg = new LauncherConfig(config.address, null, null, new HashMap<>(), "ServerWrapper");
|
||||
Launcher.setConfig(cfg);
|
||||
}
|
||||
|
||||
|
@ -200,7 +199,6 @@ public void setConfig(Config config) {
|
|||
public Config getDefaultConfig() {
|
||||
Config newConfig = new Config();
|
||||
newConfig.serverName = "your server name";
|
||||
newConfig.projectname = "MineCraft";
|
||||
newConfig.mainclass = "";
|
||||
newConfig.extendedTokens = new HashMap<>();
|
||||
newConfig.args = new ArrayList<>();
|
||||
|
@ -211,6 +209,7 @@ public Config getDefaultConfig() {
|
|||
}
|
||||
|
||||
public static final class Config {
|
||||
@Deprecated
|
||||
public String projectname;
|
||||
public String address;
|
||||
public String serverName;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
id 'org.openjfx.javafxplugin' version '0.0.10' apply false
|
||||
}
|
||||
group = 'pro.gravit.launcher'
|
||||
version = '5.2.4'
|
||||
version = '5.2.5'
|
||||
|
||||
apply from: 'props.gradle'
|
||||
|
||||
|
|
2
modules
2
modules
|
@ -1 +1 @@
|
|||
Subproject commit fd75e8dfa26a3103f03e4e6e6e3eb1c6e6a4ba1a
|
||||
Subproject commit dced154854c59d8b1e816ebfb1f51baaaeafabfb
|
Loading…
Reference in a new issue