I don't know if it's possible, but if I don't ask I'll never know :)
I have the exact problem discuted in this topic. That's: I have some static files in some folders and I want only some users to see that content. That users are coming from a previous login.
Some possible solutions are discussed in that topic, but I have thought another possible solution. If I could send with PHP the Authorization HTTP Header, which contains the username and password of the user, and keep it persitent in subsequents requests (as I think it happens with the apache authentication). I would send that headers during my previous login, and then when the user would try to access to its directory, an .htaccess would check if he is a valid user.
I have tried to send the Authorization header with PHP with:
header('Authorization: Basic '.base64_encode($USERNAME.':'.$PASSWORD).PHP_EOL);
But they are only present for one request.
In .htaccess, I have checked that it's not possible to have an unique `Require user USERNAME', so I think it would be necessary to create an htpasswd file storing the same credentials than the ones the login process use, and then create an usual authentication configuration (basic or digest):
AuthType Basic
AuthName "Restricted Files"
AuthUserFile /path/to/htpasswd/file
Require user USERNAME
Thank you in advance
You could have an Basic or Digest HTTP authentification handled by Apache, with a simple "require valid user".
No apache can implement a lot of mod_auth variations, check for mod_auth* in this page.
So you can tell apache to authenticate on your database, or even to perform authentification with a custom code that you provide with mod_authnz_external.
External script support is good as you could implement a session authentification with a cache level (to prevent redoing the whole authentification for each requested resource), which is what basically happen with the default cookie based session (first authenticate, then just transfer the PHPSESSID, so we'll check the session exists).
I have thought another possible solution. If I could send with PHP the Authorization HTTP Header,
You couldn't
Related
I have created an extension for my website. It should log in user to forum after he has logged in to the website.
User session was created successfully (checked in database), but user still not logged in.
If I try to log in with external login form, it works great (the session is created and user is logged in).
I think the problem is not in my authentication extension.
I think I did something wrong with curl post and cookie.
What curl options should I set to login? Or maybe you can give me some useful links?
Take some of those phpbb3_* cookies and then send them through
[setcookie()](php.net/setcookie) to pass along to the user. It
might work, depending on your level of cookie security in phpBB (it
can't be tied to IP because curl and the user IP will be different
drew010
You won't be able to use curl and pass the cookies to the client if you >have Session IP validation turned on. I'd suggest turning that off, or, >instead of using curl, look for a plugin/module that can do 3rd party >logins, or look at the authentication handling code and replicate it. It >wouldn't take much to log a user in without requiring their phpBB password
drew010
To start things off, my server is not running PHP in CGI mode. And even if it was I have the proper mod_rewrite stuff setup (this is a Drupal site).
My problem is that when the user/pass are passed via the URL in the form of http://user:pass#example.com then they do not show up in any of $_SERVER's values. Not PHP_AUTH_USER, not in HTTP_AUTHORIZATION, not in REMOTE_USER, or anywhere else within that super global.
If the credentials are passed via the browser's HTTP basic auth dialog or directly using the base64 encoded Authorization: Basic ZXhhbXBsZTpleGFtcGxl HTTP header then everything works as expected, `$_SERVER['HTTP_AUTH_USER'] is filled out and everything is okay. But if the user/pass are passed via the URL then it's a no go.
Any ideas on what could be going on here?
PHP 5.3.10
Apache 2.2.22
tl;dr: Caching of the 401 Unauthorized response faked me into thinking there was a problem with the authentication code when there wasn't, it was just sending the cached authentication failure response over and over again despite correct credentials. Disabling the caching fixed the problem.
For context, this was all for an API. Basically, Drupal was aggressively caching the responses from the API, including the 401 Unauthorized response. But I didn't notice that the reason authorization was failing was due to the caching, I saw two separate problems: responses were being improperly cached and authorization wasn't working in some situations.
That was on production, so in my development environment I disabled caching for the API and then started to troubleshoot the authorization problem, not realizing I had already solved it. As a debugging method, I short-circuited the responses so that the API wouldn't actually check the HTTP Basic Auth credentials, it would just spew debug info ($_SERVER, mainly). Because the server was no longer sending 401 Unauthorized when it should, Safari wasn't packaging up the user and pass in the URL as a HTTP Authorization header. But I hadn't realized that yet.
So, Safari was working with user/pass in the URL on a site that uses Apache for handling HTTP Basic Auth but it wasn't working with my PHP API. This made me think that Apache was eating the authentication in the URL and not sending it along. This idea is what spawned this question.
Thanks to Basic's and Barmar's comments on the question, I realized my error and tested actually sending the 401 Unauthorized status code and low-and-behold, Safari was working with the user/pass in the URL.
I didn't notice the caching while I was developing the API because I was logged into the Drupal site the API is built on and Drupal only does the full page caching for anonymous users. Interestingly, even the Chrome app, Postman, which acts like a separate application, sends your cookies from the main Chrome application. I didn't even realize that I was logged into the site when I sent requests with it.
http://httpd.apache.org/docs/2.2/howto/auth.html
Are you requiring a valid-user? in a block like this.
AuthType Basic
AuthName "By Invitation Only"
# Optional line:
AuthBasicProvider file
AuthUserFile /usr/local/apache/passwd/passwords
AuthGroupFile /usr/local/apache/passwd/groups
Require group GroupName
Can you post the relevant httpd.conf block?
This is a two part question.
The first question is. I am looking for a way to shield my php pages using one of these generic login boxes that appear without a real page / html form. Like this box here. What is the name of this? How is it done?
The second is. I want to CRON to visit this password page, and kick off a php script.
The dialog shows up for HTTP "Basic" or "Digest" authentication. This should not be used for anything serious. The "Basic" authentication sends passwords in the clear to the server. "Digest" is somewhat better, but there is no way for a user to detect whether the password he's supplying will be used for Basic or Digest (it might not even be clear to the user whether he's authenticating with an HTTP or HTTPS server).
Finally, most browsers offer only very obscure ways to clear a password for these authentication methods once it has been typed in. There is no way for the website itself to force a "log out" purge. So users who need to use shared/public computers will not be able to log out afterwards.
http://php.net/manual/en/features.http-auth.php
It sounds like you're referring to basic HTTP authentication.
If you're using the Apache webserver, use this documentation to help you set it up.
In general, URIs may contain authentication details and HTTP will accept these.
Form your URL like:
http://<username>:<password>#hostname/path
You may be better-off using CodeIgniter's built-in authentication facilities.
This is called HTTP Basic Authentication. Basic authentication can be invoked through PHP (as Timur suggested), or through Apache.
AuthType Basic
AuthName "Restricted Files"
AuthUserFile /usr/local/apache/passwd/passwords
Require user thomasreggi
As for the second part, you can use cron with wget or make cron run your php curl script. Here's a question which shows how to do this.
Sorry for the confusion. To clarify my question, the session will be created over ssl and will stay encrypted. While users browse using normal http, I'm asking if I "require" a ssl page that verifies the users' session, will it run in ssl or will it simply be a part of the parent page which is in http which will be unable to retrieve the session id because the session is saved in https.
I'm currently working on a secure member log in with php.
A log in form will redirect to a ssl url (i.e. https) to keep the password safe for people who are logging in using unencrypted network/wifi.
The only problem is, I can't think of any way to "securely" pass users' log in session from https to http.
So I was thinking to use "require_once" from php which includes a file url starting with https. And the included file will create a session under https and all I have to do is simply require the page in every authentication-required page.
The only issue is, I'm not too sure if the "required file" will run under https or the codes will simply be included in the parent page and run under http.
In other words, how exactly does include or require work (does the function run the code in the separate page or simply include the code in the parent page and run)? I searched php manual, but I was't able to find the answer. Also, I can't test it by myself because I don't have ssl license yet.
Also, any suggestion on building a secure log in using https (just for log in) in combination with http for any other user interface?
include() and require() will only go 'external' and do an HTTP-type request if the path you're providing to them looks like a url (e.g. 'http://....'). Otherwise it's interpreted as a local file file request and does NOT involve the HTTP layer.
There's no practical difference to PHP if a script was requested via HTTP or HTTPS, except there'll be extra SSL-specific entries in $_SERVER. Includes/requires still work as they if the script was running in a non-SSL environment, and the script can still do CURL requests and whatnot. Remember that the SSL link is established by the server and the client browser BEFORE php is invoked, and applies only to do the client<->server communications. Anything the script does with external resources will only involve SSL if the resources requested themselves are done via a completely separate SSL request.
You cannot "turn on" SSL from within a PHP script. There's no mechanism in HTTP to dynamically migrate a link from a regular unencrypted port 80 to an encrypted port 443 within the same request. You can redirect the client towards an SSL url, but that involves a completely new HTTP request - the original request started as non-SSL and will stay non-SSL.
Edit: The below is an answer to the original question, which was phrased in a way that made it sound like the author only wanted the login page to be protected.
I assume that the reason you want to redirect back to HTTP is that the site contents itself isn't confidential, and that you only care about protecting the user's password and account. However, if you redirect the user back to HTTP after logging in, your site will be almost as insecure as if you didn't use HTTPS at all. Granted, HTTPS login will prevent the user's password from being sniffed, but anyone can use Firesheep or similar applications to steal the user's session id after login if you redirect back to HTTP - then, they can take over the account by changing the password (or simply act as the user without changing the password).
(While we're on the subject: why on Earth doesn't StackOverflow use HTTPS after login?) :-(
In order to maintain security, you need to ensure the https:// is in the user's address bar at all times. You can't just include a file and expect it to be secure.
Think of it this way. Say you have a form on http:// and you make a curl call to https:// # Verisign to post a credit card payment. That unencrypted data can easily be intercepted before it reaches Verisign's secure page.
If it's SSL, keep it SSL throughout the entire session. You'll notice on bank sites, there is usually a login button which directs you to an https:// page containing the form - OR they mix it by grabbing your username on the http:// page and then posting that to the https:// page before asking for your password. US Bank does this just to get the user engaged on the home page.
EDIT:
To respond to the new clarification. I would not let a user browse http:// pages while logged in via https://. I would add this logic:
if(isset($_SESSION['LOGGED_IN_SSL']))
{
if ($_SERVER['HTTPS'] != "on")
{
$url = "https://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
header("Location: $url");
exit();
}
}
That would force the user to view the https:// version of whatever page he/she wishes to view.
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.