1
0

authelia.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. package authelia
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net/http"
  7. "net/url"
  8. "imuslab.com/zoraxy/mod/database"
  9. "imuslab.com/zoraxy/mod/info/logger"
  10. "imuslab.com/zoraxy/mod/utils"
  11. )
  12. type AutheliaRouterOptions struct {
  13. UseHTTPS bool //If the Authelia server is using HTTPS
  14. AutheliaURL string //The URL of the Authelia server
  15. Logger *logger.Logger
  16. Database *database.Database
  17. }
  18. type AutheliaRouter struct {
  19. options *AutheliaRouterOptions
  20. }
  21. // NewAutheliaRouter creates a new AutheliaRouter object
  22. func NewAutheliaRouter(options *AutheliaRouterOptions) *AutheliaRouter {
  23. options.Database.NewTable("authelia")
  24. //Read settings from database, if exists
  25. options.Database.Read("authelia", "autheliaURL", &options.AutheliaURL)
  26. options.Database.Read("authelia", "useHTTPS", &options.UseHTTPS)
  27. return &AutheliaRouter{
  28. options: options,
  29. }
  30. }
  31. // HandleSetAutheliaURLAndHTTPS is the internal handler for setting the Authelia URL and HTTPS
  32. func (ar *AutheliaRouter) HandleSetAutheliaURLAndHTTPS(w http.ResponseWriter, r *http.Request) {
  33. if r.Method == http.MethodGet {
  34. //Return the current settings
  35. js, _ := json.Marshal(map[string]interface{}{
  36. "useHTTPS": ar.options.UseHTTPS,
  37. "autheliaURL": ar.options.AutheliaURL,
  38. })
  39. utils.SendJSONResponse(w, string(js))
  40. return
  41. } else if r.Method == http.MethodPost {
  42. //Update the settings
  43. autheliaURL, err := utils.PostPara(r, "autheliaURL")
  44. if err != nil {
  45. utils.SendErrorResponse(w, "autheliaURL not found")
  46. return
  47. }
  48. useHTTPS, err := utils.PostBool(r, "useHTTPS")
  49. if err != nil {
  50. useHTTPS = false
  51. }
  52. //Write changes to runtime
  53. ar.options.AutheliaURL = autheliaURL
  54. ar.options.UseHTTPS = useHTTPS
  55. //Write changes to database
  56. ar.options.Database.Write("authelia", "autheliaURL", autheliaURL)
  57. ar.options.Database.Write("authelia", "useHTTPS", useHTTPS)
  58. utils.SendOK(w)
  59. } else {
  60. http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
  61. return
  62. }
  63. }
  64. // handleAutheliaAuth is the internal handler for Authelia authentication
  65. // Set useHTTPS to true if your authelia server is using HTTPS
  66. // Set autheliaURL to the URL of the Authelia server, e.g. authelia.example.com
  67. func (ar *AutheliaRouter) HandleAutheliaAuth(w http.ResponseWriter, r *http.Request) error {
  68. client := &http.Client{}
  69. if ar.options.AutheliaURL == "" {
  70. ar.options.Logger.PrintAndLog("Authelia", "Authelia URL not set", nil)
  71. w.WriteHeader(500)
  72. w.Write([]byte("500 - Internal Server Error"))
  73. return errors.New("authelia URL not set")
  74. }
  75. protocol := "http"
  76. if ar.options.UseHTTPS {
  77. protocol = "https"
  78. }
  79. autheliaBaseURL := protocol + "://" + ar.options.AutheliaURL
  80. //Remove tailing slash if any
  81. if autheliaBaseURL[len(autheliaBaseURL)-1] == '/' {
  82. autheliaBaseURL = autheliaBaseURL[:len(autheliaBaseURL)-1]
  83. }
  84. //Make a request to Authelia to verify the request
  85. req, err := http.NewRequest("POST", autheliaBaseURL+"/api/verify", nil)
  86. if err != nil {
  87. ar.options.Logger.PrintAndLog("Authelia", "Unable to create request", err)
  88. w.WriteHeader(401)
  89. return errors.New("unauthorized")
  90. }
  91. scheme := "http"
  92. if r.TLS != nil {
  93. scheme = "https"
  94. }
  95. req.Header.Add("X-Original-URL", fmt.Sprintf("%s://%s", scheme, r.Host))
  96. // Copy cookies from the incoming request
  97. for _, cookie := range r.Cookies() {
  98. req.AddCookie(cookie)
  99. }
  100. // Making the verification request
  101. resp, err := client.Do(req)
  102. if err != nil {
  103. ar.options.Logger.PrintAndLog("Authelia", "Unable to verify", err)
  104. w.WriteHeader(401)
  105. return errors.New("unauthorized")
  106. }
  107. if resp.StatusCode != 200 {
  108. redirectURL := autheliaBaseURL + "/?rd=" + url.QueryEscape(scheme+"://"+r.Host+r.URL.String()) + "&rm=" + r.Method
  109. http.Redirect(w, r, redirectURL, http.StatusSeeOther)
  110. return errors.New("unauthorized")
  111. }
  112. return nil
  113. }