PHP + Apache Basic HTTP authentication/limit users to specific directories - php

I'd like to have logged in users access to certain directories only. For example, have the following directory structure:
/stuff/user-a/pic.jpg
/stuff/user-b/file.doc
I'd like Apache to only give user-a access to /stuff/user-a and give a 403 if he tries to reach /stuff/user-b
Now, I've been reading and it seems to be possible to do this with REMOTE_USER and mod_rewrite. Which will make it even better, as i could rewrite it as /stuff -> /stuff/$REMOTE_USER
The problem is, I don't want the ugly browser popup. My PHP application already has a login form and a session. From what I've been reading, it is possible to use basic HTTP authentication as an auth method for PHP (to login as http://user:pass#stackoverflow.com). But the opposite (passing a web form to the HTTP authentication) doesn't seem to be possible.
I would also like to avoid using something as mod_xsendfile, as I'd rather not use any "proxy" scripts to handle this, and let Apache take care of access.

Related

Can I implement a transparent, PHP-based authentication layer with Apache's help?

Background
I'm looking for a transparent, PHP-driven authentication layer for a web site.
I'm aware of the following simple approaches:
HTTP Authentication
Mechanics:
Apache controls access rights;
Attempts to access any file in a given directory transparently require HTTP auth if not already authed.
Downsides:
Limited configuration options;
Difficult to integrate with existing user database;
No control over visual presentation of login prompt.
PHP-based login
Mechanics:
PHP controls access rights;
Attempts to access any file explicitly built for the system if not already authed will result in redirection to a login page.
Downsides:
If I forget to write the required include "login_required.inc.php"; or similar at the top of any PHP file, that file will be accessible by anybody.
What I want
I'd like to implement the PHP-based login solution, but to somehow configure Apache to invoke login_required.inc.php (or similar) transparently as an intermediate step when any PHP file is requested.
This script will:
run;
check session variables;
tell Apache either "yes, produce the requested page" or "no, redirect to the login page";
not require code to be inserted at the top of every PHP script that requires authentication.
Is this a pipe dream? Or can I do it? And if so, how?
If you rewrite all php requests through index.php, index.php/php would then control access to anything.
RewriteRule ^(.*)$ /index.php?pageid=$1 [QSA,L]
Something like that will push any request to index.php, in which you can do your authentication and then it will farm out the content...
The QSA in this will retain any query string parameters etc.
I think you should restructure you website to use a Front Controller. There's a reason that pretty much every framework uses the FrontController pattern: single point of access makes your app simpler.
One possibility is to use .htaccess ModRewrite to redirect all requests to, say, login_required.php?redirect=<ORIGINALLY-REQUESTED-SCRIPT>.
login_required.php can then perform its magic and do one of the following:
Present a login form
include <ORIGINALLY-REQUESTED-SCRIPT>.
Note that a header("Location: <ORIGINALLY-REQUESTED-SCRIPT>)"; will, I believe, merely fall foul of the .htaccess again and cause an infinite redirect loop! Setting the .htaccess ModRewrite directive to only conditionally redirect based on the value of HTTP_REFERER is not secure enough.
This is not the preferred solution, but it's a possibility...
Another possibility:
Have only a single entry-point. Just one file that's accessible from the outside world, like index.php?target=<REQUESTED-SCRIPT>. This one file can contain the authentication logic and include the required script.
All other files would be blocked from external access by .htaccess, or simple file permissions.
This is a good solution, but it would be a large change to update all URLs throughout the existing system.
Edit Apparently this is called the "Front Controller" pattern.

http file access and php sessions

If a site has php session's in place to enforce authentication/authorization to pages on the site which are implemented in php, how does the same logic enforce access to certain files.
Lets say a repository of files in a directory. So /var/www/html/ is protected via authentication however, this PHP authentication logic won't prohibit a user from simply going to http://site.com/someDirectory/fileIShouldNotAccess.txt and pulling that file.
How do you couple the php session and authentication with apache to enforce this type of behavior?
Since PHP won't be invoked when the user requests a non-PHP file, you can't have Apache enforce PHP's access protection. You can make a very coarse and easy-to-fake check in Apache to make sure that a session ID cookie is present, but that's highly insecure. It just checks if the cookie's there, not that it represents a valid session or that the user's actually been granted access.
This other answer might help. Using PHP/Apache to restrict access to static files (html, css, img, etc). Basically, you serve up all the protected content via a PHP script, instead of providing direct access.
A couple answers:
1) make your php sessions use HTTP authentication. Then you can use a .htaccess file to control file access in directories
2) Use mod_rewrite to redirect all requests to a "front controller". Let the front controller manage whether access is allowed, denied, or forwarded to a different controller module for further processing.
You can try HTTP Authentication with PHP. This article might help.

How can I restrict / authorize access to PHP script?

