[FEATURE] AuthCoreProvider: OAuth Support Part 1

This commit is contained in:
Gravita 2021-05-23 02:46:31 +07:00
parent f317912de7
commit b919020988
4 changed files with 100 additions and 31 deletions

View file

@ -11,6 +11,7 @@
import pro.gravit.launchserver.Reconfigurable;
import pro.gravit.launchserver.auth.AuthException;
import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportGetAllUsers;
import pro.gravit.launchserver.manangers.AuthManager;
import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
import pro.gravit.utils.ProviderMap;
@ -41,11 +42,13 @@ public static void registerProviders() {
}
public abstract User getUserByUsername(String username);
public abstract User getUserByUUID(UUID uuid);
public abstract User getUserByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired;
public abstract AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context /* may be null */);
public abstract void verifyAuth(AuthResponse.AuthContext context) throws AuthException;
public abstract PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordInterface password);
public abstract AuthManager.AuthReport createOAuthSession(User user, AuthResponse.AuthContext context /* may be null */, PasswordVerifyReport report /* may be null */, boolean minecraftAccess) throws IOException;
public abstract void init(LaunchServer server);
// Auth Handler methods
protected abstract boolean updateAuth(User user, String accessToken) throws IOException;
protected abstract boolean updateServerID(User user, String serverID) throws IOException;
public List<GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails> getDetails(Client client) {
@ -125,7 +128,6 @@ public static class PasswordVerifyReport {
public final boolean success;
public final boolean needMoreFactor;
public final List<Integer> factors;
public final String accessToken;
public static final PasswordVerifyReport REQUIRED_2FA = new PasswordVerifyReport(-1);
public static final PasswordVerifyReport FAILED = new PasswordVerifyReport(false);
@ -133,28 +135,37 @@ public PasswordVerifyReport(boolean success) {
this.success = success;
this.needMoreFactor = false;
this.factors = List.of();
this.accessToken = SecurityHelper.randomStringToken();
}
public PasswordVerifyReport(String accessToken) {
this.success = true;
this.needMoreFactor = false;
this.factors = List.of();
this.accessToken = accessToken;
}
public PasswordVerifyReport(int nextFactor) {
this.success = false;
this.needMoreFactor = true;
this.factors = List.of(nextFactor);
this.accessToken = null;
}
public PasswordVerifyReport(List<Integer> factors) {
this.success = false;
this.needMoreFactor = false;
this.factors = Collections.unmodifiableList(factors);
this.accessToken = null;
}
private PasswordVerifyReport(boolean success, boolean needMoreFactor, List<Integer> factors) {
this.success = success;
this.needMoreFactor = needMoreFactor;
this.factors = factors;
}
}
public static class OAuthAccessTokenExpired extends Exception {
public OAuthAccessTokenExpired() {
}
public OAuthAccessTokenExpired(String message) {
super(message);
}
public OAuthAccessTokenExpired(String message, Throwable cause) {
super(message, cause);
}
}
}

View file

