package handlers import ( "net/http" "github.com/gin-gonic/gin" "go.uber.org/zap" "github.com/kms/api-key-service/internal/domain" "github.com/kms/api-key-service/internal/services" ) // AuthHandler handles authentication-related HTTP requests type AuthHandler struct { authService services.AuthenticationService tokenService services.TokenService logger *zap.Logger } // NewAuthHandler creates a new auth handler func NewAuthHandler( authService services.AuthenticationService, tokenService services.TokenService, logger *zap.Logger, ) *AuthHandler { return &AuthHandler{ authService: authService, tokenService: tokenService, logger: logger, } } // Login handles POST /login func (h *AuthHandler) Login(c *gin.Context) { var req domain.LoginRequest if err := c.ShouldBindJSON(&req); err != nil { h.logger.Warn("Invalid login request", zap.Error(err)) c.JSON(http.StatusBadRequest, gin.H{ "error": "Bad Request", "message": "Invalid request body: " + err.Error(), }) return } // For now, we'll extract user ID from headers since we're using HeaderAuthenticationProvider userID := c.GetHeader("X-User-Email") if userID == "" { h.logger.Warn("User email not found in headers") c.JSON(http.StatusUnauthorized, gin.H{ "error": "Unauthorized", "message": "User authentication required", }) return } h.logger.Info("Processing login request", zap.String("user_id", userID), zap.String("app_id", req.AppID)) // Generate user token token, err := h.tokenService.GenerateUserToken(c.Request.Context(), req.AppID, userID, req.Permissions) if err != nil { h.logger.Error("Failed to generate user token", zap.Error(err)) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Internal Server Error", "message": "Failed to generate token", }) return } // For now, we'll just return the token directly // In a real implementation, this would redirect to the callback URL response := domain.LoginResponse{ RedirectURL: req.RedirectURI + "?token=" + token, } if req.RedirectURI == "" { // If no redirect URI, return token directly c.JSON(http.StatusOK, gin.H{ "token": token, "user_id": userID, "app_id": req.AppID, "expires_in": 604800, // 7 days in seconds }) return } c.JSON(http.StatusOK, response) } // Verify handles POST /verify func (h *AuthHandler) Verify(c *gin.Context) { var req domain.VerifyRequest if err := c.ShouldBindJSON(&req); err != nil { h.logger.Warn("Invalid verify request", zap.Error(err)) c.JSON(http.StatusBadRequest, gin.H{ "error": "Bad Request", "message": "Invalid request body: " + err.Error(), }) return } h.logger.Debug("Verifying token", zap.String("app_id", req.AppID), zap.String("type", string(req.Type))) response, err := h.tokenService.VerifyToken(c.Request.Context(), &req) if err != nil { h.logger.Error("Failed to verify token", zap.Error(err)) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Internal Server Error", "message": "Failed to verify token", }) return } c.JSON(http.StatusOK, response) } // Renew handles POST /renew func (h *AuthHandler) Renew(c *gin.Context) { var req domain.RenewRequest if err := c.ShouldBindJSON(&req); err != nil { h.logger.Warn("Invalid renew request", zap.Error(err)) c.JSON(http.StatusBadRequest, gin.H{ "error": "Bad Request", "message": "Invalid request body: " + err.Error(), }) return } h.logger.Info("Renewing token", zap.String("app_id", req.AppID), zap.String("user_id", req.UserID)) response, err := h.tokenService.RenewUserToken(c.Request.Context(), &req) if err != nil { h.logger.Error("Failed to renew token", zap.Error(err)) c.JSON(http.StatusInternalServerError, gin.H{ "error": "Internal Server Error", "message": "Failed to renew token", }) return } c.JSON(http.StatusOK, response) }