package middleware // import ( // "strings" // "gitlab.com/mbugroup/lti-api.git/internal/config" // service "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services" // "gitlab.com/mbugroup/lti-api.git/internal/utils" // "github.com/gofiber/fiber/v2" // ) // func Auth(userService service.UserService, requiredRights ...string) fiber.Handler { // return func(c *fiber.Ctx) error { // authHeader := c.Get("Authorization") // token := strings.TrimSpace(strings.TrimPrefix(authHeader, "Bearer ")) // if token == "" { // return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") // } // userID, err := utils.VerifyToken(token, config.JWTSecret, config.TokenTypeAccess) // if err != nil { // return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") // } // // Only end-user subjects are allowed by this middleware. Service tokens // if verification.UserID == 0 { // return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") // } // // Fail-closed on revocation check errors for stricter security posture. // if revoker := session.GetRevocationStore(); revoker != nil { // if fingerprint := session.TokenFingerprint(token); fingerprint != "" { // revoked, err := revoker.IsRevoked(c.Context(), fingerprint) // if err != nil { // utils.Log.WithError(err).Warn("failed to check token revocation") // return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") // } // if revoked { // return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") // } // } // } // user, err := userService.GetBySSOUserID(c, verification.UserID) // if err != nil || user == nil { // return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate") // } // if len(requiredRights) > 0 && verification.Claims != nil { // if !hasAllScopes(verification.Claims.Scopes(), requiredRights) { // return fiber.NewError(fiber.StatusForbidden, "Insufficient scope") // } // } // c.Locals("user", user) // // if len(requiredRights) > 0 { // // userRights, hasRights := config.RoleRights[user.Role] // // if (!hasRights || !hasAllRights(userRights, requiredRights)) && c.Params("userId") != userID { // // return fiber.NewError(fiber.StatusForbidden, "You don't have permission to access this resource") // // } // // } // return c.Next() // } // } // // bearerToken extracts a Bearer token from the Authorization header using // // case-insensitive scheme matching and tolerant whitespace handling. // func bearerToken(c *fiber.Ctx) string { // parts := strings.Fields(c.Get("Authorization")) // if len(parts) == 2 && strings.EqualFold(parts[0], "Bearer") { // return strings.TrimSpace(parts[1]) // } // return "" // } // func hasAllScopes(have, required []string) bool { // if len(required) == 0 { // return true // } // set := make(map[string]struct{}, len(have)) // for _, s := range have { // s = strings.ToLower(strings.TrimSpace(s)) // if s != "" { // set[s] = struct{}{} // } // } // for _, r := range required { // r = strings.ToLower(strings.TrimSpace(r)) // if r == "" { // continue // } // if _, ok := set[r]; !ok { // return false // } // } // return true // }