I had an issue recently that had the same symptoms: EE + Freeform and I was always getting the error message, "This form has expired. Please refresh and try again." I was not using any ExpressionEngine caching. I was, however, using AWS Cloudfront and even though I was excluding the pages with my form from being cached by Cloudfront, I was still getting the error.
The issue turned out to be that Cloudfront was not passing through query strings and cookie data that Freeform Next / Freeform Pro was expecting. As such, even though the CSRF token was valid and included in the POST data, other data was missing. I updated my Cloudfront behaviors to pass through all query string and cookie data which can decrease performance, but since I don't want pages with CSRF tokens cached, anyway, is something I am willing to suffer.
If you are using Cloudfront, here are the steps I used that solved my problem:
- In your Cloudfront distribution, add a new behavior
- Set the correct path pattern
- Set "Allowed HTTP Methods" to "GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE" (this ensures that POST data can still be sent)
- Set "Cache Based on Selected Request Headers" to "All" (this prevent the matching resource from being cached)
- Set "Forward Cookies" to "All"
- Set "Query String Forwarding and Caching" to "Forward all, cache based on all"
- Save the behavior and wait for it to be deployed to the edge caches
Your mileage may vary based on your specific setup, but if you've tried everything else, look and see if you might have a similar issue with query string and/or cookie forwarding.