How can I serve files from the filesystem but enforce user authentication?

So I want to upload files to domain.com/secure/attachment/<attachment_id>/<attachment_filename>.<extension>. So if a user_a uploads "screenshot.jpg" it would live at domain.com/secure/attachment/5154234/screenshot_5154234.jpg. If the user_a wanted to view this file they could navigate to this url in their browser. My question is, how can I serve these files from the filesystem while enforcing user authentication/authorization so that user_a can view the file because they're authorized and logged in to the system but user_b can't because either 1) he isn't logged in or 2) he's not authorized?

As a real life example, JIRA implements this method.

As a side note, this seems interesting because, how could your run this kind of logic when the uri is to a jpeg and not a php script.

Please include code examples.
LVL 1
aristanobleAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ray PaseurCommented:
...uri is to a jpeg and not a php script

A URI represents an HTTP request.  The request (usually GET or POST method) is sent to the server.  The server responds in any way that it sees fit.  The server may have rewrite rules that (for example) see requests for .jpg files and send the requests to an intermediate client authentication script.  This is one way that a server could respond.  But most servers are configured to simply serve up the image files.

If you want to keep image files away from people, the only secure answer is, "Do not put those files on the internet."  Once you have sent an image file to a client browser you have released it into the wild.  You have no more control over the file.  The client can copy it, store it, modify it, re-transmit it, republish it, etc.  Your only protections against these actions are the legal system.  And as we have seen many times in the last two decades the legal system is not a nimble match for technologists who would choose to ignore it.

My advice would be to have a data base that handled client authentication and held two other tables.  One is the table that gives the file paths to all the uploaded files.  The other table is the junction table that relates authorized clients and uploaded files.  When a client requests a directory listing, he is shown the files that are permitted to his client identity.  When the client requests a file, he is given access via an authentication script that checks the junction table for the appropriate relationship before it serves the file.

If you keep the files outside of the web root directory tree and serve the files via the authentication script, you will be fairly secure.

HTH, ~Ray

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
aristanobleAuthor Commented:
serve the files via the authentication script


So, is that to say the files will be served as /files.php?file_id=khj4344gkj2, for example, and I would perform the authentication in that script before I serve the file?

If so, how would I serve up various filetypes (images, pdfs, zips, etc...) through that script?
Slick812Commented:
greetings aristanoble, , , This may not be a straight forward code setup for you, since you will need to have error control for -
1. No Sign In, Not a Logged In User asks for a restricted file.
2  User that wants to get something (file) that he does Not have rights to.
3. Asks for a file that does not exist, or is in the wrong location (directory).

Since you ask for - "how would I serve up various filetypes"  in your post here is some code that may help you, although it DOES NOT do any User access verification, this just does some verification for the GET input and if the file exists -

// User verification would go FIRST, maybe using a Session variable

$dir = (empty($_GET['loca'])) ? '?' : $_GET['loca'];
$fl = (empty($_GET['fl'])) ? '?' : $_GET['fl'];
$ext = (empty($_GET['ext'])) ? '?' : $_GET['ext'];

// ERROR out with a 404 status and error page as =
$error = '<html><head><title>404 ERROR - File Does NOT Exist</title></head><body><h2>ERROR 404 - File Does NOT Exist on this Server</h2></body></html>';


if (($dir == '?') || ($fl == '?') || ($ext == '?')) {
	header('Status: 404  Not Found');
	echo $error;
	exit;
	}

switch($ct){
	case 'jpg': $type = 'Content-Type: image/jpeg'; break;
	
	case 'png': $type = 'Content-Type: image/png'; break;
	
	case 'pdf': $type = 'Content-Type: document/pdf'; break;
	
// ERROR out if it is NOT an approved extention
	default: header('Status: 404  Not Found');
	echo $error;
	exit;
	}

// ERROR out if NOT a valid file path
if (!file_exists ('/home/domain/userF/'.$dir.'/'.$fl.$ext)) {
	header('Status: 404  Not Found');
	echo $error;
	exit;
	}

$fl = file_get_contents('/home/domain/userF/'.$dir.'/'.$fl.$ext);
// Error out if problems getting file
if (($fl === false) || (strlen($fl) < 2)) {
	header('Status: 404  Not Found');
	echo $error;
	exit;
	}

// For any file you absolutly MUST set the file TYPE in header
header($type);
echo $fl;

Open in new window



Ask questions if you need more info or explanation
Slick812Commented:
sorry the line -

switch($ct){

should be

switch($ext){
aristanobleAuthor Commented:
Thank you both.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.