1
0

oauth2.go 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package sso
  2. import (
  3. "context"
  4. _ "embed"
  5. "encoding/json"
  6. "fmt"
  7. "log"
  8. "net/http"
  9. "net/url"
  10. "time"
  11. "github.com/go-oauth2/oauth2/v4/errors"
  12. "github.com/go-oauth2/oauth2/v4/generates"
  13. "github.com/go-oauth2/oauth2/v4/manage"
  14. "github.com/go-oauth2/oauth2/v4/models"
  15. "github.com/go-oauth2/oauth2/v4/server"
  16. "github.com/go-oauth2/oauth2/v4/store"
  17. "github.com/go-session/session"
  18. "imuslab.com/zoraxy/mod/utils"
  19. )
  20. type OAuth2Server struct {
  21. srv *server.Server //oAuth server instance
  22. config *SSOConfig
  23. parent *SSOHandler
  24. }
  25. //go:embed static/auth.html
  26. var authHtml []byte
  27. //go:embed static/login.html
  28. var loginHtml []byte
  29. // NewOAuth2Server creates a new OAuth2 server instance
  30. func NewOAuth2Server(config *SSOConfig, parent *SSOHandler) (*OAuth2Server, error) {
  31. manager := manage.NewDefaultManager()
  32. manager.SetAuthorizeCodeTokenCfg(manage.DefaultAuthorizeCodeTokenCfg)
  33. // token store
  34. manager.MustTokenStorage(store.NewMemoryTokenStore())
  35. // generate jwt access token
  36. manager.MapAccessGenerate(generates.NewAccessGenerate())
  37. //Load user information from SSO_USERS
  38. clientStore := store.NewClientStore()
  39. clientStore.Set("alanyeung", &models.Client{
  40. ID: "alanyeung",
  41. Secret: "password",
  42. Domain: "localhost:8000",
  43. })
  44. manager.MapClientStorage(clientStore)
  45. thisServer := OAuth2Server{
  46. config: config,
  47. parent: parent,
  48. }
  49. //Create a new oauth server
  50. srv := server.NewServer(server.NewConfig(), manager)
  51. srv.SetPasswordAuthorizationHandler(thisServer.PasswordAuthorizationHandler)
  52. srv.SetUserAuthorizationHandler(thisServer.UserAuthorizeHandler)
  53. srv.SetInternalErrorHandler(func(err error) (re *errors.Response) {
  54. log.Println("Internal Error:", err.Error())
  55. return
  56. })
  57. srv.SetResponseErrorHandler(func(re *errors.Response) {
  58. log.Println("Response Error:", re.Error.Error())
  59. })
  60. thisServer.srv = srv
  61. return &thisServer, nil
  62. }
  63. // Password handler, validate if the given username and password are correct
  64. func (oas *OAuth2Server) PasswordAuthorizationHandler(ctx context.Context, clientID, username, password string) (userID string, err error) {
  65. fmt.Println(username, password)
  66. if username == "alanyeung" && password == "password" {
  67. userID = "alanyeung"
  68. }
  69. return
  70. }
  71. // User Authorization Handler, handle auth request from user
  72. func (oas *OAuth2Server) UserAuthorizeHandler(w http.ResponseWriter, r *http.Request) (userID string, err error) {
  73. store, err := session.Start(r.Context(), w, r)
  74. if err != nil {
  75. return
  76. }
  77. uid, ok := store.Get("ZoraxySSO")
  78. if !ok {
  79. if r.Form == nil {
  80. r.ParseForm()
  81. }
  82. store.Set("ReturnUri", r.Form)
  83. store.Save()
  84. w.Header().Set("Location", "/oauth2/login")
  85. w.WriteHeader(http.StatusFound)
  86. return
  87. }
  88. userID = uid.(string)
  89. store.Delete("ZoraxySSO")
  90. store.Save()
  91. return
  92. }
  93. /* SSO Web Server Toggle Functions */
  94. func (oas *OAuth2Server) RegisterOauthEndpoints(primaryMux *http.ServeMux) {
  95. primaryMux.HandleFunc("/oauth2/login", oas.loginHandler)
  96. primaryMux.HandleFunc("/oauth2/auth", oas.authHandler)
  97. primaryMux.HandleFunc("/oauth2/authorize", func(w http.ResponseWriter, r *http.Request) {
  98. store, err := session.Start(r.Context(), w, r)
  99. if err != nil {
  100. http.Error(w, err.Error(), http.StatusInternalServerError)
  101. return
  102. }
  103. var form url.Values
  104. if v, ok := store.Get("ReturnUri"); ok {
  105. form = v.(url.Values)
  106. }
  107. r.Form = form
  108. store.Delete("ReturnUri")
  109. store.Save()
  110. err = oas.srv.HandleAuthorizeRequest(w, r)
  111. if err != nil {
  112. http.Error(w, err.Error(), http.StatusBadRequest)
  113. }
  114. })
  115. primaryMux.HandleFunc("/oauth2/token", func(w http.ResponseWriter, r *http.Request) {
  116. err := oas.srv.HandleTokenRequest(w, r)
  117. if err != nil {
  118. http.Error(w, err.Error(), http.StatusInternalServerError)
  119. }
  120. })
  121. primaryMux.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
  122. token, err := oas.srv.ValidationBearerToken(r)
  123. if err != nil {
  124. http.Error(w, err.Error(), http.StatusBadRequest)
  125. return
  126. }
  127. data := map[string]interface{}{
  128. "expires_in": int64(time.Until(token.GetAccessCreateAt().Add(token.GetAccessExpiresIn())).Seconds()),
  129. "client_id": token.GetClientID(),
  130. "user_id": token.GetUserID(),
  131. }
  132. e := json.NewEncoder(w)
  133. e.SetIndent("", " ")
  134. e.Encode(data)
  135. })
  136. }
  137. func (oas *OAuth2Server) loginHandler(w http.ResponseWriter, r *http.Request) {
  138. store, err := session.Start(r.Context(), w, r)
  139. if err != nil {
  140. http.Error(w, err.Error(), http.StatusInternalServerError)
  141. return
  142. }
  143. if r.Method == "POST" {
  144. if r.Form == nil {
  145. if err := r.ParseForm(); err != nil {
  146. http.Error(w, err.Error(), http.StatusInternalServerError)
  147. return
  148. }
  149. }
  150. //Load username and password from form post
  151. username, err := utils.PostPara(r, "username")
  152. if err != nil {
  153. w.Write([]byte("Invalid username or password"))
  154. return
  155. }
  156. password, err := utils.PostPara(r, "password")
  157. if err != nil {
  158. w.Write([]byte("Invalid username or password"))
  159. return
  160. }
  161. //Validate the user
  162. if !oas.parent.ValidateUsernameAndPassword(username, password) {
  163. //Wrong password
  164. w.Write([]byte("Invalid username or password"))
  165. return
  166. }
  167. store.Set("ZoraxySSO", r.Form.Get("username"))
  168. store.Save()
  169. w.Header().Set("Location", "/oauth2/auth")
  170. w.WriteHeader(http.StatusFound)
  171. return
  172. }
  173. //User not logged in. Show login page
  174. w.Write(loginHtml)
  175. }
  176. func (oas *OAuth2Server) authHandler(w http.ResponseWriter, r *http.Request) {
  177. store, err := session.Start(context.TODO(), w, r)
  178. if err != nil {
  179. http.Error(w, err.Error(), http.StatusInternalServerError)
  180. return
  181. }
  182. if _, ok := store.Get("ZoraxySSO"); !ok {
  183. w.Header().Set("Location", "/oauth2/login")
  184. w.WriteHeader(http.StatusFound)
  185. return
  186. }
  187. //User logged in. Show authentication confirm page
  188. w.Write(authHtml)
  189. }