package sso import ( "embed" "net/http" "github.com/gorilla/sessions" "imuslab.com/zoraxy/mod/database" "imuslab.com/zoraxy/mod/info/logger" ) //go:embed static/* var staticFiles embed.FS //Static files for the SSO portal type SSOConfig struct { SystemUUID string //System UUID, should be passed in from main scope AuthURL string //Authentication subdomain URL PortalServerPort int //SSO portal server port Database *database.Database Logger *logger.Logger } type SSOHandler struct { cookieStore *sessions.CookieStore ssoPortalServer *http.Server ssoPortalMux *http.ServeMux Config *SSOConfig } // Create a new Zoraxy SSO handler func NewSSOHandler(config *SSOConfig) (*SSOHandler, error) { //Create a cookie store for the SSO handler cookieStore := sessions.NewCookieStore([]byte(config.SystemUUID)) cookieStore.Options = &sessions.Options{ Path: "", Domain: "", MaxAge: 0, Secure: false, HttpOnly: false, SameSite: 0, } //Create a table for the new sso user management system err := config.Database.NewTable("sso_users") if err != nil { return nil, err } //Create the SSO Handler thisHandler := SSOHandler{ cookieStore: cookieStore, Config: config, } thisHandler.InitSSOPortal(config.PortalServerPort) return &thisHandler, nil } // ServeHTTP handle the SSO request by forwarding auth to the authelia server // return false if the request is not authorized and shall not be proceed // Note that only accounts that have SSO enabled will be handled by this handler func (h *SSOHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) bool { //Check if the user have the cookie "Zoraxy-SSO" set session, err := h.cookieStore.Get(r, "Zoraxy-SSO") if err != nil { //Redirect to auth subdomain http.Redirect(w, r, h.Config.AuthURL, http.StatusFound) return false } //Check if the user is logged in if session.Values["username"] != true { //Redirect to auth subdomain http.Redirect(w, r, h.Config.AuthURL, http.StatusFound) return false } //Check if the current request subdomain is allowed userName := session.Values["username"].(string) user, err := h.SSO_GetUser(userName) if err != nil { //User might have been removed from SSO. Redirect to auth subdomain http.Redirect(w, r, h.Config.AuthURL, http.StatusFound) return false } //Check if the user have access to the current subdomain if !user.Subdomains[r.Host].AllowAccess { //User is not allowed to access the current subdomain. Sent 403 http.Error(w, "Forbidden", http.StatusForbidden) //TODO: Use better looking template if exists return false } //User is logged in, continue to the next handler return true } // Log a message with the SSO module tag func (h *SSOHandler) Log(message string, err error) { h.Config.Logger.PrintAndLog("SSO", message, err) }