Ver código fonte

fix revoked tokens to be unauthorized

abhishek9686 5 meses atrás
pai
commit
c88469b4a5
4 arquivos alterados com 31 adições e 21 exclusões
  1. 3 2
      controllers/user.go
  2. 2 3
      logic/auth.go
  3. 15 16
      logic/jwts.go
  4. 11 0
      models/user_mgmt.go

+ 3 - 2
controllers/user.go

@@ -7,6 +7,7 @@ import (
 	"net/http"
 	"reflect"
 
+	"github.com/google/uuid"
 	"github.com/gorilla/mux"
 	"github.com/gorilla/websocket"
 	"github.com/gravitl/netmaker/auth"
@@ -82,8 +83,8 @@ func createUserAccessToken(w http.ResponseWriter, r *http.Request) {
 		logic.ReturnErrorResponse(w, r, logic.FormatError(errors.New("user is registered via SSO"), "badrequest"))
 		return
 	}
-	jwt, err := logic.CreateUserJWTWithExpiry(user.UserName, user.PlatformRoleID, req.ExpiresAt)
-
+	req.ID = uuid.New().String()
+	jwt, err := logic.CreateUserAccessJwtToken(user.UserName, user.PlatformRoleID, req.ExpiresAt, req.ID)
 	if jwt == "" {
 		// very unlikely that err is !nil and no jwt returned, but handle it anyways.
 		logic.ReturnErrorResponse(

+ 2 - 3
logic/auth.go

@@ -8,7 +8,6 @@ import (
 	"time"
 
 	"github.com/go-playground/validator/v10"
-	"github.com/google/uuid"
 	"golang.org/x/crypto/bcrypt"
 	"golang.org/x/exp/slog"
 
@@ -166,7 +165,7 @@ func RevokeAllUserTokens(username string) {
 }
 
 func GetAccessToken(k string) (a models.AccessToken, err error) {
-	value, err := database.FetchRecord(k, database.ACCESS_TOKENS_TABLE_NAME)
+	value, err := database.FetchRecord(database.ACCESS_TOKENS_TABLE_NAME, k)
 	if err != nil {
 		return
 	}
@@ -196,7 +195,7 @@ func ListAccessTokens(username string) (tokens []models.AccessToken) {
 }
 
 func CreateAccessToken(a models.AccessToken) error {
-	a.ID = uuid.New().String()
+
 	data, err := json.Marshal(a)
 	if err != nil {
 		logger.Log(0, "failed to marshal", err.Error())

+ 15 - 16
logic/jwts.go

@@ -53,10 +53,11 @@ func CreateJWT(uuid string, macAddress string, network string) (response string,
 }
 
 // CreateUserJWT - creates a user jwt token
-func CreateUserJWTWithExpiry(username string, role models.UserRoleID, d time.Time) (response string, err error) {
+func 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.ServerInfo.APIHost,
 		RacAutoDisable: servercfg.GetRacAutoDisable() && (role != models.SuperAdminRole && role != models.AdminRole),
 		RegisteredClaims: jwt.RegisteredClaims{
@@ -64,6 +65,7 @@ func CreateUserJWTWithExpiry(username string, role models.UserRoleID, d time.Tim
 			Subject:   fmt.Sprintf("user|%s", username),
 			IssuedAt:  jwt.NewNumericDate(time.Now()),
 			ExpiresAt: jwt.NewNumericDate(d),
+			ID:        tokenID,
 		},
 	}
 
@@ -81,6 +83,7 @@ func CreateUserJWT(username string, role models.UserRoleID) (response string, er
 	claims := &models.UserClaims{
 		UserName:       username,
 		Role:           role,
+		TokenType:      models.UserIDTokenType,
 		RacAutoDisable: servercfg.GetRacAutoDisable() && (role != models.SuperAdminRole && role != models.AdminRole),
 		RegisteredClaims: jwt.RegisteredClaims{
 			Issuer:    "Netmaker",
@@ -98,18 +101,6 @@ func CreateUserJWT(username string, role models.UserRoleID) (response string, er
 	return "", err
 }
 
-// VerifyJWT verifies Auth Header
-func VerifyJWT(bearerToken string) (username string, issuperadmin, isadmin bool, err error) {
-	token := ""
-	tokenSplit := strings.Split(bearerToken, " ")
-	if len(tokenSplit) > 1 {
-		token = tokenSplit[1]
-	} else {
-		return "", false, false, errors.New("invalid auth header")
-	}
-	return VerifyUserToken(token)
-}
-
 func GetUserNameFromToken(authtoken string) (username string, err error) {
 	claims := &models.UserClaims{}
 	var tokenSplit = strings.Split(authtoken, " ")
@@ -154,15 +145,23 @@ func GetUserNameFromToken(authtoken string) (username string, err error) {
 // VerifyUserToken func will used to Verify the JWT Token while using APIS
 func 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 != "" {
+			// check if access token is active
+			_, err := GetAccessToken(jti)
+			if err != nil {
+				err = errors.New("token revoked")
+				return "", false, false, err
+			}
+		}
+	}
 	if token != nil && token.Valid {
 		var user *models.User
 		// check that user exists

+ 11 - 0
models/user_mgmt.go

@@ -13,6 +13,7 @@ type RsrcID string
 type UserRoleID string
 type UserGroupID string
 type AuthType string
+type TokenType string
 
 var (
 	BasicAuth AuthType = "basic_auth"
@@ -35,6 +36,15 @@ func GetRAGRoleID(netID, hostID string) UserRoleID {
 	return UserRoleID(fmt.Sprintf("netID-%s-rag-%s", netID, hostID))
 }
 
+func (t TokenType) String() string {
+	return string(t)
+}
+
+var (
+	UserIDTokenType TokenType = "user_id_token"
+	AccessTokenType TokenType = "access_token"
+)
+
 var RsrcTypeMap = map[RsrcType]struct{}{
 	HostRsrc:           {},
 	RelayRsrc:          {},
@@ -186,6 +196,7 @@ type UserClaims struct {
 	Role           UserRoleID
 	UserName       string
 	Api            string
+	TokenType      TokenType
 	RacAutoDisable bool
 	jwt.RegisteredClaims
 }