I have protected a page. When someone wants to view it, WP shows up the "This post is password protected. To view it please enter your password below" prompt. After the visitor enters the passwords and submits the form, he faces the same login page again and again ... until he forces the browser to reload. The problem is reproducible.
What I found out is that the problem appears to be a caching issue. When the visitor first accesses the page, WP detects the protection and displays the password prompt. This is done by the get_the_content() function in post-template.php when it calls get_the_password_form(). I believe the root cause of the problem is that at this point the HTTP headers have been setup (maybe even sent) to show a normal page which is subject to be cached. If your reverse proxy or your visitors proxy or browser does cache the page with the password form login appearance, then the problem will show up later. Once the visitor enters the password, the form is submitted to wp-pass.php which essentially takes the POST request and redirects the user to the referring page. Bingo! The referring page is the page the visitor wanted to see but was rendered with the password dialog - and this page has been cached so the password dialog shows up again ... until shift-reload enforces cache invalidation.
My quick and dirty workaround is to add a question mark to the URL wp-pass.php redirects the user to. A question mark is usually a visual annoyance only and it inhibits some caches from actually caching something at all and it effectively creates a new URL which shouldn't have been cached previously. The trick adds a '?' for every login attempt. Dirty.
--- wp-pass.php.orig +++ wp-pass.php @@ -10,2 +10,2 @@ -wp_redirect(wp_get_referer()); +wp_redirect(wp_get_referer() . '?');
The real solution would be to move or dup the page protection logic from get_the_content() to an earlier point where a call to nocache_headers() yields effect. Or defer sending out the headers past the password decision for the same reason. This requires deeper insight in the WP logic which I do not currently have.