Bladeren bron

Added authelia support

Toby Chui 2 maanden geleden
bovenliggende
commit
a86aa8cb26

+ 4 - 16
api.go

@@ -77,21 +77,9 @@ func RegisterTLSAPIs(authRouter *auth.RouterDef) {
 	authRouter.HandleFunc("/api/cert/delete", handleCertRemove)
 }
 
-// Register the APIs for SSO and Oauth functions, WIP
-func RegisterSSOAPIs(authRouter *auth.RouterDef) {
-	authRouter.HandleFunc("/api/sso/status", ssoHandler.HandleSSOStatus)
-	authRouter.HandleFunc("/api/sso/enable", ssoHandler.HandleSSOEnable)
-	authRouter.HandleFunc("/api/sso/setPort", ssoHandler.HandlePortChange)
-	authRouter.HandleFunc("/api/sso/setAuthURL", ssoHandler.HandleSetAuthURL)
-
-	authRouter.HandleFunc("/api/sso/app/register", ssoHandler.HandleRegisterApp)
-	//authRouter.HandleFunc("/api/sso/app/list", ssoHandler.HandleListApp)
-	//authRouter.HandleFunc("/api/sso/app/remove", ssoHandler.HandleRemoveApp)
-
-	authRouter.HandleFunc("/api/sso/user/list", ssoHandler.HandleListUser)
-	authRouter.HandleFunc("/api/sso/user/add", ssoHandler.HandleAddUser)
-	authRouter.HandleFunc("/api/sso/user/edit", ssoHandler.HandleEditUser)
-	authRouter.HandleFunc("/api/sso/user/remove", ssoHandler.HandleRemoveUser)
+// Register the APIs for Authentication handlers like Authelia and OAUTH2
+func RegisterAuthenticationHandlerAPIs(authRouter *auth.RouterDef) {
+	authRouter.HandleFunc("/api/sso/Authelia", autheliaRouter.HandleSetAutheliaURLAndHTTPS)
 }
 
 // Register the APIs for redirection rules management functions
@@ -339,7 +327,7 @@ func initAPIs(targetMux *http.ServeMux) {
 	RegisterAuthAPIs(requireAuth, targetMux)
 	RegisterHTTPProxyAPIs(authRouter)
 	RegisterTLSAPIs(authRouter)
-	//RegisterSSOAPIs(authRouter)
+	RegisterAuthenticationHandlerAPIs(authRouter)
 	RegisterRedirectionAPIs(authRouter)
 	RegisterAccessRuleAPIs(authRouter)
 	RegisterPathRuleAPIs(authRouter)

+ 5 - 3
def.go

@@ -16,7 +16,7 @@ import (
 	"imuslab.com/zoraxy/mod/access"
 	"imuslab.com/zoraxy/mod/acme"
 	"imuslab.com/zoraxy/mod/auth"
-	"imuslab.com/zoraxy/mod/auth/sso"
+	"imuslab.com/zoraxy/mod/auth/sso/authelia"
 	"imuslab.com/zoraxy/mod/database"
 	"imuslab.com/zoraxy/mod/dockerux"
 	"imuslab.com/zoraxy/mod/dynamicproxy/loadbalance"
@@ -43,7 +43,7 @@ const (
 	/* Build Constants */
 	SYSTEM_NAME       = "Zoraxy"
 	SYSTEM_VERSION    = "3.1.5"
-	DEVELOPMENT_BUILD = false /* Development: Set to false to use embedded web fs */
+	DEVELOPMENT_BUILD = true /* Development: Set to false to use embedded web fs */
 
 	/* System Constants */
 	DATABASE_PATH              = "sys.db"
@@ -128,7 +128,9 @@ var (
 	staticWebServer    *webserv.WebServer        //Static web server for hosting simple stuffs
 	forwardProxy       *forwardproxy.Handler     //HTTP Forward proxy, basically VPN for web browser
 	loadBalancer       *loadbalance.RouteManager //Global scope loadbalancer, store the state of the lb routing
-	ssoHandler         *sso.SSOHandler           //Single Sign On handler
+
+	//Authentication Provider
+	autheliaRouter *authelia.AutheliaRouter //Authelia router for Authelia authentication
 
 	//Helper modules
 	EmailSender       *email.Sender         //Email sender that handle email sending

+ 0 - 0
mod/auth/sso/app.go → deprecated/sso_old/app.go


+ 0 - 0
mod/auth/sso/handlers.go → deprecated/sso_old/handlers.go


+ 1 - 1
mod/auth/sso/oauth2.go → deprecated/sso_old/oauth2server.go

@@ -1,4 +1,4 @@
-package sso
+package oauth2server
 
 import (
 	"context"

+ 0 - 0
mod/auth/sso/oauth_test.go → deprecated/sso_old/oauth_test.go


+ 0 - 0
mod/auth/sso/openid.go → deprecated/sso_old/openid.go


+ 0 - 0
mod/auth/sso/server.go → deprecated/sso_old/server.go


+ 0 - 0
mod/auth/sso/sso.go → deprecated/sso_old/sso.go


+ 0 - 0
mod/auth/sso/static/auth.html → deprecated/sso_old/static/auth.html


+ 0 - 0
mod/auth/sso/static/index.html → deprecated/sso_old/static/index.html


+ 0 - 0
mod/auth/sso/static/login.html → deprecated/sso_old/static/login.html


+ 0 - 0
mod/auth/sso/userHandlers.go → deprecated/sso_old/userHandlers.go


+ 0 - 0
mod/auth/sso/users.go → deprecated/sso_old/users.go


+ 70 - 21
mod/auth/sso/authelia/authelia.go

@@ -1,50 +1,99 @@
 package authelia
 
 import (
+	"encoding/json"
 	"errors"
 	"fmt"
 	"net/http"
 	"net/url"
 
-	"imuslab.com/zoraxy/mod/dynamicproxy"
+	"imuslab.com/zoraxy/mod/database"
 	"imuslab.com/zoraxy/mod/info/logger"
+	"imuslab.com/zoraxy/mod/utils"
 )
 
-type Options struct {
-	AutheliaURL string //URL of the Authelia server, e.g. authelia.example.com
-	UseHTTPS    bool   //Whether to use HTTPS for the Authelia server
-	Logger      logger.Logger
+type AutheliaRouterOptions struct {
+	UseHTTPS    bool   //If the Authelia server is using HTTPS
+	AutheliaURL string //The URL of the Authelia server
+	Logger      *logger.Logger
+	Database    *database.Database
 }
 
-type AutheliaHandler struct {
-	options *Options
+type AutheliaRouter struct {
+	options *AutheliaRouterOptions
 }
 
-func NewAutheliaAuthenticator(options *Options) *AutheliaHandler {
-	return &AutheliaHandler{
+// NewAutheliaRouter creates a new AutheliaRouter object
+func NewAutheliaRouter(options *AutheliaRouterOptions) *AutheliaRouter {
+	options.Database.NewTable("authelia")
+
+	//Read settings from database, if exists
+	options.Database.Read("authelia", "autheliaURL", &options.AutheliaURL)
+	options.Database.Read("authelia", "useHTTPS", &options.UseHTTPS)
+
+	return &AutheliaRouter{
 		options: options,
 	}
 }
 
-// HandleAutheliaAuthRouting is the handler for Authelia authentication, if the error is not nil, the request will be forwarded to the endpoint
-// Do not continue processing or write to the response writer if the error is not nil
-func (h *AutheliaHandler) HandleAutheliaAuthRouting(w http.ResponseWriter, r *http.Request, pe *dynamicproxy.ProxyEndpoint) error {
-	err := h.handleAutheliaAuth(w, r)
-	if err != nil {
-		return nil
+// HandleSetAutheliaURLAndHTTPS is the internal handler for setting the Authelia URL and HTTPS
+func (ar *AutheliaRouter) HandleSetAutheliaURLAndHTTPS(w http.ResponseWriter, r *http.Request) {
+	if r.Method == http.MethodGet {
+		//Return the current settings
+		js, _ := json.Marshal(map[string]interface{}{
+			"useHTTPS":    ar.options.UseHTTPS,
+			"autheliaURL": ar.options.AutheliaURL,
+		})
+
+		utils.SendJSONResponse(w, string(js))
+		return
+	} else if r.Method == http.MethodPost {
+		//Update the settings
+		autheliaURL, err := utils.PostPara(r, "autheliaURL")
+		if err != nil {
+			utils.SendErrorResponse(w, "autheliaURL not found")
+			return
+		}
+
+		useHTTPS, err := utils.PostBool(r, "useHTTPS")
+		if err != nil {
+			useHTTPS = false
+		}
+
+		//Write changes to runtime
+		ar.options.AutheliaURL = autheliaURL
+		ar.options.UseHTTPS = useHTTPS
+
+		//Write changes to database
+		ar.options.Database.Write("authelia", "autheliaURL", autheliaURL)
+		ar.options.Database.Write("authelia", "useHTTPS", useHTTPS)
+
+		utils.SendOK(w)
+	} else {
+		http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
+		return
 	}
-	return err
+
 }
 
-func (h *AutheliaHandler) handleAutheliaAuth(w http.ResponseWriter, r *http.Request) error {
+// handleAutheliaAuth is the internal handler for Authelia authentication
+// Set useHTTPS to true if your authelia server is using HTTPS
+// Set autheliaURL to the URL of the Authelia server, e.g. authelia.example.com
+func (ar *AutheliaRouter) HandleAutheliaAuth(w http.ResponseWriter, r *http.Request) error {
 	client := &http.Client{}
 
+	if ar.options.AutheliaURL == "" {
+		ar.options.Logger.PrintAndLog("Authelia", "Authelia URL not set", nil)
+		w.WriteHeader(500)
+		w.Write([]byte("500 - Internal Server Error: Authelia URL not set"))
+		return errors.New("authelia URL not set")
+	}
 	protocol := "http"
-	if h.options.UseHTTPS {
+	if ar.options.UseHTTPS {
 		protocol = "https"
 	}
 
-	autheliaBaseURL := protocol + "://" + h.options.AutheliaURL
+	autheliaBaseURL := protocol + "://" + ar.options.AutheliaURL
 	//Remove tailing slash if any
 	if autheliaBaseURL[len(autheliaBaseURL)-1] == '/' {
 		autheliaBaseURL = autheliaBaseURL[:len(autheliaBaseURL)-1]
@@ -53,7 +102,7 @@ func (h *AutheliaHandler) handleAutheliaAuth(w http.ResponseWriter, r *http.Requ
 	//Make a request to Authelia to verify the request
 	req, err := http.NewRequest("POST", autheliaBaseURL+"/api/verify", nil)
 	if err != nil {
-		h.options.Logger.PrintAndLog("Authelia", "Unable to create request", err)
+		ar.options.Logger.PrintAndLog("Authelia", "Unable to create request", err)
 		w.WriteHeader(401)
 		return errors.New("unauthorized")
 	}
@@ -72,7 +121,7 @@ func (h *AutheliaHandler) handleAutheliaAuth(w http.ResponseWriter, r *http.Requ
 	// Making the verification request
 	resp, err := client.Do(req)
 	if err != nil {
-		h.options.Logger.PrintAndLog("Authelia", "Unable to verify", err)
+		ar.options.Logger.PrintAndLog("Authelia", "Unable to verify", err)
 		w.WriteHeader(401)
 		return errors.New("unauthorized")
 	}

+ 4 - 17
mod/dynamicproxy/Server.go

@@ -83,24 +83,11 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 			}
 		}
 
-		//SSO Interception Mode
-		/*
-			if sep.AuthenticationProvider.SSOInterceptMode {
-				allowPass := h.Parent.Option.SSOHandler.ServeForwardAuth(w, r)
-				if !allowPass {
-					h.Parent.Option.Logger.LogHTTPRequest(r, "sso-x", 307)
-					return
-				}
-			}
-		*/
-
 		//Validate basic auth
-		if sep.AuthenticationProvider.AuthMethod == AuthMethodBasic {
-			err := h.handleBasicAuthRouting(w, r, sep)
-			if err != nil {
-				h.Parent.Option.Logger.LogHTTPRequest(r, "host", 401)
-				return
-			}
+		respWritten := handleAuthProviderRouting(sep, w, r, h)
+		if respWritten {
+			//Request handled by subroute
+			return
 		}
 
 		//Check if any virtual directory rules matches

+ 45 - 3
mod/dynamicproxy/basicAuth.go → mod/dynamicproxy/authProviders.go

@@ -9,12 +9,47 @@ import (
 )
 
 /*
-	BasicAuth.go
+	authProviders.go
 
-	This file handles the basic auth on proxy endpoints
-	if RequireBasicAuth is set to true
+	This script handle authentication providers
 */
 
+/*
+Central Authentication Provider Router
+
+This function will route the request to the correct authentication provider
+if the return value is true, do not continue to the next handler
+
+handleAuthProviderRouting takes in 4 parameters:
+- sep: the ProxyEndpoint object
+- w: the http.ResponseWriter object
+- r: the http.Request object
+- h: the ProxyHandler object
+
+and return a boolean indicate if the request is written to http.ResponseWriter
+- true: the request is handled, do not write to http.ResponseWriter
+- false: the request is not handled (usually means auth ok), continue to the next handler
+*/
+func handleAuthProviderRouting(sep *ProxyEndpoint, w http.ResponseWriter, r *http.Request, h *ProxyHandler) bool {
+	if sep.AuthenticationProvider.AuthMethod == AuthMethodBasic {
+		err := h.handleBasicAuthRouting(w, r, sep)
+		if err != nil {
+			h.Parent.Option.Logger.LogHTTPRequest(r, "host", 401)
+			return true
+		}
+	} else if sep.AuthenticationProvider.AuthMethod == AuthMethodAuthelia {
+		err := h.handleAutheliaAuth(w, r)
+		if err != nil {
+			h.Parent.Option.Logger.LogHTTPRequest(r, "host", 401)
+			return true
+		}
+	}
+
+	//No authentication provider, do not need to handle
+	return false
+}
+
+/* Basic Auth */
 func (h *ProxyHandler) handleBasicAuthRouting(w http.ResponseWriter, r *http.Request, pe *ProxyEndpoint) error {
 	err := handleBasicAuth(w, r, pe)
 	if err != nil {
@@ -64,3 +99,10 @@ func handleBasicAuth(w http.ResponseWriter, r *http.Request, pe *ProxyEndpoint)
 
 	return nil
 }
+
+/* Authelia */
+
+// Handle authelia auth routing
+func (h *ProxyHandler) handleAutheliaAuth(w http.ResponseWriter, r *http.Request) error {
+	return h.Parent.Option.AutheliaRouter.HandleAutheliaAuth(w, r)
+}

+ 25 - 12
mod/dynamicproxy/typedef.go

@@ -7,7 +7,7 @@ import (
 	"sync"
 
 	"imuslab.com/zoraxy/mod/access"
-	"imuslab.com/zoraxy/mod/auth/sso"
+	"imuslab.com/zoraxy/mod/auth/sso/authelia"
 	"imuslab.com/zoraxy/mod/dynamicproxy/dpcore"
 	"imuslab.com/zoraxy/mod/dynamicproxy/loadbalance"
 	"imuslab.com/zoraxy/mod/dynamicproxy/permissionpolicy"
@@ -33,14 +33,17 @@ type ProxyHandler struct {
 
 /* Router Object Options */
 type RouterOption struct {
-	HostUUID           string                    //The UUID of Zoraxy, use for heading mod
-	HostVersion        string                    //The version of Zoraxy, use for heading mod
-	Port               int                       //Incoming port
-	UseTls             bool                      //Use TLS to serve incoming requsts
-	ForceTLSLatest     bool                      //Force TLS1.2 or above
-	NoCache            bool                      //Force set Cache-Control: no-store
-	ListenOnPort80     bool                      //Enable port 80 http listener
-	ForceHttpsRedirect bool                      //Force redirection of http to https endpoint
+	/* Basic Settings */
+	HostUUID           string //The UUID of Zoraxy, use for heading mod
+	HostVersion        string //The version of Zoraxy, use for heading mod
+	Port               int    //Incoming port
+	UseTls             bool   //Use TLS to serve incoming requsts
+	ForceTLSLatest     bool   //Force TLS1.2 or above
+	NoCache            bool   //Force set Cache-Control: no-store
+	ListenOnPort80     bool   //Enable port 80 http listener
+	ForceHttpsRedirect bool   //Force redirection of http to https endpoint
+
+	/* Routing Service Managers */
 	TlsManager         *tlscert.Manager          //TLS manager for serving SAN certificates
 	RedirectRuleTable  *redirection.RuleTable    //Redirection rules handler and table
 	GeodbStore         *geodb.Store              //GeoIP resolver
@@ -48,8 +51,12 @@ type RouterOption struct {
 	StatisticCollector *statistic.Collector      //Statistic collector for storing stats on incoming visitors
 	WebDirectory       string                    //The static web server directory containing the templates folder
 	LoadBalancer       *loadbalance.RouteManager //Load balancer that handle load balancing of proxy target
-	SSOHandler         *sso.SSOHandler           //SSO handler for handling SSO requests, interception mode only
-	Logger             *logger.Logger            //Logger for reverse proxy requets
+
+	/* Authentication Providers */
+	AutheliaRouter *authelia.AutheliaRouter //Authelia router for Authelia authentication
+
+	/* Utilities */
+	Logger *logger.Logger //Logger for reverse proxy requets
 }
 
 /* Router Object */
@@ -129,9 +136,15 @@ const (
 )
 
 type AuthenticationProvider struct {
-	AuthMethod              AuthMethod                //The authentication method to use
+	AuthMethod AuthMethod //The authentication method to use
+	/* Basic Auth Settings */
 	BasicAuthCredentials    []*BasicAuthCredentials   //Basic auth credentials
 	BasicAuthExceptionRules []*BasicAuthExceptionRule //Path to exclude in a basic auth enabled proxy target
+	BasicAuthGroupIDs       []string                  //Group IDs that are allowed to access this endpoint
+
+	/* Authelia Settings */
+	AutheliaURL string //URL of the Authelia server, leave empty to use global settings e.g. authelia.example.com
+	UseHTTPS    bool   //Whether to use HTTPS for the Authelia server
 }
 
 // A proxy endpoint record, a general interface for handling inbound routing

+ 15 - 7
reverseproxy.go

@@ -98,8 +98,8 @@ func ReverseProxtInit() {
 		StatisticCollector: statisticCollector,
 		WebDirectory:       *staticWebServerRoot,
 		AccessController:   accessController,
+		AutheliaRouter:     autheliaRouter,
 		LoadBalancer:       loadBalancer,
-		SSOHandler:         ssoHandler,
 		Logger:             SystemWideLogger,
 	})
 	if err != nil {
@@ -471,13 +471,17 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
 	}
 	bypassGlobalTLS := (bpgtls == "true")
 
-	// Basic Auth
-	rba, _ := utils.PostPara(r, "bauth")
-	if rba == "" {
-		rba = "false"
+	// Auth Provider
+	authProviderTypeStr, _ := utils.PostPara(r, "authprovider")
+	if authProviderTypeStr == "" {
+		authProviderTypeStr = "0"
 	}
 
-	requireBasicAuth := (rba == "true")
+	authProviderType, err := strconv.Atoi(authProviderTypeStr)
+	if err != nil {
+		utils.SendErrorResponse(w, "Invalid auth provider type")
+		return
+	}
 
 	// Rate Limiting?
 	rl, _ := utils.PostPara(r, "rate")
@@ -519,8 +523,12 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
 			BasicAuthExceptionRules: []*dynamicproxy.BasicAuthExceptionRule{},
 		}
 	}
-	if requireBasicAuth {
+	if authProviderType == 1 {
 		newProxyEndpoint.AuthenticationProvider.AuthMethod = dynamicproxy.AuthMethodBasic
+	} else if authProviderType == 2 {
+		newProxyEndpoint.AuthenticationProvider.AuthMethod = dynamicproxy.AuthMethodAuthelia
+	} else if authProviderType == 3 {
+		newProxyEndpoint.AuthenticationProvider.AuthMethod = dynamicproxy.AuthMethodOauth2
 	} else {
 		newProxyEndpoint.AuthenticationProvider.AuthMethod = dynamicproxy.AuthMethodNone
 	}

+ 8 - 15
start.go

@@ -12,6 +12,7 @@ import (
 	"imuslab.com/zoraxy/mod/access"
 	"imuslab.com/zoraxy/mod/acme"
 	"imuslab.com/zoraxy/mod/auth"
+	"imuslab.com/zoraxy/mod/auth/sso/authelia"
 	"imuslab.com/zoraxy/mod/database"
 	"imuslab.com/zoraxy/mod/database/dbinc"
 	"imuslab.com/zoraxy/mod/dockerux"
@@ -136,21 +137,13 @@ func startupSequence() {
 		panic(err)
 	}
 
-	/*
-		//Create an SSO handler
-		ssoHandler, err = sso.NewSSOHandler(&sso.SSOConfig{
-			SystemUUID:       nodeUUID,
-			PortalServerPort: 5488,
-			AuthURL:          "http://auth.localhost",
-			Database:         sysdb,
-			Logger:           SystemWideLogger,
-		})
-		if err != nil {
-			log.Fatal(err)
-		}
-		//Restore the SSO handler to previous state before shutdown
-		ssoHandler.RestorePreviousRunningState()
-	*/
+	//Create authentication providers
+	autheliaRouter = authelia.NewAutheliaRouter(&authelia.AutheliaRouterOptions{
+		UseHTTPS:    false, // Automatic populate in router initiation
+		AutheliaURL: "",    // Automatic populate in router initiation
+		Logger:      SystemWideLogger,
+		Database:    sysdb,
+	})
 
 	//Create a statistic collector
 	statisticCollector, err = statistic.NewStatisticCollector(statistic.CollectorOption{

+ 45 - 50
tools/tcpcpy/main.go

@@ -1,66 +1,61 @@
 package main
 
 import (
-	"log"
+	"flag"
+	"fmt"
+	"net"
 	"os"
-	"strings"
 )
 
-const timeout = 5
-
 func main() {
-	//log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
-	log.SetFlags(log.Ldate | log.Lmicroseconds)
+	//180.177.2.133 TW
+	//124.244.86.40 HK
+	ip := flag.String("ip", "180.177.2.133:62531", "IP address to send and receive UDP packets")
+	port := flag.Int("port", 8890, "Port to send and receive UDP packets")
+	flag.Parse()
 
-	printWelcome()
+	if *ip == "" {
+		fmt.Println("IP address is required")
+		os.Exit(1)
+	}
 
-	args := os.Args
-	argc := len(os.Args)
-	if argc <= 2 {
-		printHelp()
-		os.Exit(0)
+	addr := net.UDPAddr{
+		IP:   net.ParseIP(*ip),
+		Port: *port,
 	}
 
-	switch args[1] {
-	case "-listen":
-		if argc < 3 {
-			log.Fatalln(`-listen need two arguments, like "nb -listen 1997 2017".`)
-		}
-		port1 := checkPort(args[2])
-		port2 := checkPort(args[3])
-		log.Println("[√]", "start to listen port:", port1, "and port:", port2)
-		port2port(port1, port2)
-		break
-	case "-tran":
-		if argc < 3 {
-			log.Fatalln(`-tran need two arguments, like "nb -tran 1997 192.168.1.2:3389".`)
-		}
-		port := checkPort(args[2])
-		var remoteAddress string
-		if checkIp(args[3]) {
-			remoteAddress = args[3]
-		}
-		split := strings.SplitN(remoteAddress, ":", 2)
-		log.Println("[√]", "start to transmit address:", remoteAddress, "to address:", split[0]+":"+port)
-		port2host(port, remoteAddress)
-		break
-	case "-slave":
-		if argc < 3 {
-			log.Fatalln(`-slave need two arguments, like "nb -slave 127.0.0.1:3389 8.8.8.8:1997".`)
+	conn, err := net.DialUDP("udp", nil, &addr)
+	if err != nil {
+		fmt.Printf("Failed to connect to UDP server: %v\n", err)
+		os.Exit(1)
+	}
+	defer conn.Close()
+
+	localAddr := conn.LocalAddr().(*net.UDPAddr)
+	fmt.Printf("Local address: %s\n", localAddr.String())
+
+	message := []byte("Hello UDP Server")
+
+	go func() {
+		for {
+			_, err := conn.Write(message)
+			if err != nil {
+				fmt.Printf("Failed to send UDP packet: %v\n", err)
+				os.Exit(1)
+			}
 		}
-		var address1, address2 string
-		checkIp(args[2])
-		if checkIp(args[2]) {
-			address1 = args[2]
+	}()
+
+	buffer := make([]byte, 1024)
+	for {
+		n, remoteAddr, err := conn.ReadFromUDP(buffer)
+		if err != nil {
+			fmt.Printf("Failed to read UDP packet: %v\n", err)
+			continue
 		}
-		checkIp(args[3])
-		if checkIp(args[3]) {
-			address2 = args[3]
+
+		if remoteAddr.IP.String() == *ip {
+			fmt.Printf("Received UDP packet from %s: %s\n", remoteAddr, string(buffer[:n]))
 		}
-		log.Println("[√]", "start to connect address:", address1, "and address:", address2)
-		host2host(address1, address2)
-		break
-	default:
-		printHelp()
 	}
 }

+ 0 - 204
tools/tcpcpy/nb.go

@@ -1,204 +0,0 @@
-package main
-
-import (
-	"fmt"
-	"io"
-	"log"
-	"net"
-	"os"
-	"regexp"
-	"strconv"
-	"strings"
-	"sync"
-	"time"
-)
-
-func printWelcome() {
-	fmt.Println("+----------------------------------------------------------------+")
-	fmt.Println("| Welcome to use NATBypass Ver1.0.0 .                            |")
-	fmt.Println("| Code by cw1997 at 2017-10-19 03:59:51                          |")
-	fmt.Println("| Modified by tobychui as Zoraxy test tool                       |")
-	fmt.Println("| If you have some problem when you use the tool,                |")
-	fmt.Println("| please submit issue at : https://github.com/cw1997/NATBypass . |")
-	fmt.Println("+----------------------------------------------------------------+")
-	fmt.Println()
-	// sleep one second because the fmt is not thread-safety.
-	// if not to do this, fmt.Print will print after the log.Print.
-	time.Sleep(time.Second)
-}
-func printHelp() {
-	fmt.Println(`usage: "-listen port1 port2" example: "nb -listen 1997 2017" `)
-	fmt.Println(`       "-tran port1 ip:port2" example: "nb -tran 1997 192.168.1.2:3389" `)
-	fmt.Println(`       "-slave ip1:port1 ip2:port2" example: "nb -slave 127.0.0.1:3389 8.8.8.8:1997" `)
-	fmt.Println(`============================================================`)
-	fmt.Println(`optional argument: "-log logpath" . example: "nb -listen 1997 2017 -log d:/nb" `)
-	fmt.Println(`log filename format: Y_m_d_H_i_s-agrs1-args2-args3.log`)
-	fmt.Println(`============================================================`)
-	fmt.Println(`if you want more help, please read "README.md". `)
-}
-
-func checkPort(port string) string {
-	PortNum, err := strconv.Atoi(port)
-	if err != nil {
-		log.Fatalln("[x]", "port should be a number")
-	}
-	if PortNum < 1 || PortNum > 65535 {
-		log.Fatalln("[x]", "port should be a number and the range is [1,65536)")
-	}
-	return port
-}
-
-func checkIp(address string) bool {
-	ipAndPort := strings.Split(address, ":")
-	if len(ipAndPort) != 2 {
-		log.Fatalln("[x]", "address error. should be a string like [ip:port]. ")
-	}
-	ip := ipAndPort[0]
-	port := ipAndPort[1]
-	checkPort(port)
-	pattern := `^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$`
-	ok, err := regexp.MatchString(pattern, ip)
-	if err != nil || !ok {
-		log.Fatalln("[x]", "ip error. ")
-	}
-	return ok
-}
-
-func port2port(port1 string, port2 string) {
-	listen1 := start_server("0.0.0.0:" + port1)
-	listen2 := start_server("0.0.0.0:" + port2)
-	log.Println("[√]", "listen port:", port1, "and", port2, "success. waiting for client...")
-	for {
-		conn1 := accept(listen1)
-		conn2 := accept(listen2)
-		if conn1 == nil || conn2 == nil {
-			log.Println("[x]", "accept client faild. retry in ", timeout, " seconds. ")
-			time.Sleep(timeout * time.Second)
-			continue
-		}
-		forward(conn1, conn2)
-	}
-}
-
-func port2host(allowPort string, targetAddress string) {
-	server := start_server("0.0.0.0:" + allowPort)
-	for {
-		conn := accept(server)
-		if conn == nil {
-			continue
-		}
-		//println(targetAddress)
-		go func(targetAddress string) {
-			log.Println("[+]", "start connect host:["+targetAddress+"]")
-			target, err := net.Dial("tcp", targetAddress)
-			if err != nil {
-				// temporarily unavailable, don't use fatal.
-				log.Println("[x]", "connect target address ["+targetAddress+"] faild. retry in ", timeout, "seconds. ")
-				conn.Close()
-				log.Println("[←]", "close the connect at local:["+conn.LocalAddr().String()+"] and remote:["+conn.RemoteAddr().String()+"]")
-				time.Sleep(timeout * time.Second)
-				return
-			}
-			log.Println("[→]", "connect target address ["+targetAddress+"] success.")
-			forward(target, conn)
-		}(targetAddress)
-	}
-}
-
-func host2host(address1, address2 string) {
-	for {
-		log.Println("[+]", "try to connect host:["+address1+"] and ["+address2+"]")
-		var host1, host2 net.Conn
-		var err error
-		for {
-			host1, err = net.Dial("tcp", address1)
-			if err == nil {
-				log.Println("[→]", "connect ["+address1+"] success.")
-				break
-			} else {
-				log.Println("[x]", "connect target address ["+address1+"] faild. retry in ", timeout, " seconds. ")
-				time.Sleep(timeout * time.Second)
-			}
-		}
-		for {
-			host2, err = net.Dial("tcp", address2)
-			if err == nil {
-				log.Println("[→]", "connect ["+address2+"] success.")
-				break
-			} else {
-				log.Println("[x]", "connect target address ["+address2+"] faild. retry in ", timeout, " seconds. ")
-				time.Sleep(timeout * time.Second)
-			}
-		}
-		forward(host1, host2)
-	}
-}
-
-func start_server(address string) net.Listener {
-	log.Println("[+]", "try to start server on:["+address+"]")
-	server, err := net.Listen("tcp", address)
-	if err != nil {
-		log.Fatalln("[x]", "listen address ["+address+"] faild.")
-	}
-	log.Println("[√]", "start listen at address:["+address+"]")
-	return server
-}
-
-func accept(listener net.Listener) net.Conn {
-	conn, err := listener.Accept()
-	if err != nil {
-		log.Println("[x]", "accept connect ["+conn.RemoteAddr().String()+"] faild.", err.Error())
-		return nil
-	}
-	log.Println("[√]", "accept a new client. remote address:["+conn.RemoteAddr().String()+"], local address:["+conn.LocalAddr().String()+"]")
-	return conn
-}
-
-func forward(conn1 net.Conn, conn2 net.Conn) {
-	log.Printf("[+] start transmit. [%s],[%s] <-> [%s],[%s] \n", conn1.LocalAddr().String(), conn1.RemoteAddr().String(), conn2.LocalAddr().String(), conn2.RemoteAddr().String())
-	var wg sync.WaitGroup
-	// wait tow goroutines
-	wg.Add(2)
-	go connCopy(conn1, conn2, &wg)
-	go connCopy(conn2, conn1, &wg)
-	//blocking when the wg is locked
-	wg.Wait()
-}
-
-func connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup) {
-	//TODO:log, record the data from conn1 and conn2.
-	logFile := openLog(conn1.LocalAddr().String(), conn1.RemoteAddr().String(), conn2.LocalAddr().String(), conn2.RemoteAddr().String())
-	if logFile != nil {
-		w := io.MultiWriter(conn1, logFile)
-		io.Copy(w, conn2)
-	} else {
-		io.Copy(conn1, conn2)
-	}
-	conn1.Close()
-	log.Println("[←]", "close the connect at local:["+conn1.LocalAddr().String()+"] and remote:["+conn1.RemoteAddr().String()+"]")
-	//conn2.Close()
-	//log.Println("[←]", "close the connect at local:["+conn2.LocalAddr().String()+"] and remote:["+conn2.RemoteAddr().String()+"]")
-	wg.Done()
-}
-func openLog(address1, address2, address3, address4 string) *os.File {
-	args := os.Args
-	argc := len(os.Args)
-	var logFileError error
-	var logFile *os.File
-	if argc > 5 && args[4] == "-log" {
-		address1 = strings.Replace(address1, ":", "_", -1)
-		address2 = strings.Replace(address2, ":", "_", -1)
-		address3 = strings.Replace(address3, ":", "_", -1)
-		address4 = strings.Replace(address4, ":", "_", -1)
-		timeStr := time.Now().Format("2006_01_02_15_04_05") // "2006-01-02 15:04:05"
-		logPath := args[5] + "/" + timeStr + args[1] + "-" + address1 + "_" + address2 + "-" + address3 + "_" + address4 + ".log"
-		logPath = strings.Replace(logPath, `\`, "/", -1)
-		logPath = strings.Replace(logPath, "//", "/", -1)
-		logFile, logFileError = os.OpenFile(logPath, os.O_APPEND|os.O_CREATE, 0666)
-		if logFileError != nil {
-			log.Fatalln("[x]", "log file path error.", logFileError.Error())
-		}
-		log.Println("[√]", "open test log file success. path:", logPath)
-	}
-	return logFile
-}

+ 0 - 16
tools/tcpcpy/server_public.sh

@@ -1,16 +0,0 @@
-#!/bin/bash
-
-# This script is suppose to run on the public server with public IP access
-
-# Ask user to input the local listening port
-read -p "Enter the local listening port for Zoraxy HTTP proxy endpoint: " port1
-
-echo "OK! Remember to add a proxy rule that points your preferred domain (e.g. service.example.com) to 127.0.0.1:$port1"
-
-# Ask user to input the Zoraxy TCP stream proxy target port
-read -p "Enter the Zoraxy TCP stream proxy listening port: " port2
-
-echo "OK! Remember to add a TCP stream proxy rule that points your WAN exposed port to 127.0.0.1:$port2"
-
-# Start the tcpcpy with the provided ports
-./tcpcpy.exe -listen $port1 $port2

+ 0 - 12
tools/tcpcpy/server_under_nat.sh

@@ -1,12 +0,0 @@
-#!/bin/bash
-
-#This script is suppose to run on the private server under NAT
-
-# Ask user to input the local listening port
-read -p "Enter your local webserver port: " port1
-
-# Ask user to input the Zoraxy TCP stream proxy target port
-read -p "Enter the Zoraxy TCP stream proxy target port on your public server: " port2
-
-# Start the tcpcpy with the provided ports
-./tcpcpy.exe -tran $port1 $port2

BIN
tools/tcpcpy/tcpcpy.exe~


+ 36 - 15
web/components/httprp.html

@@ -126,9 +126,11 @@
                         <td data-label="" editable="true" datatype="vdir">${vdList}</td>
                         <td data-label="" editable="true" datatype="advanced" style="width: 350px;">
                             ${subd.AuthenticationProvider.AuthMethod == 0x1?`<i class="ui green check icon"></i> Basic Auth`:``}
-                            ${subd.AuthenticationProvider.AuthMethod == 0x1 && subd.RequireRateLimit?"<br>":""}
-                            ${subd.AuthenticationProvider.RequireRateLimit?`<i class="ui green check icon"></i> Rate Limit @ ${subd.RateLimit} req/s`:``}
-                            ${!subd.AuthenticationProvider.AuthMethod == 0x1 && !subd.RequireRateLimit?`<small style="opacity: 0.3; pointer-events: none; user-select: none;">No Special Settings</small>`:""}
+                            ${subd.AuthenticationProvider.AuthMethod == 0x2?`<i class="ui blue key icon"></i> Authelia`:``}
+                            ${subd.AuthenticationProvider.AuthMethod == 0x3?`<i class="ui yellow key icon"></i> Oauth2`:``}
+                            ${subd.AuthenticationProvider.AuthMethod != 0x0 && subd.RequireRateLimit?"<br>":""}
+                            ${subd.RequireRateLimit?`<i class="ui green check icon"></i> Rate Limit @ ${subd.RateLimit} req/s`:``}
+                            ${subd.AuthenticationProvider.AuthMethod == 0x0 && !subd.RequireRateLimit?`<small style="opacity: 0.3; pointer-events: none; user-select: none;">No Special Settings</small>`:""}
                         </td>
                         <td class="center aligned ignoremw" editable="true" datatype="action" data-label="">
                             <div class="ui toggle tiny fitted checkbox" style="margin-bottom: -0.5em; margin-right: 0.4em;" title="Enable / Disable Rule">
@@ -194,6 +196,11 @@
                     }
 
                     let rule = accessRuleMap[thisAccessRuleID];
+                    if (rule == undefined){
+                        //Old configs with no access rule field, use default
+                        rule = {};
+                        rule.ID = "default";
+                    }
                     let icon = `<i class="ui grey filter icon"></i>`;
                     if (rule.ID == "default"){
                         icon = `<i class="ui yellow star icon"></i>`;
@@ -269,11 +276,8 @@
                 </button>`);
 
             }else if (datatype == "advanced"){
-                let requireBasicAuth = payload.AuthenticationProvider.AuthMethod == 0x1;
-                let basicAuthCheckstate = "";
-                if (requireBasicAuth){
-                    basicAuthCheckstate = "checked";
-                }
+                let authProvider = payload.AuthenticationProvider.AuthMethod;
+                
 
                 let skipWebSocketOriginCheck = payload.SkipWebSocketOriginCheck;
                 let wsCheckstate = "";
@@ -296,13 +300,29 @@
                     rateLimitDisableState = "disabled";
                 }
 
-                column.empty().append(`<div class="ui checkbox" style="margin-top: 0.4em;">
-                    <input type="checkbox" class="RequireBasicAuth" ${basicAuthCheckstate}>
-                        <label>Require Basic Auth</label>
+                column.empty().append(`
+                    <div class="grouped fields authProviderPicker">
+                        <label><b>Authentication Provider</b></label>
+                        <div class="field">
+                            <div class="ui radio checkbox">
+                                <input type="radio" value="0" checked="checked" name="authProviderType">
+                                <label>None (Anyone can access)</label>
+                            </div>
+                        </div>
+                        <div class="field">
+                            <div class="ui radio checkbox">
+                                <input type="radio" value="1" name="authProviderType">
+                                <label>Basic Auth</label>
+                            </div>
+                        </div>
+                        <div class="field">
+                            <div class="ui radio checkbox">
+                                <input type="radio" value="2" name="authProviderType">
+                                <label>Authelia</label>
+                            </div>
+                        </div>
                     </div>
-                    <br>
                     <button class="ui basic compact tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editBasicAuthCredentials('${uuid}');"><i class="ui blue user circle icon"></i> Edit Credentials</button>
-                    <br>
                     <button class="ui basic compact tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editCustomHeaders('${uuid}');"><i class="heading icon"></i> Custom Headers</button>
 
                     <div class="ui basic advance segment" style="padding: 0.4em !important; border-radius: 0.4em;">
@@ -328,6 +348,7 @@
                     <div>
                 `);
 
+                $('.authProviderPicker .ui.checkbox').checkbox();
             } else if (datatype == "ratelimit"){
                
                 column.empty().append(`
@@ -421,7 +442,7 @@
         
         var epttype = "host";
         let useStickySession =  $(row).find(".UseStickySession")[0].checked;
-        let requireBasicAuth = $(row).find(".RequireBasicAuth")[0].checked;
+        let authProviderType = $(row).find(".authProviderPicker input[type='radio']:checked").val();
         let requireRateLimit = $(row).find(".RequireRateLimit")[0].checked;
         let rateLimit = $(row).find(".RateLimit").val();
         let bypassGlobalTLS = $(row).find(".BypassGlobalTLS")[0].checked;
@@ -434,7 +455,7 @@
                 "rootname": uuid,
                 "ss":useStickySession,
                 "bpgtls": bypassGlobalTLS,
-                "bauth" :requireBasicAuth,
+                "authprovider" :authProviderType,
                 "rate" :requireRateLimit,
                 "ratenum" :rateLimit,
             },

+ 47 - 349
web/components/sso.html

@@ -1,381 +1,79 @@
 <div class="standardContainer">
     <div class="ui basic segment">
-        <div class="ui message">
+        <h2>SSO</h2>
+        <p>Single Sign-On (SSO) and authentication providers settings </p>
+    </div>
+
+    <div class="ui basic segment">
+        <div class="ui yellow message">
             <div class="header">
-                Work in Progress
+                Experimental Feature
             </div>
-            <p>The SSO feature is currently under development.</p>
+            <p>Please note that this feature is still in development and may not work as expected.</p>
         </div>
     </div>
-</div>
-<!-- 
-<div class="standardContainer">
+    <div class="ui divider"></div>
     <div class="ui basic segment">
-        <h2>Zoraxy SSO / Oauth</h2>
-        <p>A centralized authentication system for all your subdomains</p>
-        <div class="ui divider"></div>
-        <div class="ui basic segment enabled ssoRunningState">
-            <h4 class="ui header" id="ssoRunningState">
-                <i class="circle check icon"></i>
-                <div class="content">
-                    <span class="webserv_status">Running</span>
-                    <div class="sub header">Listen port :<span class="oauthserv_port">8081</span></div>
-                </div>
-            </h4>
-        </div>
-        <div class="ui form">
-            <h3 class="ui dividing header">Oauth2 Server Settings</h3>
-            <div class="field">
-                <div class="ui toggle checkbox">
-                    <input type="checkbox" name="enableOauth2">
-                    <label>Enable Oauth2 Server<br>
-                    <small>Oauth2 server for handling external authentication requests</small></label>
-                </div>
-            </div>
-            <div class="field">
-                <label>Oauth2 Server Port</label>
-                <div class="ui action input">
-                    <input type="number" name="oauth2Port" placeholder="Port" value="5488">
-                    <button id="saveOauthServerPortBtn" class="ui basic green button"><i class="ui green circle check icon"></i> Update</button>         
-                </div>
-                <small>Listening port of the Zoraxy internal Oauth2 Server.You can create a subdomain proxy rule to <code>127.0.0.1:<span class="ssoPort">5488</span></code></small>
-            </div>
+        <h3>Authelia</h3>
+        <p>Configuration settings for Authelia authentication provider.</p>
+
+        <form class="ui form">
             <div class="field">
-                <label>Auth URL</label>
-                <div class="ui action input">
-                    <input type="text" name="authURL" placeholder="https://auth.yourdomain.com">
-                    <button id="saveAuthURLBtn" class="ui basic blue button"><i class="ui blue save icon"></i> Save</button>
-                </div>
-                <small>The exposed authentication URL of the Oauth2 server, usually <code>https://auth.example.com</code> or <code>https://sso.yourdomain.com</code>. <b>Remember to include the http:// or https:// in your URL.</b></small>
+                <label for="autheliaServerUrl">Authelia Server URL</label>
+                <input type="text" id="autheliaServerUrl" name="autheliaServerUrl" placeholder="Enter Authelia Server URL">
+                <small>Example: auth.example.com</small>
             </div>
-        </div>
-        <br>
-        <div class="ui form">
-            <h3 class="ui dividing header">Zoraxy SSO Settings</h3>
             <div class="field">
-                <label>Default Redirection URL </label>   
-                <div class="ui fluid input">
-                    <input type="text" name="defaultSiteURL" placeholder="https://yourdomain.com">
+                <div class="ui checkbox">
+                    <input type="checkbox" id="useHttps" name="useHttps">
+                    <label for="useHttps">Use HTTPS</label>
+                    <small>Check this if your authelia server uses HTTPS</small>
                 </div>
-                <small>The default URL to redirect to after login if redirection target is not set</small>
-            </div>
-
-            <button class="ui basic button"> <i class="ui green check icon"></i> Apply Changes </button>
-        </div>
-        <div class="ui basic message">
-            <div class="header">
-                <i class="ui yellow exclamation triangle icon"></i> Important Notes about Zoraxy SSO
             </div>
-            <p>Zoraxy SSO, if enabled in HTTP Proxy rule, will automatically intercept the proxy request and provide an SSO interface on upstreams that do not support OAuth natively.
-                It is basically like basic auth with a login page. <b> The same user credential can be used in OAuth sign-in and Zoraxy SSO sign-in.</b>
-            </p>
-        </div>
-        <div class="ui divider"></div>
-        <div>
-            <h3 class="ui header">
-                <i class="ui blue user circle icon"></i>
-                <div class="content">
-                    Registered Users
-                  <div class="sub header">A list of users that are registered with the SSO server</div>
-                </div>
-            </h3>
-            <table class="ui celled table">
-                <thead>
-                    <tr>
-                        <th>Username</th>
-                        <th>Registered On</th>
-                        <th>Reset Password</th>
-                        <th>Remove</th>
-                    </tr>
-                </thead>
-                <tbody id="registeredSsoUsers">
-                    <tr>
-                        <td>admin</td>
-                        <td>2020-01-01</td>
-                        <td><button class="ui blue basic small icon button"><i class="ui blue key icon"></i></button></td>
-                        <td><button class="ui red basic small icon button"><i class="ui red trash icon"></i></button></td>
-                    </tr>
-                </tbody>
-            </table>
-            <button onclick="handleUserListRefresh();" class="ui basic right floated button"><i class="ui green refresh icon"></i> Refresh</button>
-            <button onclick="openRegisteredUserManager();" class="ui basic button"><i class="ui blue users icon"></i> Manage Registered Users</button>
-        </div>
-        <div class="ui divider"></div>
-        <div>
-            <h3 class="ui header">
-                <i class="ui green th icon"></i>
-                <div class="content">
-                    Registered Apps
-                  <div class="sub header">A list of apps that are registered with the SSO server</div>
-                </div>
-            </h3>
-            <table class="ui celled table">
-                <thead>
-                    <tr>
-                        <th>App Name</th>
-                        <th>Domain</th>
-                        <th>App ID</th>
-                        <th>Registered On</th>
-                        <th>Remove</th>
-                    </tr>
-                </thead>
-                <tbody id="registeredSsoApps">
-                    <tr>
-                        <td>My App</td>
-                        <td><a href="//example.com" target="_blank">example.com</a></td>
-                        <td>123456</td>
-                        <td>2020-01-01</td>
-                        <td><button class="ui red basic small icon button"><i class="ui red trash icon"></i></button></td>
-                    </tr>
-                </tbody>
-            </table>
-            <button onclick="handleRegisterAppListRefresh();" class="ui basic right floated button"><i class="ui green refresh icon"></i> Refresh</button>
-            <button onclick="openRegisterAppManagementSnippet();" class="ui basic button"><i style="font-size: 1em; margin-top: -0.2em;" class="ui green th large icon"></i> Manage Registered App</button>
-            <p></p>
-        </div>
+            <button class="ui basic button" onclick="event.preventDefault(); updateAutheliaSettings();"><i class="green check icon"></i> Apply Change</button>
+        </form>
     </div>
+    <div class="ui divider"></div>
 </div>
 
 <script>
-    $("input[name=oauth2Port]").on("change", function() {
-        $(".ssoPort").text($(this).val());
-    });
-
-    function updateSSOStatus(){
-        $.get("/api/sso/status", function(data){
-            if(data.error != undefined){
-                //Show error message
-                $(".ssoRunningState").removeClass("enabled").addClass("disabled");
-                $("#ssoRunningState .webserv_status").html('Error: '+data.error);
-            }else{
-                if (data.Enabled){
-                    $(".ssoRunningState").addClass("enabled");
-                    $("#ssoRunningState .webserv_status").html('Running');
-                    $(".ssoRunningState i").attr("class", "circle check icon");
-                    $("input[name=enableOauth2]").parent().checkbox("set checked");
-                }else{
-                    $(".ssoRunningState").removeClass("enabled");
-                    $("#ssoRunningState .webserv_status").html('Stopped');
-                    $(".ssoRunningState i").attr("class", "circle times icon");
-                    $("input[name=enableOauth2]").parent().checkbox("set unchecked");
-                }
-                $("input[name=oauth2Port]").val(data.ListeningPort);
-                $(".oauthserv_port").text(data.ListeningPort);
-                $("input[name=authURL]").val(data.AuthURL);
-            }
-        });
-    }
-
-
-    function initSSOStatus(){
-        $.get("/api/sso/status", function(data){
-            //Update the SSO status from the server
-            updateSSOStatus();
-
-            //Bind events to the enable checkbox
-            $("input[name=enableOauth2]").off("change").on("change", function(){
-                var checked = $(this).prop("checked");
-                $.cjax({
-                    url: "/api/sso/enable",
-                    method: "POST",
-                    data: {
-                        enable: checked
-                    },
-                    success: function(data){
-                        if(data.error != undefined){
-                            msgbox("Failed to toggle SSO: " + data.error, false);
-                            //Unbind the event to prevent infinite loop
-                            $("input[name=enableOauth2]").off("change");
-                        }else{
-                            initSSOStatus();
-                        }
-                    }
-                });
-            });
-        });
-    }
-    initSSOStatus();
-
-    /* Save the Oauth server port */
-    function saveOauthServerPort(){
-        var port = $("input[name=oauth2Port]").val();
-        //Check if the port is valid
-        if (port < 1 || port > 65535){
-                msgbox("Invalid port number", false);
-                return;
-        }
-        //Use cjax to send the port to the server with csrf token
+    $(document).ready(function() {
         $.cjax({
-            url: "/api/sso/setPort",
-            method: "POST",
-            data: {
-                port: port
-            },
+            url: '/api/sso/Authelia',
+            method: 'GET',
+            dataType: 'json',
             success: function(data) {
-                if (data.error != undefined) {
-                    msgbox("Failed to update Oauth server port: " + data.error, false);
-                } else {
-                    msgbox("Oauth server port updated", true);
-                    
-                }
-                updateSSOStatus();
+                $('#autheliaServerUrl').val(data.autheliaURL);
+                $('#useHttps').prop('checked', data.useHTTPS);
+            },
+            error: function(jqXHR, textStatus, errorThrown) {
+                console.error('Error fetching SSO settings:', textStatus, errorThrown);
             }
         });
-    }
-    //Bind the save button to the saveOauthServerPort function
-    $("#saveOauthServerPortBtn").on("click", function() {
-        saveOauthServerPort();
-    });
-    $("input[name=oauth2Port]").on("keypress", function(e) {
-        if (e.which == 13) {
-            saveOauthServerPort();
-        }
     });
 
-    /* Save the Oauth server URL (aka AuthURL) */
-    function saveAuthURL(){
-        var url = $("input[name=authURL]").val();
-        //Make sure the url contains http:// or https://
-        if (!url.startsWith("http://") && !url.startsWith("https://")){
-            msgbox("Invalid URL. Make sure to include http:// or https://", false);
-            $("input[name=authURL]").parent().parent().addClass("error");
-            return;
-        }else{
-            $("input[name=authURL]").parent().parent().removeClass("error");
-        }
-        //Use cjax to send the port to the server with csrf token
+    function updateAutheliaSettings(){
+        var autheliaServerUrl = $('#autheliaServerUrl').val();
+        var useHttps = $('#useHttps').prop('checked');
+
         $.cjax({
-            url: "/api/sso/setAuthURL",
-            method: "POST",
+            url: '/api/sso/Authelia',
+            method: 'POST',
             data: {
-                "auth_url": url
+                autheliaURL: autheliaServerUrl,
+                useHTTPS: useHttps
             },
             success: function(data) {
                 if (data.error != undefined) {
-                    msgbox("Failed to update Oauth server port: " + data.error, false);
-                } else {
-                    msgbox("Oauth server port updated", true);
-                    
+                    $.msgbox(data.error, false);
+                    return;
                 }
-                updateSSOStatus();
-            }
-        });
-    }
-
-    //Bind the save button to the saveAuthURL function
-    $("#saveAuthURLBtn").on("click", function() {
-        saveAuthURL();
-    });
-    $("input[name=authURL]").on("keypress", function(e) {
-        if (e.which == 13) {
-            saveAuthURL();
-        }
-    });
-    
-    /* Registered Apps Event Handlers */
-    
-    //Function to initialize the registered app table
-    function initRegisteredAppTable(){
-        $.get("/api/sso/app/list", function(data){
-            if(data.error != undefined){
-                msgbox("Failed to get registered apps: " + data.error, false);
-            }else{
-                var tbody = $("#registeredSsoApps");
-                tbody.empty();
-                for(var i = 0; i < data.length; i++){
-                    var app = data[i];
-                    var tr = $("<tr>");
-                    tr.append($("<td>").text(app.AppName));
-                    tr.append($("<td>").html('<a href="//'+app.Domain+'" target="_blank">'+app.Domain+'</a>'));
-                    tr.append($("<td>").text(app.AppID));
-                    tr.append($("<td>").text(app.RegisteredOn));
-                    var removeBtn = $("<button>").addClass("ui red basic small icon button").html('<i class="ui red trash icon"></i>');
-                    removeBtn.on("click", function(){
-                        removeApp(app.AppID);
-                    });
-                    tr.append($("<td>").append(removeBtn));
-                    tbody.append(tr);
-                }
-
-                if (data.length == 0){
-                    tbody.append($("<tr>").append($("<td>").attr("colspan", 4).html(`<i class="ui green circle check icon"></i> No registered users`)));
-                }
-            }
-        });
-    }
-    initRegisteredAppTable();
-
-    //Also bind the refresh button to the initRegisteredAppTable function
-    function handleRegisterAppListRefresh(){
-        initRegisteredAppTable();
-    }
-
-    function openRegisterAppManagementSnippet(){
-        //Open the register app management snippet
-        showSideWrapper("snippet/sso_app.html");
-    }
-
-
-    //Bind the remove button to the removeApp function
-    function removeApp(appID){
-        $.cjax({
-            url: "/api/sso/removeApp",
-            method: "POST",
-            data: {
-                appID: appID
+                msgbox('Authelia settings updated', true);
+                console.log('Authelia settings updated:', data);
             },
-            success: function(data){
-                if(data.error != undefined){
-                    msgbox("Failed to remove app: " + data.error, false);
-                }else{
-                    msgbox("App removed", true);
-                    updateSSOStatus();
-                }
+            error: function(jqXHR, textStatus, errorThrown) {
+                console.error('Error updating Authelia settings:', textStatus, errorThrown);
             }
         });
     }
-
-    /* Registered Users Event Handlers */
-    function initUserList(){
-        $.get("/api/sso/user/list", function(data){
-            if(data.error != undefined){
-                msgbox("Failed to get registered users: " + data.error, false);
-            }else{
-                var tbody = $("#registeredSsoUsers");
-                tbody.empty();
-                for(var i = 0; i < data.length; i++){
-                    var user = data[i];
-                    var tr = $("<tr>");
-                    tr.append($("<td>").text(user.Username));
-                    tr.append($("<td>").text(user.RegisteredOn));
-                    var resetBtn = $("<button>").addClass("ui blue basic small icon button").html('<i class="ui blue key icon"></i>');
-                    resetBtn.on("click", function(){
-                        resetPassword(user.Username);
-                    });
-                    tr.append($("<td>").append(resetBtn));
-                    var removeBtn = $("<button>").addClass("ui red basic small icon button").html('<i class="ui red trash icon"></i>');
-                    removeBtn.on("click", function(){
-                        removeUser(user.Username);
-                    });
-                    tr.append($("<td>").append(removeBtn));
-                    tbody.append(tr);
-                }
-
-                if (data.length == 0){
-                    tbody.append($("<tr>").append($("<td>").attr("colspan", 4).html(`<i class="ui green circle check icon"></i> No registered users`)));
-                }
-            }
-        });
-    }
-
-    //Bind the refresh button to the initUserList function
-    function handleUserListRefresh(){
-        initUserList();
-    }
-
-    function openRegisteredUserManager(){
-        //Open the registered user management snippet
-        showSideWrapper("snippet/sso_user.html");
-    }
-</script>
--->
+</script>

+ 0 - 29
web/snippet/sso_app.html

@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html>
-    <head>
-        <meta charset="utf-8">
-        <meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
-        <link rel="stylesheet" href="../script/semantic/semantic.min.css">
-        <script src="../script/jquery-3.6.0.min.js"></script>
-        <script src="../script/semantic/semantic.min.js"></script>
-        <script src="../script/utils.js"></script>
-        <style>
-            body{
-                height: 100%;
-                width: 100%;
-            }
-        </style>
-    </head>
-    <body>
-        <link rel="stylesheet" href="../darktheme.css">
-        <script src="../script/darktheme.js"></script>
-        <br>
-        <div class="ui container">
-            <div class="ui basic segment">
-                <h2 class="ui header">SSO App Management</h2>
-                <div class="ui divider"></div>
-                <h3>Work in progress</h3>
-            </div>
-        </div>
-    </body>
-</html>

+ 0 - 29
web/snippet/sso_user.html

@@ -1,29 +0,0 @@
-<!DOCTYPE html>
-<html>
-    <head>
-        <meta charset="utf-8">
-        <meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
-        <link rel="stylesheet" href="../script/semantic/semantic.min.css">
-        <script src="../script/jquery-3.6.0.min.js"></script>
-        <script src="../script/semantic/semantic.min.js"></script>
-        <script src="../script/utils.js"></script>
-        <style>
-            body{
-                height: 100%;
-                width: 100%;
-            }
-        </style>
-    </head>
-    <body>
-        <link rel="stylesheet" href="../darktheme.css">
-        <script src="../script/darktheme.js"></script>
-        <br>
-        <div class="ui container">
-            <div class="ui basic segment">
-                <h2 class="ui header">SSO User Management</h2>
-                <div class="ui divider"></div>
-                <h3>Work in progress</h3>
-            </div>
-        </div>
-    </body>
-</html>