There is this PHP script on my website which I don't want people to be able to run by just typing its name in the browser.
Ideally I would like this script to be run only by registered users and only from within a Windows app (which I will have to provide). Can this be done ?
Alternatively, how can I protect this script so that it can only be called from a specific page or script?
Also how can I hide the exact URI from appearing on the address bar?
Thanks !
If you are running Apache for your webserver, you can protect it with a username/password combo using .htaccess. It takes a little configuration if your server is not already configured to allow .htaccess. Here are the Apache docs.
If you need authentication based on application-specific factors, you can put something at the top of your script like
<?php
if(!$user->isLoggedIn()) {
// do 404
header('HTTP/1.0 404 Not Found');
}
Do you have a question about how you would implement isLoggedIn?
You can also use mod_rewrite to rewrite URIs, and those directives can go inside your .htaccess as well. mod_rewrite can rewrite incoming requests transparently (from the browser's perspective) so a request for /foo/bar can be translated into secret_script.php/foo/bar. Docs for mod_rewrite.
However you decide to implement this, I would urge you to not rely solely on the fact that your script's name is obscure as a means to secure your application. At the very least, use .htaccess with some per-user authentication, and consider having your application authenticate users as well.
As Jesse says, it's possible to restrict your script to logged in users. There are a large number of questions on this already. Search for PHP authentication.
However, it is not possible to restrict it to a single application. It is fairly simple to use a program like Wireshark to see exactly how the program logs in and makes request. At that point, they can reproduce its behavior manually or in their own application.
There are a variety of different ways that you could go about securing a script. All have pluses and minuses, and its likely that the correct answer for your situation will be a combination of several.
Like mentioned, you could lock down the account with Apache...it's a good start. Similarly, you could build a powerful 'salt-ed' security system such as this: http://www.devarticles.com/c/a/JavaScript/Building-a-CHAP-Login-System-An-ObjectOriented-Approach/ If you use SSL as well, you're essentially getting yourself security like banks use on their websites--not perfect, but certainly not easy to break into.
But there are other ideas to consider too. Park your script in a class file that sits inaccessible via direct URI, then do calls to the various functions from an intermediary view script. Not perfect, but it does limit the ways that someone could directly access the file. Consider adding a "qualifier" to the URL via a simple get--have the script check for the qualifier or fail....again, not a great solution on its own, but one additional layer to dissuade the bad guys. If you have control of who's getting access (know exactly which networks) you could even go so far as to limit the IP's or the http referers that are allowed to access the file. Consider setting and checking cookies, with a clear expiration. Don't forget to set your robots file so the browsers don't stumble upon the script your trying to protect.
A while back my company did a membership app using Delphi on the front end, talking to php and MySql on the backend....it was a bit clunky given that we were all web application developers. If you're so inclined, perhaps Adobe Flex might be an option. But ultimately, you'll have to open a door that the application could talk to, and if someone was determined, theoretically they could dig through your app to find the credentials and use them to gain instant access to the site. If you're going the desktop app route, perhaps its time to consider having the app avoid talking to an intermediary script and do its work on the local machine, communicating the db that sits remote.
you can use deny access on .htaccess on a folder with a php authentification that will redirect to those php file

.htaccess authentication from a php script to prevent a browser dialog box

Using php I authenticate a user, then behind the scenes,they are then again authenticated a second time with a single .htaccess username & password. This would be the same for all users, but I would not want them to have to enter a username and password again and they would now be allowed to enter the password protected directory. I prefer not to use http://username#password:somedomain.com.
Any thoughts?
You should not do this.
Either:
Add code to your .htaccess protected directory to use your PHP authentication scheme and remove the .htaccess authentication.
Write a new PHP page/script through which your authenticated users will access all of the protected content. Move the protected content out of the web root, or use your .htaccess file to deny all access. Your script will be able to access the files, but users will have to go through the script to access them.
If you want to avoid multiple logins but need HTTP authentication, you can use only HTTP authentication for the actual login. This is because PHP can issue and respond to such headers.
http://php.net/manual/en/features.http-auth.php
This way the user receives a pop up, PHP can read it and respond accordingly and the browser will pass it with subsequent requests eliminating further prompts.
Note: This solution is not available to CGI versions of PHP.
Sorry, I do not believe this is possible (unless you want to use the username:pass#url scheme). You could write some ajax to do it behind the scenes, which would mean that the browser will remember the auth for that area (maybe, I have never actually tried it). But you would still need the username/pass regardless.
For the security of not transmitting the password in clear text on the browser (I assume you are using https to transmit the password over the network, or if your not you should!) I think it will be a little annoying for the user, but not a huge amount of hassle in my opinion.
Of course you could do the authenticating on that other folder in PHP, which would solve the issue, or put all your protected code in the one place with the one HTTP auth, but I assume you dont want (or cant) do this.

HTTP authentication using PHP authentication

I'm making a members area for my site and I have it already running. I authenticate members using mysql and php and this works really well.
But now problems occurs, I would like to offer members a possibility to upload files to the systems, and those files should be available ONLY to logged in members.
I know I could store those files to a database or even in a filesystem and serve them throught php, BUT this will get very heavy for the server when members upload bigger files. Those files might be even 20MB or even bigger.
I would like to let apache serve the files, but just need to find a way to automatically do the http authentication, so users wouldn't need to log in twice. I suppose it is ok to make this http authentication behind one username and password, something like when a user logs in to the php and mysql authentication, transparently at the same time javascript etc. would do that http authentication also, every member would do the http authentication with the same credentials. Of course I wouldn't want to store those http auth credentials in a javascript file, but something ajax like solution maybe would do the trick. I'm just not sure how to do this.
It seems like you are confusing authentication (where you provide some way to login) with HTTP authentication (where you specifically use the HTTP protocol to authenticate, and the browser shows a popup to the user).
You probably want the former so you can style the login page. In that case you'll have to use PHP or some scripting langauge to check that the user is logged in. fpassthru or readfile can be good solutions for some web sites; they're fast and optimised for this type of work.
If you really want to do the file handling work in the web browser and not in PHP, one solution can be to create unique, short-lived filenames. You can for example create hard links to the file in PHP using link and then redirect the user to the temporary filename. Store the hard links in a database and remove them after a short while.
Check out Using PHP/Apache to restrict access to static files (html, css, img, etc). I think the approach taken there is pretty similar to your problem.

Categories