| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 | package logicimport (	"context"	"errors"	"fmt"	"strings"	"time"	"github.com/golang-jwt/jwt/v4"	"github.com/gravitl/netmaker/db"	"github.com/gravitl/netmaker/logger"	"github.com/gravitl/netmaker/models"	"github.com/gravitl/netmaker/schema"	"github.com/gravitl/netmaker/servercfg")var jwtSecretKey []byte// SetJWTSecret - sets the jwt secret on server startupfunc SetJWTSecret() {	currentSecret, jwtErr := FetchJWTSecret()	if jwtErr != nil {		newValue := RandomString(64)		jwtSecretKey = []byte(newValue) // 512 bit random password		if err := StoreJWTSecret(string(jwtSecretKey)); err != nil {			logger.FatalLog("something went wrong when configuring JWT authentication")		}	} else {		jwtSecretKey = []byte(currentSecret)	}}// CreateJWT func will used to create the JWT while signing in and signing outfunc CreateJWT(uuid string, macAddress string, network string) (response string, err error) {	expirationTime := time.Now().Add(15 * time.Minute)	claims := &models.Claims{		ID:         uuid,		Network:    network,		MacAddress: macAddress,		RegisteredClaims: jwt.RegisteredClaims{			Issuer:    "Netmaker",			Subject:   fmt.Sprintf("node|%s", uuid),			IssuedAt:  jwt.NewNumericDate(time.Now()),			ExpiresAt: jwt.NewNumericDate(expirationTime),		},	}	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)	tokenString, err := token.SignedString(jwtSecretKey)	if err == nil {		return tokenString, nil	}	return "", err}// CreateUserJWT - creates a user jwt tokenfunc CreateUserAccessJwtToken(username string, role models.UserRoleID, d time.Time, tokenID string) (response string, err error) {	claims := &models.UserClaims{		UserName:       username,		Role:           role,		TokenType:      models.AccessTokenType,		Api:            servercfg.GetAPIHost(),		RacAutoDisable: GetRacAutoDisable() && (role != models.SuperAdminRole && role != models.AdminRole),		RegisteredClaims: jwt.RegisteredClaims{			Issuer:    "Netmaker",			Subject:   fmt.Sprintf("user|%s", username),			IssuedAt:  jwt.NewNumericDate(time.Now()),			ExpiresAt: jwt.NewNumericDate(d),			ID:        tokenID,		},	}	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)	tokenString, err := token.SignedString(jwtSecretKey)	if err == nil {		return tokenString, nil	}	return "", err}// CreateUserJWT - creates a user jwt tokenfunc CreateUserJWT(username string, role models.UserRoleID) (response string, err error) {	settings := GetServerSettings()	expirationTime := time.Now().Add(time.Duration(settings.JwtValidityDuration) * time.Minute)	claims := &models.UserClaims{		UserName:       username,		Role:           role,		TokenType:      models.UserIDTokenType,		RacAutoDisable: settings.RacAutoDisable && (role != models.SuperAdminRole && role != models.AdminRole),		RegisteredClaims: jwt.RegisteredClaims{			Issuer:    "Netmaker",			Subject:   fmt.Sprintf("user|%s", username),			IssuedAt:  jwt.NewNumericDate(time.Now()),			ExpiresAt: jwt.NewNumericDate(expirationTime),		},	}	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)	tokenString, err := token.SignedString(jwtSecretKey)	if err == nil {		return tokenString, nil	}	return "", err}func GetUserNameFromToken(authtoken string) (username string, err error) {	claims := &models.UserClaims{}	var tokenSplit = strings.Split(authtoken, " ")	var tokenString = ""	if len(tokenSplit) < 2 {		return "", Unauthorized_Err	} else {		tokenString = tokenSplit[1]	}	if tokenString == servercfg.GetMasterKey() && servercfg.GetMasterKey() != "" {		return MasterUser, nil	}	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {		return jwtSecretKey, nil	})	if err != nil {		return "", Unauthorized_Err	}	if claims.TokenType == models.AccessTokenType {		jti := claims.ID		if jti != "" {			a := schema.UserAccessToken{ID: jti}			// check if access token is active			err := a.Get(db.WithContext(context.TODO()))			if err != nil {				err = errors.New("token revoked")				return "", err			}			a.LastUsed = time.Now()			a.Update(db.WithContext(context.TODO()))		}	}	if token != nil && token.Valid {		var user *models.User		// check that user exists		user, err = GetUser(claims.UserName)		if err != nil {			return "", err		}		if user.UserName != "" {			return user.UserName, nil		}		if user.PlatformRoleID != claims.Role {			return "", Unauthorized_Err		}		err = errors.New("user does not exist")	} else {		err = Unauthorized_Err	}	return "", err}// VerifyUserToken func will used to Verify the JWT Token while using APISfunc VerifyUserToken(tokenString string) (username string, issuperadmin, isadmin bool, err error) {	claims := &models.UserClaims{}	if tokenString == servercfg.GetMasterKey() && servercfg.GetMasterKey() != "" {		return MasterUser, true, true, nil	}	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {		return jwtSecretKey, nil	})	if claims.TokenType == models.AccessTokenType {		jti := claims.ID		if jti != "" {			a := schema.UserAccessToken{ID: jti}			// check if access token is active			err := a.Get(db.WithContext(context.TODO()))			if err != nil {				err = errors.New("token revoked")				return "", false, false, err			}			a.LastUsed = time.Now()			a.Update(db.WithContext(context.TODO()))		}	}	if token != nil && token.Valid {		var user *models.User		// check that user exists		user, err = GetUser(claims.UserName)		if err != nil {			return "", false, false, err		}		if user.UserName != "" {			return user.UserName, user.PlatformRoleID == models.SuperAdminRole,				user.PlatformRoleID == models.AdminRole, nil		}		err = errors.New("user does not exist")	}	return "", false, false, err}// VerifyHostToken - [hosts] Onlyfunc VerifyHostToken(tokenString string) (hostID string, mac string, network string, err error) {	claims := &models.Claims{}	// this may be a stupid way of serving up a master key	// TODO: look into a different method. Encryption?	if tokenString == servercfg.GetMasterKey() && servercfg.GetMasterKey() != "" {		return "mastermac", "", "", nil	}	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {		return jwtSecretKey, nil	})	if token != nil {		return claims.ID, claims.MacAddress, claims.Network, nil	}	return "", "", "", err}
 |