begin oauth2 setup

This commit is contained in:
Taah 2024-03-05 19:41:08 -08:00
parent ff9cf12acc
commit 2e40ddc6bc
8 changed files with 252 additions and 16 deletions

View File

@ -1,35 +1,26 @@
package dev.plex; package dev.plex;
import dev.plex.authentication.AuthenticationManager;
import dev.plex.cache.FileCache; import dev.plex.cache.FileCache;
import dev.plex.config.ModuleConfig; import dev.plex.config.ModuleConfig;
import dev.plex.module.PlexModule; import dev.plex.module.PlexModule;
import dev.plex.request.AbstractServlet; import dev.plex.request.AbstractServlet;
import dev.plex.request.SchematicUploadServlet; import dev.plex.request.SchematicUploadServlet;
import dev.plex.request.impl.CommandsEndpoint; import dev.plex.request.impl.*;
import dev.plex.request.impl.IndefBansEndpoint;
import dev.plex.request.impl.IndexEndpoint;
import dev.plex.request.impl.ListEndpoint;
import dev.plex.request.impl.PunishmentsEndpoint;
import dev.plex.request.impl.SchematicDownloadEndpoint;
import dev.plex.request.impl.SchematicUploadEndpoint;
import dev.plex.util.PlexLog; import dev.plex.util.PlexLog;
import jakarta.servlet.MultipartConfigElement; import jakarta.servlet.MultipartConfigElement;
import java.io.File;
import java.util.concurrent.atomic.AtomicReference;
import lombok.Getter; import lombok.Getter;
import net.milkbowl.vault.permission.Permission; import net.milkbowl.vault.permission.Permission;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.RegisteredServiceProvider;
import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import java.io.File;
import java.util.concurrent.atomic.AtomicReference;
public class HTTPDModule extends PlexModule public class HTTPDModule extends PlexModule
{ {
public static ServletContextHandler context; public static ServletContextHandler context;
@ -45,6 +36,8 @@ public class HTTPDModule extends PlexModule
public static final String template = AbstractServlet.readFileReal(HTTPDModule.class.getResourceAsStream("/httpd/template.html")); public static final String template = AbstractServlet.readFileReal(HTTPDModule.class.getResourceAsStream("/httpd/template.html"));
private AuthenticationManager authenticationManager;
@Override @Override
public void load() public void load()
{ {
@ -61,6 +54,18 @@ public class HTTPDModule extends PlexModule
{ {
throw new RuntimeException("Plex-HTTPD requires the 'Vault' plugin as well as a Permissions plugin that hooks into 'Vault'. We recommend LuckPerms!"); throw new RuntimeException("Plex-HTTPD requires the 'Vault' plugin as well as a Permissions plugin that hooks into 'Vault'. We recommend LuckPerms!");
} }
this.authenticationManager = new AuthenticationManager();
if (this.authenticationManager.provider() != null)
{
PlexLog.debug(this.authenticationManager.provider().generateLogin());
}
else
{
PlexLog.debug("Provider was not found for Authentication so disabled");
}
serverThread = new Thread(() -> serverThread = new Thread(() ->
{ {
Server server = new Server(); Server server = new Server();

View File

@ -0,0 +1,24 @@
package dev.plex.authentication;
import com.google.common.collect.Lists;
import lombok.Data;
import lombok.experimental.Accessors;
import java.time.ZonedDateTime;
import java.util.LinkedList;
import java.util.List;
/**
* @author Taah
* @since 6:37 PM [03-05-2024]
*/
@Data
@Accessors(fluent = true)
public class AuthenticatedUser
{
private final String ip;
private final ZonedDateTime lastAuthenticated;
private final LinkedList<String> roles = Lists.newLinkedList();
private final UserType userType = UserType.UNKNOWN;
}

View File

@ -0,0 +1,57 @@
package dev.plex.authentication;
import dev.plex.HTTPDModule;
import dev.plex.authentication.impl.DiscordOAuth2Provider;
import dev.plex.util.PlexLog;
import org.apache.commons.lang3.NotImplementedException;
/**
* @author Taah
* @since 7:08 PM [03-05-2024]
*/
public class AuthenticationManager
{
private final OAuth2Provider provider;
public AuthenticationManager()
{
final boolean enabled = HTTPDModule.moduleConfig.getBoolean("authentication.enabled", false);
if (!enabled)
{
provider = null;
return;
}
PlexLog.debug("[HTTPD] Auth is enabled");
final String providerName = HTTPDModule.moduleConfig.getString("authentication.provider.name", "");
if (providerName.isEmpty())
{
PlexLog.error("OAuth2 Authentication is enabled but no provider was given!");
provider = null;
return;
}
PlexLog.debug("[HTTPD] Provider name is {0}", providerName);
switch (providerName.toLowerCase())
{
case "discord" -> {
provider = new DiscordOAuth2Provider();
}
case "xenforo" -> {
throw new NotImplementedException("XenForo OAuth2 is not implemented yet!");
}
default -> {
provider = null;
}
}
PlexLog.log("Using {0} provider for authentication", providerName);
}
public OAuth2Provider provider()
{
return this.provider;
}
}

View File

@ -0,0 +1,21 @@
package dev.plex.authentication;
import org.eclipse.jetty.server.Response;
import java.util.HashMap;
/**
* @author Taah
* @since 6:36 PM [03-05-2024]
*/
public interface OAuth2Provider
{
HashMap<String, AuthenticatedUser> sessions();
AuthenticatedUser login(Response response, UserType type);
String[] roles(AuthenticatedUser user);
String generateLogin();
}

View File

@ -0,0 +1,10 @@
package dev.plex.authentication;
/**
* @author Taah
* @since 6:37 PM [03-05-2024]
*/
public enum UserType
{
DISCORD, UNKNOWN
}

View File

@ -0,0 +1,81 @@
package dev.plex.authentication.impl;
import com.google.common.collect.Maps;
import dev.plex.HTTPDModule;
import dev.plex.authentication.AuthenticatedUser;
import dev.plex.authentication.OAuth2Provider;
import dev.plex.authentication.UserType;
import dev.plex.util.PlexLog;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.server.Response;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
/**
* @author Taah
* @since 6:41 PM [03-05-2024]
*/
public class DiscordOAuth2Provider implements OAuth2Provider
{
private final HashMap<String, AuthenticatedUser> sessions = Maps.newHashMap();
private final String token;
private final String clientId;
private final String redirectUri;
public DiscordOAuth2Provider()
{
token = System.getenv("BOT_TOKEN").isEmpty() ? HTTPDModule.moduleConfig.getString("authentication.provider.discord.token", System.getProperty("BOT_TOKEN", "")) : System.getenv("BOT_TOKEN");
clientId = HTTPDModule.moduleConfig.getString("authentication.provider.discord.clientId", "");
redirectUri = URLEncoder.encode(HTTPDModule.moduleConfig.getString("authentication.provider.redirectUri", ""), StandardCharsets.UTF_8);
PlexLog.debug("[HTTPD] Client ID: {0}, Redirect URL: {1}", clientId, redirectUri);
if (redirectUri.isEmpty())
{
PlexLog.error("Provided authentication redirect url was empty for HTTPD!");
return;
}
if (token.isEmpty())
{
PlexLog.error("Provided discord authentication token was empty for HTTPD!");
return;
}
if (clientId.isEmpty())
{
PlexLog.error("Provided discord client ID was empty for HTTPD!");
}
}
@Override
public HashMap<String, AuthenticatedUser> sessions()
{
return sessions;
}
@Override
public AuthenticatedUser login(Response response, UserType type)
{
return null;
}
@Override
public String[] roles(AuthenticatedUser user)
{
return new String[0];
}
@Override
public String generateLogin()
{
return String.format("https://discord.com/oauth2/authorize?client_id=%s&scope=%s&redirect_uri=%s",
clientId,
"identify%20guilds%20guilds.members.read",
redirectUri);
}
}

View File

@ -0,0 +1,27 @@
package dev.plex.request.impl;
import dev.plex.command.PlexCommand;
import dev.plex.command.annotation.CommandPermissions;
import dev.plex.request.AbstractServlet;
import dev.plex.request.GetMapping;
import dev.plex.util.PlexLog;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandMap;
import org.bukkit.command.PluginIdentifiableCommand;
import java.util.*;
public class AuthenticationEndpoint extends AbstractServlet
{
@GetMapping(endpoint = "/oauth2")
public String login(HttpServletRequest request, HttpServletResponse response)
{
// TODO: Nuh uh
return "";
}
}

View File

@ -1,4 +1,15 @@
server: server:
bind-address: 0.0.0.0 bind-address: 0.0.0.0
port: 27192 port: 27192
logging: false logging: false
authentication:
enabled: false
# Providers: discord
provider:
name: discord
redirectUri: ""
discord: # Fill if using discord provider
clientId: ""
token: "" # Can also use environment variable or system property BOT_TOKEN