When implementing a custom 401 error page on an authenticated Apache website, the behaviour may not be the same as the default 401 error page.
e.g. Apache directive for a 401 custom error:
ErrorDocument 401 /error_docs/denied.html
Typically, the first access with produce the authentication dialogue box, but if the dialogue box is cancelled refreshes or subsequent attempts to access the page will not show the authentication dialogue box.
Adding meta tags for no-cache or expires fails to resolve the issue.
This can be caused by the Last-Modified and ETag headers added to a default HTML document, in conjunction with a proxy server between the client and server.
The custom 401 error page gets cached on the proxy server, and the proxy server returns 304 (Not Modified) to the client on subsequent attempts, instead of the 401 (Authentication Required) that is expected.
The default error page does not include the Last-Modified and ETag HTTP headers, and so is not cached by the proxy. By default the static html of the custom error page is returned with these tags, and is cached by the proxy. On the second and subsequent loads of the page the proxy will return 304 (Not Modified) instead of 401 (Not Authenticated) as the Last-Modified and ETag headers have not changed.
To resolve the issue, remove the Last-Modified and ETag HTTP headers from custom error pages using "Header unset" and "FileETag None" directives. e.g.
<IfModule !mod_headers.c>
LoadModule headers_module modules/mod_headers.so
</IfModule>
<IfModule mod_headers.c>
<Location /error_docs/*>
# Disable authentication to allow error pages to unauthenticated users
Order allow,deny
Allow from all
AuthType None
Require None
Satisfy Any
# Ensure Proxy does not cache error page and return 304 instead of 401
Header unset Last-Modified
Header unset ETag
FileETag None
</Location>
</IfModule>