1
0

handlers.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. package sso
  2. /*
  3. handlers.go
  4. This file contains the handlers for the SSO module.
  5. If you are looking for handlers for SSO user management,
  6. please refer to userHandlers.go.
  7. */
  8. import (
  9. "encoding/json"
  10. "net/http"
  11. "strings"
  12. "github.com/gofrs/uuid"
  13. "imuslab.com/zoraxy/mod/utils"
  14. )
  15. // HandleSSOStatus handle the request to get the status of the SSO portal server
  16. func (s *SSOHandler) HandleSSOStatus(w http.ResponseWriter, r *http.Request) {
  17. type SSOStatus struct {
  18. Enabled bool
  19. SSOInterceptEnabled bool
  20. ListeningPort int
  21. AuthURL string
  22. }
  23. status := SSOStatus{
  24. Enabled: s.ssoPortalServer != nil,
  25. //SSOInterceptEnabled: s.ssoInterceptEnabled,
  26. ListeningPort: s.Config.PortalServerPort,
  27. AuthURL: s.Config.AuthURL,
  28. }
  29. js, _ := json.Marshal(status)
  30. utils.SendJSONResponse(w, string(js))
  31. }
  32. // HandleStartSSOPortal handle the request to start the SSO portal server
  33. func (s *SSOHandler) HandleStartSSOPortal(w http.ResponseWriter, r *http.Request) {
  34. err := s.StartSSOPortal()
  35. if err != nil {
  36. s.Log("Failed to start SSO portal server", err)
  37. utils.SendErrorResponse(w, "failed to start SSO portal server")
  38. return
  39. }
  40. //Write current state to database
  41. err = s.Config.Database.Write("sso_conf", "enabled", true)
  42. if err != nil {
  43. utils.SendErrorResponse(w, "failed to update SSO state")
  44. return
  45. }
  46. utils.SendOK(w)
  47. }
  48. // HandleStopSSOPortal handle the request to stop the SSO portal server
  49. func (s *SSOHandler) HandleStopSSOPortal(w http.ResponseWriter, r *http.Request) {
  50. err := s.ssoPortalServer.Close()
  51. if err != nil {
  52. s.Log("Failed to stop SSO portal server", err)
  53. utils.SendErrorResponse(w, "failed to stop SSO portal server")
  54. return
  55. }
  56. s.ssoPortalServer = nil
  57. //Write current state to database
  58. err = s.Config.Database.Write("sso_conf", "enabled", false)
  59. if err != nil {
  60. utils.SendErrorResponse(w, "failed to update SSO state")
  61. return
  62. }
  63. //Clear the cookie store and restart the server
  64. err = s.RestartSSOServer()
  65. if err != nil {
  66. utils.SendErrorResponse(w, "failed to restart SSO server")
  67. return
  68. }
  69. utils.SendOK(w)
  70. }
  71. // HandlePortChange handle the request to change the SSO portal server port
  72. func (s *SSOHandler) HandlePortChange(w http.ResponseWriter, r *http.Request) {
  73. if r.Method == http.MethodGet {
  74. //Return the current port
  75. js, _ := json.Marshal(s.Config.PortalServerPort)
  76. utils.SendJSONResponse(w, string(js))
  77. return
  78. }
  79. port, err := utils.PostInt(r, "port")
  80. if err != nil {
  81. utils.SendErrorResponse(w, "invalid port given")
  82. return
  83. }
  84. s.Config.PortalServerPort = port
  85. //Write to the database
  86. err = s.Config.Database.Write("sso_conf", "port", port)
  87. if err != nil {
  88. utils.SendErrorResponse(w, "failed to update port")
  89. return
  90. }
  91. //Clear the cookie store and restart the server
  92. err = s.RestartSSOServer()
  93. if err != nil {
  94. utils.SendErrorResponse(w, "failed to restart SSO server")
  95. return
  96. }
  97. utils.SendOK(w)
  98. }
  99. // HandleSetAuthURL handle the request to change the SSO auth URL
  100. // This is the URL that the SSO portal server will redirect to for authentication
  101. // e.g. auth.yourdomain.com
  102. func (s *SSOHandler) HandleSetAuthURL(w http.ResponseWriter, r *http.Request) {
  103. if r.Method == http.MethodGet {
  104. //Return the current auth URL
  105. js, _ := json.Marshal(s.Config.AuthURL)
  106. utils.SendJSONResponse(w, string(js))
  107. return
  108. }
  109. //Get the auth URL
  110. authURL, err := utils.PostPara(r, "auth_url")
  111. if err != nil {
  112. utils.SendErrorResponse(w, "invalid auth URL given")
  113. return
  114. }
  115. s.Config.AuthURL = authURL
  116. //Write to the database
  117. err = s.Config.Database.Write("sso_conf", "authurl", authURL)
  118. if err != nil {
  119. utils.SendErrorResponse(w, "failed to update auth URL")
  120. return
  121. }
  122. //Clear the cookie store and restart the server
  123. err = s.RestartSSOServer()
  124. if err != nil {
  125. utils.SendErrorResponse(w, "failed to restart SSO server")
  126. return
  127. }
  128. utils.SendOK(w)
  129. }
  130. // HandleRegisterApp handle the request to register a new app to the SSO portal
  131. func (s *SSOHandler) HandleRegisterApp(w http.ResponseWriter, r *http.Request) {
  132. appName, err := utils.PostPara(r, "app_name")
  133. if err != nil {
  134. utils.SendErrorResponse(w, "invalid app name given")
  135. return
  136. }
  137. id, err := utils.PostPara(r, "app_id")
  138. if err != nil {
  139. //If id is not given, use the app name with a random UUID
  140. newID, err := uuid.NewV4()
  141. if err != nil {
  142. utils.SendErrorResponse(w, "failed to generate new app ID")
  143. return
  144. }
  145. id = strings.ReplaceAll(appName, " ", "") + "-" + newID.String()
  146. }
  147. //Check if the given appid is already in use
  148. if _, ok := s.Apps[id]; ok {
  149. utils.SendErrorResponse(w, "app ID already in use")
  150. return
  151. }
  152. /*
  153. Process the app domain
  154. An app can have multiple domains, separated by commas
  155. Usually the app domain is the proxy rule that points to the app
  156. For example, if the app is hosted at app.yourdomain.com, the app domain is app.yourdomain.com
  157. */
  158. appDomain, err := utils.PostPara(r, "app_domain")
  159. if err != nil {
  160. utils.SendErrorResponse(w, "invalid app URL given")
  161. return
  162. }
  163. appURLs := strings.Split(appDomain, ",")
  164. //Remove padding and trailing spaces in each URL
  165. for i := range appURLs {
  166. appURLs[i] = strings.TrimSpace(appURLs[i])
  167. }
  168. //Create a new app entry
  169. thisAppEntry := RegisteredUpstreamApp{
  170. ID: id,
  171. Secret: "",
  172. Domain: appURLs,
  173. Scopes: []string{},
  174. SessionDuration: 3600,
  175. }
  176. js, _ := json.Marshal(thisAppEntry)
  177. //Create a new app in the database
  178. err = s.Config.Database.Write("sso_apps", appName, string(js))
  179. if err != nil {
  180. utils.SendErrorResponse(w, "failed to create new app")
  181. return
  182. }
  183. //Also add the app to runtime config
  184. s.Apps[appName] = thisAppEntry
  185. utils.SendOK(w)
  186. }
  187. // HandleAppRemove handle the request to remove an app from the SSO portal
  188. func (s *SSOHandler) HandleAppRemove(w http.ResponseWriter, r *http.Request) {
  189. appID, err := utils.PostPara(r, "app_id")
  190. if err != nil {
  191. utils.SendErrorResponse(w, "invalid app ID given")
  192. return
  193. }
  194. //Check if the app actually exists
  195. if _, ok := s.Apps[appID]; !ok {
  196. utils.SendErrorResponse(w, "app not found")
  197. return
  198. }
  199. delete(s.Apps, appID)
  200. //Also remove it from the database
  201. err = s.Config.Database.Delete("sso_apps", appID)
  202. if err != nil {
  203. s.Log("Failed to remove app from database", err)
  204. }
  205. }