@ -9,7 +9,9 @@
import pro.gravit.launchserver.auth.AuthException;
import pro.gravit.launchserver.auth.MySQLSourceConfig;
import pro.gravit.launchserver.auth.password.PasswordVerifier;
import pro.gravit.launchserver.manangers.AuthManager;
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
import pro.gravit.utils.helper.SecurityHelper;
import java.io.IOException;
import java.sql.Connection;
@ -56,6 +58,16 @@ public User getUserByUUID(UUID uuid) {
}
}
@Override
public User getUserByOAuthAccessToken(String accessToken) {
return null;
}
@Override
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
return null;
}
@Override
public void verifyAuth(AuthResponse.AuthContext context) throws AuthException {
@ -70,6 +82,17 @@ public PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordIn
}
}
@Override
public AuthManager.AuthReport createOAuthSession(User user, AuthResponse.AuthContext context, PasswordVerifyReport report, boolean minecraftAccess) throws IOException {
if(minecraftAccess) {
String minecraftAccessToken = SecurityHelper.randomStringToken();
updateAuth(user, minecraftAccessToken);
return AuthManager.AuthReport.ofMinecraftAccessToken(minecraftAccessToken);
} else {
return AuthManager.AuthReport.ofMinecraftAccessToken(null);
}
}
@Override
public void init(LaunchServer server) {
if (mySQLHolder == null) logger.error("mySQLHolder cannot be null");
@ -90,7 +113,6 @@ public void init(LaunchServer server) {
table, serverIDColumn, uuidColumn);
}
@Override
protected boolean updateAuth(User user, String accessToken) throws IOException {
try (Connection c = mySQLHolder.getConnection()) {
PreparedStatement s = c.prepareStatement(updateAuthSQL);

View file

@ -3,6 +3,7 @@
import pro.gravit.launcher.request.auth.AuthRequest;
import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.AuthException;
import pro.gravit.launchserver.manangers.AuthManager;
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
import java.io.IOException;
@ -19,6 +20,16 @@ public User getUserByUUID(UUID uuid) {
return null;
}
@Override
public User getUserByOAuthAccessToken(String accessToken) {
return null;
}
@Override
public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthResponse.AuthContext context) {
return null;
}
@Override
public void verifyAuth(AuthResponse.AuthContext context) throws AuthException {
throw new AuthException("Please configure AuthCoreProvider");
@ -30,13 +41,13 @@ public PasswordVerifyReport verifyPassword(User user, AuthRequest.AuthPasswordIn
}
@Override
public void init(LaunchServer server) {
public AuthManager.AuthReport createOAuthSession(User user, AuthResponse.AuthContext context, PasswordVerifyReport report, boolean minecraftAccess) throws IOException {
return null;
}
@Override
protected boolean updateAuth(User user, String accessToken) throws IOException {
return false;
public void init(LaunchServer server) {
}
@Override

View file

@ -16,7 +16,6 @@
import pro.gravit.launchserver.auth.provider.AuthProviderResult;
import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
import pro.gravit.launchserver.socket.response.profile.ProfileByUUIDResponse;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.SecurityHelper;
@ -63,26 +62,52 @@ public void check(AuthResponse.AuthContext context) throws AuthException {
}
}
public static class AuthReport {
public final String minecraftAccessToken;
public final String oauthAccessToken;
public final String oauthRefreshToken;
public final long oauthExpire;
private AuthReport(String minecraftAccessToken, String oauthAccessToken, String oauthRefreshToken, long oauthExpire) {
this.minecraftAccessToken = minecraftAccessToken;
this.oauthAccessToken = oauthAccessToken;
this.oauthRefreshToken = oauthRefreshToken;
this.oauthExpire = oauthExpire;
}
public static AuthReport ofOAuth(String oauthAccessToken, String oauthRefreshToken, long oauthExpire) {
return new AuthReport(null, oauthAccessToken, oauthRefreshToken, oauthExpire);
}
public static AuthReport ofOAuthWithMinecraft(String minecraftAccessToken, String oauthAccessToken, String oauthRefreshToken, long oauthExpire) {
return new AuthReport(minecraftAccessToken, oauthAccessToken, oauthRefreshToken, oauthExpire);
}
public static AuthReport ofMinecraftAccessToken(String minecraftAccessToken) {
return new AuthReport(minecraftAccessToken, null, null, 0);
}
}
/**
* Full client authorization with password verification
* @param context AuthContext
* @param password User password
* @return Access token
*/
public String auth(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException {
public AuthReport auth(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException {
AuthProviderPair pair = context.pair;
String accessToken;
AuthReport report;
if(pair.core == null) {
try {
accessToken = authWithProviderAndHandler(context, password);
report = AuthReport.ofMinecraftAccessToken(authWithProviderAndHandler(context, password));
} catch (Exception e) {
if(e instanceof AuthException) throw (AuthException) e;
throw new AuthException("Internal Auth Error. Please contact administrator");
}
} else {
accessToken = authWithCore(context, password);
report = authWithCore(context, password);
}
return accessToken;
return report;
}
@SuppressWarnings("deprecation")
@ -106,7 +131,7 @@ private String authWithProviderAndHandler(AuthResponse.AuthContext context, Auth
return accessToken;
}
private String authWithCore(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException {
private AuthReport authWithCore(AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password) throws AuthException {
AuthCoreProvider provider = context.pair.core;
provider.verifyAuth(context);
User user = provider.getUserByUsername(context.login);
@ -115,17 +140,17 @@ private String authWithCore(AuthResponse.AuthContext context, AuthRequest.AuthPa
}
AuthCoreProvider.PasswordVerifyReport report = provider.verifyPassword(user, password);
if(report.success) {
String accessToken;
UUID uuid = user.getUUID();
if(context.authType == AuthResponse.ConnectTypes.CLIENT && server.config.protectHandler.allowGetAccessToken(context)) {
provider.verifyAuth(context);
accessToken = report.accessToken;
} else {
accessToken = null;
AuthReport result;
try {
result = provider.createOAuthSession(user, context, report, context.authType == AuthResponse.ConnectTypes.CLIENT && server.config.protectHandler.allowGetAccessToken(context));
} catch (IOException e) {
logger.error(e);
throw new AuthException("Internal Auth Error");
}
context.client.coreObject = user;
internalAuth(context.client, context.authType, context.pair, user.getUsername(), uuid, user.getPermissions());
return accessToken;
return result;
}
else {
if(report.needMoreFactor) {