mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-01 13:17:21 +02:00
165 lines
4.1 KiB
Go
165 lines
4.1 KiB
Go
package authelia
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"imuslab.com/zoraxy/mod/database"
|
|
"imuslab.com/zoraxy/mod/info/logger"
|
|
"imuslab.com/zoraxy/mod/utils"
|
|
)
|
|
|
|
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 AutheliaRouter struct {
|
|
options *AutheliaRouterOptions
|
|
}
|
|
|
|
// 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,
|
|
}
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
}
|
|
|
|
// 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"))
|
|
return errors.New("authelia URL not set")
|
|
}
|
|
protocol := "http"
|
|
if ar.options.UseHTTPS {
|
|
protocol = "https"
|
|
}
|
|
|
|
autheliaURL := &url.URL{
|
|
Scheme: protocol,
|
|
Host: ar.options.AutheliaURL,
|
|
}
|
|
|
|
//Make a request to Authelia to verify the request
|
|
req, err := http.NewRequest("POST", autheliaURL.JoinPath("api", "verify").String(), nil)
|
|
if err != nil {
|
|
ar.options.Logger.PrintAndLog("Authelia", "Unable to create request", err)
|
|
w.WriteHeader(401)
|
|
return errors.New("unauthorized")
|
|
}
|
|
|
|
originalURL := rOriginalHeaders(r, req)
|
|
|
|
// Copy cookies from the incoming request
|
|
for _, cookie := range r.Cookies() {
|
|
req.AddCookie(cookie)
|
|
}
|
|
|
|
// Making the verification request
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
ar.options.Logger.PrintAndLog("Authelia", "Unable to verify", err)
|
|
w.WriteHeader(401)
|
|
return errors.New("unauthorized")
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
redirectURL := autheliaURL.JoinPath()
|
|
|
|
query := redirectURL.Query()
|
|
|
|
query.Set("rd", originalURL.String())
|
|
query.Set("rm", r.Method)
|
|
|
|
http.Redirect(w, r, redirectURL.String(), http.StatusSeeOther)
|
|
return errors.New("unauthorized")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func rOriginalHeaders(r, req *http.Request) *url.URL {
|
|
if r.RemoteAddr != "" {
|
|
before, _, _ := strings.Cut(r.RemoteAddr, ":")
|
|
|
|
if ip := net.ParseIP(before); ip != nil {
|
|
req.Header.Set("X-Forwarded-For", ip.String())
|
|
}
|
|
}
|
|
|
|
originalURL := &url.URL{
|
|
Scheme: "http",
|
|
Host: r.Host,
|
|
Path: r.URL.Path,
|
|
RawPath: r.URL.RawPath,
|
|
}
|
|
|
|
if r.TLS != nil {
|
|
originalURL.Scheme = "https"
|
|
}
|
|
|
|
req.Header.Add("X-Forwarded-Method", r.Method)
|
|
req.Header.Add("X-Original-URL", originalURL.String())
|
|
|
|
return originalURL
|
|
}
|