users.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package sso
  2. import (
  3. "encoding/json"
  4. "time"
  5. "github.com/xlzd/gotp"
  6. "imuslab.com/zoraxy/mod/auth"
  7. )
  8. /*
  9. users.go
  10. This file contains the user structure and user management
  11. functions for the SSO module.
  12. If you are looking for handlers, please refer to handlers.go.
  13. */
  14. type SubdomainAccessRule struct {
  15. Subdomain string
  16. AllowAccess bool
  17. }
  18. type UserEntry struct {
  19. UserID string `json:sub` //User ID
  20. Username string `json:"name"` //Username
  21. Email string `json:"email"` //Email
  22. PasswordHash string `json:"passwordhash"` //Password hash
  23. TOTPCode string `json:"totpcode"` //TOTP code
  24. Enable2FA bool `json:"enable2fa"` //Enable 2FA
  25. Subdomains map[string]*SubdomainAccessRule `json:"subdomains"` //Subdomain access rules
  26. LastLogin int64 `json:"lastlogin"` //Last login time
  27. LastLoginIP string `json:"lastloginip"` //Last login IP
  28. LastLoginCountry string `json:"lastlogincountry"` //Last login country
  29. parent *SSOHandler //Parent SSO handler
  30. }
  31. type ClientResponse struct {
  32. Sub string `json:"sub"` //User ID
  33. Name string `json:"name"` //Username
  34. Nickname string `json:"nickname"` //Nickname
  35. PreferredUsername string `json:"preferred_username"` //Preferred Username
  36. Email string `json:"email"` //Email
  37. Locale string `json:"locale"` //Locale
  38. Website string `json:"website"` //Website
  39. }
  40. func (s *SSOHandler) SSOUserExists(userid string) bool {
  41. //Check if the user exists in the database
  42. var userEntry UserEntry
  43. err := s.Config.Database.Read("sso_users", userid, &userEntry)
  44. return err == nil
  45. }
  46. func (s *SSOHandler) GetSSOUser(userid string) (UserEntry, error) {
  47. //Load the user entry from database
  48. var userEntry UserEntry
  49. err := s.Config.Database.Read("sso_users", userid, &userEntry)
  50. if err != nil {
  51. return UserEntry{}, err
  52. }
  53. userEntry.parent = s
  54. return userEntry, nil
  55. }
  56. func (s *SSOHandler) ListSSOUsers() ([]*UserEntry, error) {
  57. entries, err := s.Config.Database.ListTable("sso_users")
  58. if err != nil {
  59. return nil, err
  60. }
  61. ssoUsers := []*UserEntry{}
  62. for _, keypairs := range entries {
  63. group := new(UserEntry)
  64. json.Unmarshal(keypairs[1], &group)
  65. group.parent = s
  66. ssoUsers = append(ssoUsers, group)
  67. }
  68. return ssoUsers, nil
  69. }
  70. // Validate the username and password
  71. func (s *SSOHandler) ValidateUsernameAndPassword(username string, password string) bool {
  72. //Validate the username and password
  73. var userEntry UserEntry
  74. err := s.Config.Database.Read("sso_users", username, &userEntry)
  75. if err != nil {
  76. return false
  77. }
  78. //TODO: Remove after testing
  79. if (username == "test") && (password == "test") {
  80. return true
  81. }
  82. return userEntry.VerifyPassword(password)
  83. }
  84. func (s *UserEntry) VerifyPassword(password string) bool {
  85. return s.PasswordHash == auth.Hash(password)
  86. }
  87. // Write changes in the user entry back to the database
  88. func (u *UserEntry) Update() error {
  89. js, _ := json.Marshal(u)
  90. err := u.parent.Config.Database.Write("sso_users", u.UserID, string(js))
  91. if err != nil {
  92. return err
  93. }
  94. return nil
  95. }
  96. // Reset and update the TOTP code for the current user
  97. // Return the provision uri of the new TOTP code for Google Authenticator
  98. func (u *UserEntry) ResetTotp(accountName string, issuerName string) (string, error) {
  99. u.TOTPCode = gotp.RandomSecret(16)
  100. totp := gotp.NewDefaultTOTP(u.TOTPCode)
  101. err := u.Update()
  102. if err != nil {
  103. return "", err
  104. }
  105. return totp.ProvisioningUri(accountName, issuerName), nil
  106. }
  107. // Verify the TOTP code at current time
  108. func (u *UserEntry) VerifyTotp(enteredCode string) bool {
  109. totp := gotp.NewDefaultTOTP(u.TOTPCode)
  110. return totp.Verify(enteredCode, time.Now().Unix())
  111. }
  112. func (u *UserEntry) GetClientResponse() ClientResponse {
  113. return ClientResponse{
  114. Sub: u.UserID,
  115. Name: u.Username,
  116. Nickname: u.Username,
  117. PreferredUsername: u.Username,
  118. Email: u.Email,
  119. Locale: "en",
  120. Website: "",
  121. }
  122. }