jwts.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package logic
  2. import (
  3. "errors"
  4. "fmt"
  5. "strings"
  6. "time"
  7. "github.com/golang-jwt/jwt/v4"
  8. "github.com/gravitl/netmaker/logger"
  9. "github.com/gravitl/netmaker/models"
  10. "github.com/gravitl/netmaker/servercfg"
  11. )
  12. var jwtSecretKey []byte
  13. // SetJWTSecret - sets the jwt secret on server startup
  14. func SetJWTSecret() {
  15. currentSecret, jwtErr := FetchJWTSecret()
  16. if jwtErr != nil {
  17. newValue := RandomString(64)
  18. jwtSecretKey = []byte(newValue) // 512 bit random password
  19. if err := StoreJWTSecret(string(jwtSecretKey)); err != nil {
  20. logger.FatalLog("something went wrong when configuring JWT authentication")
  21. }
  22. } else {
  23. jwtSecretKey = []byte(currentSecret)
  24. }
  25. }
  26. // CreateJWT func will used to create the JWT while signing in and signing out
  27. func CreateJWT(uuid string, macAddress string, network string) (response string, err error) {
  28. expirationTime := time.Now().Add(5 * time.Minute)
  29. claims := &models.Claims{
  30. ID: uuid,
  31. Network: network,
  32. MacAddress: macAddress,
  33. RegisteredClaims: jwt.RegisteredClaims{
  34. Issuer: "Netmaker",
  35. Subject: fmt.Sprintf("node|%s", uuid),
  36. IssuedAt: jwt.NewNumericDate(time.Now()),
  37. ExpiresAt: jwt.NewNumericDate(expirationTime),
  38. },
  39. }
  40. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  41. tokenString, err := token.SignedString(jwtSecretKey)
  42. if err == nil {
  43. return tokenString, nil
  44. }
  45. return "", err
  46. }
  47. // CreateProUserJWT - creates a user jwt token
  48. func CreateProUserJWT(username string, networks, groups []string, isadmin bool) (response string, err error) {
  49. expirationTime := time.Now().Add(60 * 12 * time.Minute)
  50. claims := &models.UserClaims{
  51. UserName: username,
  52. Networks: networks,
  53. IsAdmin: isadmin,
  54. Groups: groups,
  55. RegisteredClaims: jwt.RegisteredClaims{
  56. Issuer: "Netmaker",
  57. Subject: fmt.Sprintf("user|%s", username),
  58. IssuedAt: jwt.NewNumericDate(time.Now()),
  59. ExpiresAt: jwt.NewNumericDate(expirationTime),
  60. },
  61. }
  62. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  63. tokenString, err := token.SignedString(jwtSecretKey)
  64. if err == nil {
  65. return tokenString, nil
  66. }
  67. return "", err
  68. }
  69. // CreateUserJWT - creates a user jwt token
  70. func CreateUserJWT(username string, networks []string, isadmin bool) (response string, err error) {
  71. expirationTime := time.Now().Add(60 * 12 * time.Minute)
  72. claims := &models.UserClaims{
  73. UserName: username,
  74. Networks: networks,
  75. IsAdmin: isadmin,
  76. RegisteredClaims: jwt.RegisteredClaims{
  77. Issuer: "Netmaker",
  78. Subject: fmt.Sprintf("user|%s", username),
  79. IssuedAt: jwt.NewNumericDate(time.Now()),
  80. ExpiresAt: jwt.NewNumericDate(expirationTime),
  81. },
  82. }
  83. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  84. tokenString, err := token.SignedString(jwtSecretKey)
  85. if err == nil {
  86. return tokenString, nil
  87. }
  88. return "", err
  89. }
  90. // VerifyJWT verifies Auth Header
  91. func VerifyJWT(bearerToken string) (username string, networks []string, isadmin bool, err error) {
  92. token := ""
  93. tokenSplit := strings.Split(bearerToken, " ")
  94. if len(tokenSplit) > 1 {
  95. token = tokenSplit[1]
  96. } else {
  97. return "", nil, false, errors.New("invalid auth header")
  98. }
  99. return VerifyUserToken(token)
  100. }
  101. // VerifyUserToken func will used to Verify the JWT Token while using APIS
  102. func VerifyUserToken(tokenString string) (username string, networks []string, isadmin bool, err error) {
  103. claims := &models.UserClaims{}
  104. if tokenString == servercfg.GetMasterKey() && servercfg.GetMasterKey() != "" {
  105. return "masteradministrator", nil, true, nil
  106. }
  107. token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
  108. return jwtSecretKey, nil
  109. })
  110. if token != nil && token.Valid {
  111. var user *models.User
  112. // check that user exists
  113. user, err = GetUser(claims.UserName)
  114. if err != nil {
  115. return "", nil, false, err
  116. }
  117. if user.UserName != "" {
  118. return claims.UserName, claims.Networks, claims.IsAdmin, nil
  119. }
  120. err = errors.New("user does not exist")
  121. }
  122. return "", nil, false, err
  123. }
  124. // VerifyHostToken - [hosts] Only
  125. func VerifyHostToken(tokenString string) (hostID string, mac string, network string, err error) {
  126. claims := &models.Claims{}
  127. // this may be a stupid way of serving up a master key
  128. // TODO: look into a different method. Encryption?
  129. if tokenString == servercfg.GetMasterKey() && servercfg.GetMasterKey() != "" {
  130. return "mastermac", "", "", nil
  131. }
  132. token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
  133. return jwtSecretKey, nil
  134. })
  135. if token != nil {
  136. return claims.ID, claims.MacAddress, claims.Network, nil
  137. }
  138. return "", "", "", err
  139. }