package middleware import ( "strings" "apskel-pos-be/internal/constants" "apskel-pos-be/internal/contract" "apskel-pos-be/internal/util" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" ) type CustomerAuthMiddleware struct { customerJWTSecret string } func NewCustomerAuthMiddleware(customerJWTSecret string) *CustomerAuthMiddleware { return &CustomerAuthMiddleware{ customerJWTSecret: customerJWTSecret, } } func (m *CustomerAuthMiddleware) ValidateCustomerToken() gin.HandlerFunc { return func(c *gin.Context) { // Get Authorization header authHeader := c.GetHeader("Authorization") if authHeader == "" { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Authorization header is required"), }), "CustomerAuthMiddleware::ValidateCustomerToken") c.Abort() return } // Check if header starts with "Bearer " if !strings.HasPrefix(authHeader, "Bearer ") { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Invalid authorization header format"), }), "CustomerAuthMiddleware::ValidateCustomerToken") c.Abort() return } // Extract token tokenString := strings.TrimPrefix(authHeader, "Bearer ") if tokenString == "" { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Token is required"), }), "CustomerAuthMiddleware::ValidateCustomerToken") c.Abort() return } // Parse and validate token token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { // Validate signing method if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Invalid token signing method") } return []byte(m.customerJWTSecret), nil }) if err != nil { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Invalid token: "+err.Error()), }), "CustomerAuthMiddleware::ValidateCustomerToken") c.Abort() return } // Check if token is valid if !token.Valid { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Token is not valid"), }), "CustomerAuthMiddleware::ValidateCustomerToken") c.Abort() return } // Extract claims claims, ok := token.Claims.(jwt.MapClaims) if !ok { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Invalid token claims"), }), "CustomerAuthMiddleware::ValidateCustomerToken") c.Abort() return } // Validate token type (should be "access") tokenType, ok := claims["type"].(string) if !ok || tokenType != "access" { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Invalid token type"), }), "CustomerAuthMiddleware::ValidateCustomerToken") c.Abort() return } // Extract customer ID customerID, ok := claims["customer_id"].(string) if !ok || customerID == "" { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Customer ID not found in token"), }), "CustomerAuthMiddleware::ValidateCustomerToken") c.Abort() return } // Extract phone number phoneNumber, ok := claims["phone_number"].(string) if !ok || phoneNumber == "" { util.HandleResponse(c.Writer, c.Request, contract.BuildErrorResponse([]*contract.ResponseError{ contract.NewResponseError(constants.ValidationErrorCode, constants.AuthHandlerEntity, "Phone number not found in token"), }), "CustomerAuthMiddleware::ValidateCustomerToken") c.Abort() return } // Set customer information in context c.Set("customer_id", customerID) c.Set("customer_phone", phoneNumber) c.Set("customer_name", claims["name"]) // Continue to next handler c.Next() } }