I used to work for a bank, that had a very cool feature in it's intranet. Once you logged in your computer, there were global variables set in PHP through Apache, and they contained the identity of the user that was logged on on the computer. Now I'm at a new job, and I'm wondering, how this thing worked! I would like to implement this kind of thing once again.
What I'm working with here:
FreeBSD server, version is unknown to me.
Apache 2.2 web server
PHP 5, some custom compilation, that for various reasons, I can't upgrade or modify.
MS AD
All of the users logging on to their computers are using active directory, all are in the same domain.
What I used to have was something like this:
echo $_SERVER['username']
which would print the username of the user currently logged in.
Could someone explain, how this could be done?
P.S. If any of my server settings are not what is required, say so, because then I will have a reason to ask the bosses to give me one of my own, with more control.
There's lots of ways this might be implemented. However a lot of them depend on having control over the client as well as the server.
Obvious sources of data include:
NTLM
Client side certificates
The Ident protocol (not very secure without the encryption extensions)
A long lasting cookie (again, not secure)
HTTP authentication methods
However none of these explain how the value appeared in the session - this must have been implemented within the PHP code.
So without knowing how it was implemented at your previous site we can't tell you:
Whether it was secure and correctly implemented
how to replicate the behaviour
Given your resource list, while it would be possible to implement authentication based on direct LDAP calls, passing the username and password through your application, I would strongly recommend using (e.g.) openId - but restricting the providers to just your openid provider - which would use the MSAD as the backend.
I did not understand correctly the question, so I edit my post...
you could use apache auth, you can make auth by ip's or hostnames
http://httpd.apache.org/docs/2.0/en/howto/auth.html
Related
We have a sharepoint instance on our network that we get automatically logged into by logging into Windows. (they do not get prompted to log in)
We have another web application that requires users to log in but it currently has it's own username/password setup.
Our goal is to get the other application (which we have built) to act the same way sharepoint does - if you are logged into windows it will log you right into the application.
Where do I start? (I assume this will require LDAP)
Any guidance would be greatly appreciated.
Our setup (windows):
Windows
IE7 & 8
Windows Active Directory managing users/password
Our setup (the other application):
RHEL (could be Windows Server if really necessary)
PHP 5
Apache
mySQL - username and password are stored in mySQL
Update:
Maybe a drawing would help: Look at this
You are looking to implement NTLM Authentication in the PHP application, see my prior answer on this:
Can a PHP intranet share Windows logins?
If your other web application uses Windows Integrated Authentication (NTLM or Kerberos authentication or even basic authentication) then it can act the same way. Depending on the browser, it can automatically remember and log into sites using one of these methods. Each browser may do it differently, though. IE has settings for automatically logging in based on the zone (Internet, Local intranet, trusted sites).
You would not necessarily need to have the have your other application use the same user store (AD/LDAP), but it would likely make sense.
I'm vaguely aware that on a computer joined to a domain IE can be asked to send some extra headers that I could use to automatically sign on to an application. I've got apache running on a windows server with mod_php. I'd like to be able to avoid the user having to log in if necessary. I've found some links talking about Kerberos and Apache modules.
http://www.onlamp.com/pub/a/onlamp/2003/09/11/kerberos.html?page=last
https://metacpan.org/pod/Apache2::AuthenNTLM
Since I'm running on Windows it's proven to be non-trivial to get Perl or Apache modules installed. But doesn't PHP already have access to HTTP headers?
I found this but it doesn't do any authentication, it just shows that PHP can read the NTLM headers.
http://siphon9.net/loune/2007/10/simple-lightweight-ntlm-in-php/
I'd like to be able to have my users just point to the application and have them automatically authenticated. Has anyone had any experience with this or gotten it to work at all?
UPDATE
Since originally posting this question, we've changed setups to nginx and php-fcgi still running on windows. Apache2 and php-cgi on windows is probably one of the slowest setups you could configure on windows. It's looking like Apache might still be needed (it works with php-fcgi) but I would prefer a nginx solution.
I also still don't understand (and would love to be educated) why HTTP server plugins are necessary and we can't have a PHP, web server agnostic solution.
All you need is the mod_auth_sspi Apache module.
Sample configuration:
AuthType SSPI
SSPIAuth On
SSPIAuthoritative On
SSPIDomain mydomain
# Set this if you want to allow access with clients that do not support NTLM, or via proxy from outside. Don't forget to require SSL in this case!
SSPIOfferBasic On
# Set this if you have only one domain and don't want the MYDOMAIN\ prefix on each user name
SSPIOmitDomain On
# AD user names are case-insensitive, so use this for normalization if your application's user names are case-sensitive
SSPIUsernameCase Lower
AuthName "Some text to prompt for domain credentials"
Require valid-user
And don't forget that you can also use Firefox for transparent SSO in a Windows domain: Simply go to about:config, search for network.automatic-ntlm-auth.trusted-uris, and enter the host name or FQDN of your internal application (like myserver or myserver.corp.domain.com). You can have more than one entry, it's a comma-separated list.
I'd be curious about a solution that uses OpenID as a backend (of sorts) for this... I wasn't seeing anything that would hook into ActiveDirectory directly when I googled (quickly). However, it could be pretty painless to implement over plain HTTP(S) (you'd be an OpenID provider that checked credentials against your local AD). In a best case scenario, you might be able to just add a couple classes to your app and be off and running -- no web server modules required. There is a lot of open source code out there for either side of this, so if nothing else, it's worth taking a look. If you exposed the backend to the users (i.e. gave them OpenID URLs), you'd have the added benefit of them being able to log in to more than just your internal sites using these credentials. (Example: Stack Overflow.)
As an aside, I'd be against making it so that Internet Explorer is required. I'm not sure if that is the goal from the way you wrote the question, but depending on your IT environment, I'd expect people who use Firefox or Safari (or Opera or ...) to be less than enthusiastic. (You're not developing against IE first, are you? That's been painful whenever I've done so.) This is not to say that you couldn't use this feature of IE, just that it shouldn't be the only option. The link you posted stated that NTLM worked with more than IE, but since I don't have any experience with it, it's hard to judge how well that would work.
I had a similar problem which I needed to solve for my organization.
I was looking into using adLDAP.
There is some documentation on the site for achieving seamless authentication with Active Directory too.
One option for you is to use CAS (central authentication service).
It has php client library.
How-to link to MS Active Directory: http://www.ja-sig.org/wiki/display/CASUM/Active+Directory
You would require Apache maven 2 though.
For IIS/PHP FCGI, You need to send out an unauthorized header:
function EnableAuthentication()
{
$realm = "yoursite";
header('WWW-Authenticate: Digest realm="'.$realm.'",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');
header("HTTP/1.1 401 Unauthorized");
exit;
}
You can then get at the username with:
$winuser = $_SERVER["REMOTE_USER"];
I then make sure the $winuser is in my database of allowed users.
Be SURE and test this under a non-privileged account. When I first installed this I tested it and it worked fine, but later when a standard non-server-admin user tried it this failed. Turns out some of the temporary directories need to have permissions changed for guest users. I can't recall the exact settings.
I'm in the final stages of implementing a CodeIgniter site which requires a really simple login system. One user, and one password to protect the admin area. I think I will be using one of the many CodeIgniter authentication libraries, which should allow me to ensure that people can't read from the database without being logged in as admin (hopefully).
Are there any glaring holes in a setup like this?
Should I take further measures beyond using a library like this to
ensure the security of the data in the MySQL database?
It will be hosted on a shared server; meaning little, or no server config will be possible.
There is a long discussion about the authentication systems available here: How should I choose an authentication library for CodeIgniter?
The latest version of Redux seems to be the favorite.
http://code.google.com/p/reduxauth/
I have used in the past (with excellent results) DX Auth 1.0.6.
You can find it at http://codeigniter.com/forums/viewthread/98465/
I would create simple form-based authentication and use a strong password.
HTTP authentication has too many problems IMHO:
Easier to brute force hack.
Anyone who sniffs the request can determine the username and password being used, but they don't even need to; they can just use an identical HTTP themselves.
Once that dialog pops up, it's difficult to dismiss, which can be irritating.
Many browsers will ask twice for a password before letting you in.
It's difficult to log out or change users, you usually have to quit the browser.
Easy to forget that you've let the browser save your credentials, which is another potential security risk.
If it is on an apache server, then I would consider just setting up an htpasswd protected directory. Read more about it here.
I have created some PHP-based intranet resources that require users to log in. The users create their own logins, and I verify that they are logged in using a cookie.
I've been asked if I can tie that login to their Windows login instead. My initial response was "a web page cannot access your Windows login - that would be a security risk." But one of our departments uses Sharepoint, and it does in fact tie itself to the Windows login.
How is that done? Can I do it in PHP? If so, why is it not a horrible security hole?
What you are looking for is NTLM authentication against the PHP website, which is perfectly doable but seems there is no single way in PHP to do it.
Have a look at http://siphon9.net/loune/2007/10/simple-lightweight-ntlm-in-php/
You also need to add the sites to your trusted sites in IE (or the equivalent in whichever browser you are using) and in the settings for trusted sites, turn on 'send current username and password'.
Its not a horrible security hole because the credentials are not sent en clair over the wire, and the end user has specifically told the browser to send credentials to the website in question.
PHP has LDAP support, so you can access Windows' Active Directory
There is this project on SourceForge:
adLDAP - "LDAP Authentication with PHP for Active Directory"
Often times this is done using a combination of LDAP and NTLM. Browsers like IE and Firefox can do NTLM authentication, which I believe is how Sharepoint works. I run a Java-based portal application that uses LDAP for syncing users and NTLM for authentication.
What you absolutely do not want to do is have the user enter their domain username and password into the browser. In years past I've seen several projects using this approach with LDAP to authenticate Windows users. You're correct, it is a security concern. The user should enter his or her password only once: when logging in to the workstation. The last thing you want are passwords sitting around in cache / temp files.
I apologize that I can not provide a "here's how you do it with a PHP app" answer. As far as I know, there is no one answer to this problem.
(One thing I have done in the past, and I never really checked to see if it was valid or poor form, was to use PHP from IIS. If you're using IIS, then PHP will populate the server variable REMOTE_USER with the Windows user's username (DOMAIN\user). It worked for what I was doing at the time.)
Is it possible to use the users windows authentication (setting in iis) for database connections in PHP?
This is possible in the .NET world through a technique called "impersonation". Does this also exist in the PHP/IIS world?
EDIT: The Database I am using is MS SQL Server 2005.
If you can authenticate the PHP application with Keberos, you can use kerberos Delegation to pass the credentials to the secondary server.
Ken Schaefer has a whole series of blogs on Kerberos, including this article on delegation.
Impersonation through Kerberos is the most secure answer, as well as the simplest to administrate. Having separate 'synthetic' users when accessing resources like databases means you basically bypass all possibilities for database authorization, get duplicate points of access administration, and that you get zero traceability at the database level (you just see that MySyntheticUser tried to access something, not who was behind it).
Having said this, I should warn you that Microsoft's Kerberos isn't always as straightforward as you would expect. We've had significant trouble getting it to work between pure .NET solutions, IIS, SQL Server 2005, AD domains and Internet Explorer. Most of it was down to getting trust configured exactly right. Also, while I'm not a PHP developer myself, I find some indications that you may have trouble accessing Kerberos library functionality. Find out what support you can get for SSPI. Also, your PHP process must have the necessary permissions to impersonate users, which I believe can be administered through IIS.
I would not necessarily expect all of this to be straightforward or easy, particularly as Microsoft has few incitaments to support non-Microsoft languages and platforms.
Must each user be verified separately? If not, you can set IIS to impersonate one person.
I know that you can supply the login name and password that you want associated with your ODBC connection if you create it through System DSN. I assume that the login un/pw can be windows user accounts.
Doing it that way seems to limit you to a predetermined account.
It might be possible to create a group, add the desired users, password protect the directory and only allow the group access to the directory.
You didn't say which database you're using though. If you are using MS Access, I know you can hide your database passwords. See my comment on another post.
Which way are you running IIS on PHP? As a standalone CGI or ISAPI?
My preferred solution would be to have a separate user on SQL Server for the access, instead of trying to force the IIS to run as an impersonated a user which is fine for development machines but not so good later on for production or even staging.
But if you're using FastCGI, it is possible to impersonate a user that the process is run by with the configuration file from what I remember, which passes the user logged in's credentials.