Forum Moderators: phranque

Message Too Old, No Replies

401 error document within protected directory - possible?

Can you use htpasswd to protect the web root?

         

HappyDog

1:30 am on Apr 6, 2005 (gmt 0)

10+ Year Member



I want to use .htpasswd to offer a simple protection to my entire website. I have set up .htaccess in the web root, using a .htpasswd file located in a secure directory, and everything works fine.

However, I now want to add a custom error document to respond to error 401 - authorisation required (i.e. if the user cancels the login).

The problem is that I can't use an external URL for the file as that is not allowed for 401 error documents, and I can't use a local file as the path is relative to the web root, not the server root, so any such file is protected by .htpasswd - catch 22!

The file I want to use is pretty big, so it's not very practical to include it as text in the ErrorDocument directive (which must all be on the same line).

If I could disable authentication for a sub-directory of the site then I could put the error document there, but I can't find any way of doing this.

Is it possible at all?

- Mark

jdMorgan

2:47 am on Apr 6, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Mark,

Welcome to WebmasterWorld!

You can use the "Satisfy any" directive, combined with SetEnvIf, to allow unlimited access to the 401 document. See Apache core, mod_auth, and mod_setenvif. There's also an Authentication, Authorization, and Access Control tutorial on the Apache site that's pretty good.

Jim

HappyDog

4:05 am on Apr 6, 2005 (gmt 0)

10+ Year Member



Thanks for the quick response, Jim.

I have got it working, thanks to your advice, but I don't know if it's the optimal solution. Here's what I've done.

I created a directory called /error_docs/ and put my error file (401.htm) into it. My root-level .htaccess now uses 'ErrorDocument 401 /error_docs/401.htm' to point to that file, but is otherwise unchanged.

I then created a new .htaccess file in the error_docs directory, which contains the following:

SetEnvIf Remote_Host "\." allow_all
Allow from env=allow_all
Satisfy Any

This essentially means that this entire directory is always readable, as the remote host will always contain a period.

Everything seems to work as I intend now, but are there any other improvements that you think I should make? For instance, is it possible to somehow store 401.htm in the site root (as the only unprotected file), as it is a bit annoying to have a separate directory for a single file. Also, does this open up any security risks that I should be aware of?

- Mark

jdMorgan

1:05 pm on Apr 6, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I'd recommend against using Remote_Host under any circumstances where it is not required. The reason for this is that it invokes a reverse-DNS lookup of the requesting IP address. This means your server must issue a request to the DNS system (just like your browser does) and await a response before proceeding any further. It is slow, and introduces unnecessary external dependencies.

What I had in mind was something like:


SetEnvIf Request_URI "^/401\.html$" allow_all
Satisfy Any
Allow from env=allow_all

or, even better:

SetEnvIf Request_URI "^/([45][01][0-9]\.html¦robots.txt¦w3c/p3p.xml)$" allow_all
Satisfy Any
Allow from env=allow_all

This allows unfettered access to all 400- and 500-series error documents, plus robots.txt and your p3p.xml privacy policy.

Neither of these requires a special error-page subdirectory -- In fact, you can't put robots.txt in a subdirectory anyway, and the p3p policy should be located in /w3c/p3p.xml relative to your Web root.

If you do want to use a subdirectory and make separate arrangements for allowing robots.txt and p3p.xml access, then you could place a much simpler .htaccess routine in that subdirectory:


Satisfy Any
Allow from all

Since there is nothing in that directory that you want to deny access to, no further restrictions are required. The .htaccess code only applies to that subdirectory and any subdirectories of that subdirectory.

Replace all broken pipe "¦" characters above with solid pipe characters (usually Shift-\) before use. Posting on this board modifies them.

Jim

HappyDog

2:09 pm on Apr 6, 2005 (gmt 0)

10+ Year Member



Cheers for the tip about Remote_Host - I didn't think of that issue.

The examples you gave don't seem to work, however. I have stripped my .htaccess file to just the directives which password protect the site, and that works OK, but simply adding the Satisfy Any line (without any further conditions) allows full access. Here's what I've got:

AuthUserFile {path to .htaccess}
AuthGroupFile /dev/null
AuthName "site"
AuthType Basic
require valid-user

Satisfy Any

Presumably there is some other directive at a higher level that is allowing the pass-through, as there is only one access restriction in the file itself. Is there anything I can do about that? Do you have any idea what it might be?

- Mark

jdMorgan

5:16 pm on Apr 6, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



> allows full access.

Allows full access to what - the whole site?

There are three concerns with access control code: What is the code, where is the code, and where are the files that the code acts upon?

If you have the custom error pages in a separate subdirectory, with the code in an .htaccess file in that subdirectory, then only those files should be made accessible by that code, unless as you say, there's something funny in the server config.

The other examples assumed that the error files were not is a separate subdirectory. If they are, then you'll need to include the full path to the file in the Request_URI pattern. That is,


SetEnvIf Request_URI "^/([b]error-subdirectory/[/b][45][01][0-9]\.html¦robots.txt¦w3c/p3p.xml)$" allow_all

Also, I assume this is a typo:
> AuthUserFile {path to .htaccess}
(It should be "path to .htpasswd")

Jim

HappyDog

10:46 pm on Apr 6, 2005 (gmt 0)

10+ Year Member



Sorry Jim, I wasn't being terribly clear there (and yes, you're right - that was a typo.)

In the example given it does not matter where the error documents are, as they are not referenced at all.

The example .htaccess code is the ONLY code in the .htaccess file in my web root, and there are no other .htaccess files present below this directory (and none above this directory in the directories that I control. However, there may be other directives in .conf files (or similar) outside my control).

The point is that without the Satisfy Any line, any requests for a file are met be a username/password prompt in the browser. However, if that line is present then all requests are granted without a prompt, even though there are no other access conditions specified in my code.

- Mark

jdMorgan

2:38 am on Apr 7, 2005 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hmm...

Well, putting it all together, the following should work if placed in .htaccess in your root directory:


ErrorDocument 401 /error-subdirectory/401.html
AuthType Basic
AuthName "site"
AuthUserFile <path to .htpasswd>
AuthGroupFile /dev/null
Require valid-user
SetEnvIf Request_URI "^/(error-subdirectory/401\.html¦robots\.txt)$" allow_all
Order allow,deny
Allow from env=allow_all
Satisfy any

If that doesn't work, I'd suggest you consult with your server admin, 'cause I sure don't know why it wouldn't work.

Replace all broken pipe "¦" characters above with solid pipe characters (usually Shift-\) before use. Posting on this board modifies them.

Jim

HappyDog

2:59 am on Apr 7, 2005 (gmt 0)

10+ Year Member



Hi Jim

That's got it working - thanks!

The key thing was the Order allow,deny directive. With that in place the problems from my previous post vanished and everything's slipped into place. I now have a 401.htm file in my root directory which appears when the authentication fails, and the rest of the site is password protected.

Once again, thank you for all your help.

- Mark