autologin.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. package auth
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "io/ioutil"
  6. "log"
  7. "net/http"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "github.com/gorilla/sessions"
  12. uuid "github.com/satori/go.uuid"
  13. )
  14. //Autologin token. This token will not expire until admin removal
  15. type AutoLoginToken struct {
  16. Owner string
  17. Token string
  18. }
  19. func (a *AuthAgent) NewAutologinToken(username string) string {
  20. //Generate a new token
  21. newTokenUUID := uuid.NewV4().String() + "-" + strconv.Itoa(int(time.Now().Unix()))
  22. a.autoLoginTokens = append(a.autoLoginTokens, &AutoLoginToken{
  23. Owner: username,
  24. Token: newTokenUUID,
  25. })
  26. //Save the token to sysdb
  27. a.Database.Write("auth", "altoken/"+newTokenUUID, username)
  28. //Return the new token
  29. return newTokenUUID
  30. }
  31. func (a *AuthAgent) RemoveAutologinToken(token string) {
  32. newTokenArray := []*AutoLoginToken{}
  33. for _, alt := range a.autoLoginTokens {
  34. if alt.Token != token {
  35. newTokenArray = append(newTokenArray, alt)
  36. } else {
  37. //Delete this from the database
  38. a.Database.Delete("auth", "altoken/"+alt.Token)
  39. }
  40. }
  41. a.autoLoginTokens = newTokenArray
  42. }
  43. func (a *AuthAgent) RemoveAutologinTokenByUsername(username string) {
  44. newTokenArray := []*AutoLoginToken{}
  45. for _, alt := range a.autoLoginTokens {
  46. if alt.Owner != username {
  47. newTokenArray = append(newTokenArray, alt)
  48. } else {
  49. //Delete this from the database
  50. a.Database.Delete("auth", "altoken/"+alt.Token)
  51. }
  52. }
  53. a.autoLoginTokens = newTokenArray
  54. }
  55. func (a *AuthAgent) LoadAutologinTokenFromDB() error {
  56. entries, err := a.Database.ListTable("auth")
  57. if err != nil {
  58. return err
  59. }
  60. for _, keypairs := range entries {
  61. if strings.Contains(string(keypairs[0]), "altoken/") {
  62. key := string(keypairs[0])
  63. owner := ""
  64. json.Unmarshal(keypairs[1], &owner)
  65. token := strings.Split(key, "/")[1]
  66. a.autoLoginTokens = append(a.autoLoginTokens, &AutoLoginToken{
  67. Owner: owner,
  68. Token: token,
  69. })
  70. }
  71. }
  72. return nil
  73. }
  74. func (a *AuthAgent) GetUsernameFromToken(token string) (string, error) {
  75. for _, alt := range a.autoLoginTokens {
  76. if alt.Token == token {
  77. return alt.Owner, nil
  78. }
  79. }
  80. return "", errors.New("Invalid Token")
  81. }
  82. func (a *AuthAgent) GetTokensFromUsername(username string) []*AutoLoginToken {
  83. results := []*AutoLoginToken{}
  84. for _, alt := range a.autoLoginTokens {
  85. if alt.Owner == username {
  86. results = append(results, alt)
  87. }
  88. }
  89. return results
  90. }
  91. func (a *AuthAgent) HandleAutologinTokenLogin(w http.ResponseWriter, r *http.Request) {
  92. //Get the authentication token from the request
  93. if a.AllowAutoLogin == false {
  94. w.WriteHeader(http.StatusForbidden)
  95. w.Write([]byte("403 - Forbidden"))
  96. log.Println("Someone is requesting autologin while this function is turned off.")
  97. return
  98. }
  99. session, _ := a.SessionStore.Get(r, a.SessionName)
  100. token, err := mv(r, "token", false)
  101. if err != nil {
  102. //Username not defined
  103. sendErrorResponse(w, "Token not defined or empty.")
  104. return
  105. }
  106. //Try to get the username from token
  107. username, err := a.GetUsernameFromToken(token)
  108. if err != nil {
  109. //This token is not valid
  110. w.WriteHeader(http.StatusUnauthorized)
  111. //Try to get the autologin error page.
  112. errtemplate, err := ioutil.ReadFile("./system/errors/invalidToken.html")
  113. if err != nil {
  114. w.Write([]byte("401 - Unauthorized (Token not valid)"))
  115. } else {
  116. w.Write(errtemplate)
  117. }
  118. return
  119. }
  120. //Check if the current client has already logged in another account
  121. currentlyLoggedUsername, err := a.GetUserName(w, r)
  122. if err == nil && currentlyLoggedUsername != username {
  123. //The current client already logged in with another user account!
  124. w.WriteHeader(http.StatusAccepted)
  125. errtemplate, err := ioutil.ReadFile("./system/errors/alreadyLoggedin.html")
  126. if err != nil {
  127. w.Write([]byte("202 - Accepted (Already logged in as another user)"))
  128. } else {
  129. w.Write(errtemplate)
  130. }
  131. return
  132. }
  133. //Ok. Allow this client to login
  134. session.Values["authenticated"] = true
  135. session.Values["username"] = username
  136. session.Values["rememberMe"] = false
  137. log.Println(username + " logged in via auto-login token")
  138. //Check if remember me is clicked. If yes, set the maxage to 1 week.
  139. session.Options = &sessions.Options{
  140. MaxAge: 3600 * 1, //1 hour
  141. Path: "/",
  142. }
  143. session.Save(r, w)
  144. redirectTarget, _ := mv(r, "redirect", false)
  145. if redirectTarget != "" {
  146. //Redirect to target website
  147. http.Redirect(w, r, redirectTarget, http.StatusTemporaryRedirect)
  148. } else {
  149. //Redirect this client to its interface module
  150. http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
  151. }
  152. }
  153. //Check if the given autologin token is valid. Autologin token is different from session token (aka token)
  154. func (a *AuthAgent) ValidateAutoLoginToken(token string) (bool, string) {
  155. //Try to get the username from token
  156. username, err := a.GetUsernameFromToken(token)
  157. if err != nil {
  158. //This token is not valid
  159. return false, ""
  160. }
  161. //Token is valid
  162. return true, username
  163. }