github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/framework/auth/auth.go (about)

     1  package auth
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"strings"
     7  
     8  	"time"
     9  
    10  	"github.com/gin-gonic/gin"
    11  	"github.com/mdaxf/iac/config"
    12  	"github.com/mdaxf/iac/logger"
    13  
    14  	jwt "github.com/dgrijalva/jwt-go"
    15  )
    16  
    17  var jwtsecretKey = "IACFramework"
    18  
    19  func Generate_authentication_token(userID string, loginName string, ClientID string) (string, string, string, error) {
    20  	log := logger.Log{ModuleName: logger.API, User: "System", ControllerName: "Authorization"}
    21  	/*	startTime := time.Now()
    22  		defer func() {
    23  			elapsed := time.Since(startTime)
    24  			log.PerformanceWithDuration("auth.Generate_authentication_token", elapsed)
    25  		}()
    26  		defer func() {
    27  			if r := recover(); r != nil {
    28  				log.Error(fmt.Sprintf("Error in auth.Generate_authentication_token: %s", r))
    29  				return
    30  			}
    31  		}() */
    32  
    33  	log.Debug("Authorization function is called.")
    34  
    35  	//Creating Access Token
    36  	atClaims := jwt.MapClaims{}
    37  	atClaims["authorized"] = true
    38  	atClaims["user_id"] = userID
    39  	atClaims["login_name"] = loginName
    40  	atClaims["client_id"] = ClientID
    41  	fmt.Println(config.SessionCacheTimeout, time.Duration(config.SessionCacheTimeout)*time.Second)
    42  	createdt := time.Now().Format("2006-01-02 15:04:05")
    43  	expiredt := time.Now().Add(time.Duration(config.SessionCacheTimeout) * time.Second)
    44  	expires := expiredt.Unix()
    45  	atClaims["exp"] = expires
    46  
    47  	at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims)
    48  	token, err := at.SignedString([]byte(jwtsecretKey))
    49  	if err != nil {
    50  		log.Error(fmt.Sprintf("Authorization Error:%s", err.Error()))
    51  		return "", "", "", err
    52  	}
    53  	log.Debug(fmt.Sprintf("Authorization Token:%s", token))
    54  	return token, createdt, string(expiredt.Format("2006-01-02 15:04:05")), nil
    55  }
    56  func GetUserInformation(c *gin.Context) (string, string, string, error) {
    57  	log := logger.Log{ModuleName: logger.API, User: "System", ControllerName: "Authorization"}
    58  	//	log.Debug(fmt.Sprintf("Authorization validation function is called for tocken: %s ", tokenString))
    59  	/*	startTime := time.Now()
    60  		defer func() {
    61  			elapsed := time.Since(startTime)
    62  			log.PerformanceWithDuration("auth.GetUserInformation", elapsed)
    63  		}()
    64  		defer func() {
    65  			if r := recover(); r != nil {
    66  				log.Error(fmt.Sprintf("Error in auth.GetUserInformation: %s", r))
    67  				return
    68  			}
    69  		}()  */
    70  	authHeader := c.GetHeader("Authorization")
    71  	if authHeader == "" {
    72  		log.Error(fmt.Sprintf("Missing Authorization header"))
    73  		return "", "", "", nil
    74  	}
    75  
    76  	bearerToken := strings.Split(authHeader, " ")
    77  	if len(bearerToken) != 2 || strings.ToLower(bearerToken[0]) != "bearer" {
    78  		log.Error(fmt.Sprintf("Invalid token format: %s", authHeader))
    79  		return "", "", "", nil
    80  	}
    81  	tokenString := bearerToken[1]
    82  
    83  	// Parse the token
    84  	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
    85  		// Provide the secret key used during token generation
    86  		secretKey := []byte(jwtsecretKey) // Replace with your actual secret key
    87  		return secretKey, nil
    88  	})
    89  	if err != nil {
    90  
    91  		log.Error(fmt.Sprintf("Failed to parse token:%s", err.Error()))
    92  		return "", "", "", err
    93  	}
    94  	if token.Valid {
    95  		// Check if the token has expired
    96  		claims, ok := token.Claims.(jwt.MapClaims)
    97  		if !ok {
    98  
    99  			log.Error(fmt.Sprintf("Invalid token claims: %s", tokenString))
   100  			return "", "", "", err
   101  		}
   102  		UserID := claims["user_id"].(string)
   103  		LoginName := claims["login_name"].(string)
   104  		ClientID := claims["client_id"].(string)
   105  		return UserID, LoginName, ClientID, nil
   106  	}
   107  	return "", "", "", err
   108  }
   109  func ValidateToken(tokenString string) (bool, error) {
   110  	log := logger.Log{ModuleName: logger.API, User: "System", ControllerName: "Authorization"}
   111  	//	log.Debug(fmt.Sprintf("Authorization validation function is called for tocken: %s ", tokenString))
   112  	/*	startTime := time.Now()
   113  		defer func() {
   114  			elapsed := time.Since(startTime)
   115  			log.PerformanceWithDuration("auth.ValidateToken", elapsed)
   116  		}()
   117  		defer func() {
   118  			if r := recover(); r != nil {
   119  				log.Error(fmt.Sprintf("Error in auth.ValidateToken: %s", r))
   120  				return
   121  			}
   122  		}()  */
   123  	// Parse the token
   124  	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
   125  		// Provide the secret key used during token generation
   126  		secretKey := []byte(jwtsecretKey) // Replace with your actual secret key
   127  		return secretKey, nil
   128  	})
   129  	if err != nil {
   130  
   131  		log.Error(fmt.Sprintf("Failed to parse token:%s", err.Error()))
   132  		return false, err
   133  	}
   134  
   135  	// Check if the token is valid
   136  	if token.Valid {
   137  		// Check if the token has expired
   138  		claims, ok := token.Claims.(jwt.MapClaims)
   139  		if !ok {
   140  
   141  			log.Error(fmt.Sprintf("Invalid token claims: %s", tokenString))
   142  			return false, err
   143  		}
   144  
   145  		expirationTime := claims["exp"].(float64)
   146  		expiration := time.Unix(int64(expirationTime), 0)
   147  
   148  		if expiration.Before(time.Now()) {
   149  
   150  			log.Error(fmt.Sprintf("Token has expired: %s", tokenString))
   151  			return false, err
   152  		} else {
   153  			log.Debug(fmt.Sprintf("Token is valid: %s", tokenString))
   154  
   155  		}
   156  	} else {
   157  		log.Error(fmt.Sprintf("Token is invalid: %s", tokenString))
   158  
   159  		return false, err
   160  	}
   161  	return true, nil
   162  }
   163  
   164  func Extendexptime(tokenString string) (string, string, string, error) {
   165  	log := logger.Log{ModuleName: logger.API, User: "System", ControllerName: "Authorization"}
   166  
   167  	/*	startTime := time.Now()
   168  		defer func() {
   169  			elapsed := time.Since(startTime)
   170  			log.PerformanceWithDuration("auth.Extendexptime", elapsed)
   171  		}()
   172  		defer func() {
   173  			if r := recover(); r != nil {
   174  				log.Error(fmt.Sprintf("Error in auth.Extendexptime: %s", r))
   175  				return
   176  			}
   177  		}()
   178  	*/
   179  	log.Debug(fmt.Sprintf("Extend the token function is called for tocken: %s ", tokenString))
   180  
   181  	// Parse the token
   182  	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
   183  		// Provide the secret key used during token generation
   184  		secretKey := []byte(jwtsecretKey) // Replace with your actual secret key
   185  		return secretKey, nil
   186  	})
   187  
   188  	if err != nil {
   189  
   190  		log.Error(fmt.Sprintf("Failed to parse token:%s", err.Error()))
   191  		return "", "", "", err
   192  	}
   193  
   194  	// Check if the token is valid and has not expired
   195  	if !token.Valid {
   196  		log.Error(fmt.Sprintf("Token is invalid: %s", tokenString))
   197  		return "", "", "", err
   198  	}
   199  
   200  	// Get the current time
   201  	now := time.Now()
   202  
   203  	// Calculate the new expiration time (e.g., extend it by 1 hour from the current time)
   204  	expirationTime := now.Add(time.Duration(config.SessionCacheTimeout) * time.Second)
   205  
   206  	// Update the "exp" (expiration) claim in the token with the new expiration time
   207  	claims := token.Claims.(jwt.MapClaims)
   208  	claims["exp"] = expirationTime.Unix()
   209  
   210  	// Create a new token with the updated claims
   211  	newToken := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
   212  
   213  	// Sign the new token with the secret key to get the final token string
   214  	newTokenString, err := newToken.SignedString([]byte(jwtsecretKey))
   215  	if err != nil {
   216  		log.Error(fmt.Sprintf("Create new token Error:%s", err.Error()))
   217  		return "", "", "", err
   218  	}
   219  	log.Debug(fmt.Sprintf("New Token:%s, createdon %s, exp: %s", newTokenString, now.Format("2006-01-02 15:04:05"), expirationTime.Format("2006-01-02 15:04:05")))
   220  	return newTokenString, now.Format("2006-01-02 15:04:05"), expirationTime.Format("2006-01-02 15:04:05"), nil
   221  }
   222  
   223  func AuthMiddleware() gin.HandlerFunc {
   224  	log := logger.Log{ModuleName: logger.API, User: "System", ControllerName: "Authorization"}
   225  	/*	startTime := time.Now()
   226  		defer func() {
   227  			elapsed := time.Since(startTime)
   228  			log.PerformanceWithDuration("auth.AuthMiddleware", elapsed)
   229  		}()
   230  		defer func() {
   231  			if r := recover(); r != nil {
   232  				log.Error(fmt.Sprintf("Error in auth.AuthMiddleware: %s", r))
   233  				return
   234  			}
   235  		}()
   236  	*/
   237  	log.Debug(fmt.Sprintf("Authorization for the API call"))
   238  
   239  	return func(c *gin.Context) {
   240  		// Get the token from the Authorization header
   241  		authHeader := c.GetHeader("Authorization")
   242  		//	log.Debug(fmt.Sprintf("Authorization Header:%s %s", authHeader, c.Request.URL.Path))
   243  
   244  		if c.Request.URL.Path == "/favicon.ico" || c.Request.URL.Path == "/user/login" || c.Request.URL.Path == "/user/changepwd" || strings.Contains(c.Request.URL.Path, "/user/image") || strings.Contains(c.Request.URL.Path, "/portal") {
   245  			//	c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Missing Authorization header"})
   246  			return
   247  		} else if authHeader == "" {
   248  			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Missing Authorization header"})
   249  			return
   250  		}
   251  
   252  		bearerToken := strings.Split(authHeader, " ")
   253  		//	log.Debug(fmt.Sprintf("Authorization Header:%s", bearerToken))
   254  		if len(bearerToken) != 2 || (strings.ToLower(bearerToken[0]) != "bearer" && strings.ToLower(bearerToken[0]) != "apikey") {
   255  			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token format"})
   256  			return
   257  		}
   258  		authtype := strings.ToLower(bearerToken[0])
   259  		tokenString := bearerToken[1]
   260  
   261  		if authtype == "apikey" {
   262  			if tokenString != config.ApiKey {
   263  				c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid APIKey"})
   264  				return
   265  			}
   266  		} else {
   267  			ok, err := ValidateToken(tokenString)
   268  
   269  			if err != nil || !ok {
   270  				c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid or expired token"})
   271  				return
   272  			}
   273  		}
   274  		/*
   275  			// Parse the JWT token
   276  			token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
   277  				// Validate the signing method and return the secret key
   278  				if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
   279  					return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
   280  				}
   281  
   282  				return []byte(secretKey), nil
   283  			})
   284  
   285  			if err != nil || !token.Valid {
   286  				c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid or expired token"})
   287  				return
   288  			}
   289  
   290  			// If the token is valid, set the token claims in the Gin context for further use
   291  			if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
   292  				c.Set("userID", claims["userID"])
   293  			} */
   294  
   295  		c.Next()
   296  	}
   297  }
   298  
   299  func protectedHandler(c *gin.Context) {
   300  	// This is the protected REST API endpoint.
   301  	// You can access the userID from the context.
   302  	log := logger.Log{ModuleName: logger.API, User: "System", ControllerName: "Authorization"}
   303  	/*	startTime := time.Now()
   304  		defer func() {
   305  			elapsed := time.Since(startTime)
   306  			log.PerformanceWithDuration("auth.protectedHandler", elapsed)
   307  		}()
   308  		defer func() {
   309  			if r := recover(); r != nil {
   310  				log.Error(fmt.Sprintf("Error in auth.protectedHandler: %s", r))
   311  				return
   312  			}
   313  		}() */
   314  	log.Debug(fmt.Sprintf("Authorization the user"))
   315  
   316  	userID, _ := c.Get("userID")
   317  
   318  	// You can implement your logic here to process the request for the authenticated user.
   319  	c.JSON(http.StatusOK, gin.H{"message": "Hello, user " + userID.(string)})
   320  
   321  }