I have an application which I am working on for a client which in summary allows each of their clients to create their own own version of the application by customizing the templates and associate their own domain name (all the code is located on my clients server).
The problem I am faced with is that when such users create their own branded version with their own domain name and then want to login to their admin the system can't provide https authentication.
I am aware that one can create a self signed certificate and I "think" there is a fairly simple way of doing this programatically, BUT if I want to give users the ability to purchase their own CA signed certificate then how could this be accomplished?
I have spent a few hours trying to find the answer to this question online but can't seem to find a solution to this perplexing problem.
What I think I need is some simple code which allow the user to fill out the required form field which in turn creates the CSR file which in turn the user would provide to the CA to obtain his CA file and for which some code would need to allow the user to upload it... Which in turn would automatically install it and redraft the needed web services.
Any/all help and guidance would greatly be appreciated!
How you would go about this depends on your architecture. But here are a couple things to consider:
Most SSL configurations operate on a unique IP address. So that means each SSL certificate you add would require another IP address. You may be able to centralize that configuration if you use a load balancer for example. Whether or not you can do that programmatically depends on your load balancer.
You will be best off generating the CSR based on your private key. Otherwise you will have to allow users to upload both a private key and certificate (and sometimes chain file).
Usually, dealing with the server certificate is done by a system administrator, so few tools will be user-friendly for people with no such knowledge.
You could create a PHP webpage that creates a private key and CSR (see openssl_csr_new examples) and lets the user copy the CSR in PEM format (and the private key for later use). Some CAs will let you paste such a CSR into their form, when requesting the certificate. Once the user gets the certificate (and perhaps the chain from the CA), they'd need to configure the server to use it (along with the private key). Tools like Webmin can let you do this from a web browser (you may want to implement something similar to what Webmin does for this, if you don't want to deploy a full web-based administration interface).
If the task of requesting the certificate is your client's responsibility (which it should really be if it's their server), they will need to be trained a little to know what to do, since the procedure will inevitably vary slightly depending on the CA they choose.
Needless to say that, if you implement scripts that can let the user change certificates and private keys, appropriate authentication and authorization should be used to perform these operations.
Related
Requirements
I'm currently working on a PHP portal for a machine-seller. His machines are capable of communicating over the internet with an integrated SBC with LAN port. The consumers who bought a machine can configure it online after they logged in to the machine-sellers-portal.
After they configured it online, they can download the configuration file via the HMI (touch display at the machine itself) to the machine. The configuration file contains valuable and private information.
The HMI is not browser based. It's a binary application that has, for example, a button "Load config". The rest has to be done in bash/php-scripts in the backround.
Solution for authentication?
I'm in a very early state of conception, but I'm wondering about some processes. I've never had a machine thats needs access to my services, only humans. What is the way to do this actually?
I have three approaches:
1. Access with "API-Key"
Means: In the OS of the SBC lies a file containing a sequence like 8asd7d7d. When I receive a GET-request to portal.company.com/getConfig/8asd7d7d I know from which machine it comes and that it is allowed to receive this config.
Disadvantage: The buyer has access to the SBCs file system. He could destroy the file by accident. He could find out the generating scheme and download configuration files from other buyers.
2. Generating one-time UUID-URL
Means: The consumer creates his configuration online. After that, he gets displayed a one-time URL like portal.company.com/getConfig/d8ac2292ea1fec3fe5c65e6ef573 which he can enter in the HMI and load the file.
Disadvantage: The consumer has to type a long URL into the display of the HMI.
3. Simulating the human authentication process
Means: The machine sends a valid post-request to portal.company.com/login with the login-data of its human owner. It gets a session-cookie (is that even possible in a non-browser environment like pure PHP-scripts?!) and the portal logic knows which URLs are accessible and which not (like for a human visitor).
Any other/better ideas?
I tend to use solution 2 as it's relatively easy to implement and hopefully secure (lets pretend a sha512-string as URL-parameter). Do you have any better suggestions? Mind, that the other way round is not possible, the portal can not actively push data to the machine (as it has no fixed IP, no webserver, ...)
If the device supports cryptographic functions, PKI can be used. Encrypt the data using the device public key. Only the device knowing the private key can decrypt the config file. PKI supports authentication also. here the device connects to a login portal that requests client certificate and after authentication of client, the config file is send to the device encrypted in device public key.
cons: each device requires a client certifcate.
I don't have a clue how to make my PHP website register and login with CAC Common Access Card. I developed for the past year a site and I can't sell it because off this. I have no clue. No HTTPS no SSL no PKI.
Set up server-side SSL.
Generate private CA for testing [if you don't have a CAC], issue an identity cert to self.
Install private CA as trusted root for client AuthN in application.
Require client-auth during SSL conversation; provide private CA and DoD Root CAs as trusted list of CAs.
Remove private CA from application trust after validation that it works.
Notes:
You'll have to parse the user-supplied certs for your User ID. This can come from the certificates signed by "DOD EMAIL CA-XX" [two digit number; presently up to 32] in the userPrincipalName field, or you can use the EDIPI which can be collected from either the DOD CA-XX certs or the DOD EMAIL CA-XX certs. Done right, both of these IDs will be immutable over time and will reliably identify a user despite any name changes they may have.
Any buyer worth their salt will demand that you're checking revocations via CRL or OCSP. Be sure you configure this, probably caching the CRLs from each of the CAs on your local system for quick access and configurable refresh time.
Assuming you're doing this in Apache, most of that work is documented in other threads here on SO and other sites. Look around; you should find 90%+ of what you need.
I've read a lot of questions here about how login can be connected to SSL and so on, but still the idea is not that clear. Based on what I read that I need to have an SSL setup and installed on my web server so that I can use the https secure connection on the page where a login is going to be used. Ok, I have done that part,but still wondering what to include in the login code in order to have the entire session must be over https. in some sites they mention that I have to add this code tep_href_link(FILENAME_ACCOUNT, '', 'SSL') so that the php login page or code be secure.
any comments will be appreciated.
Thanks a lot.
Update: I believe that this code is very important to add so that the login page goes on the https. if(!isset($_SERVER['HTTPS']))
{
header("location: https://" . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']);
}
HTTPS represents using an algorithm to secure transport layer communications that encrypts what the browser and server are sending each other. The encrypted form that is sent over the network is expensive computationally to turn back into it's original content, unless whoever is decrypting the ciphertext has the paired private key (or... a "computationally weak" algorithm was used).
This is point to point (client sends request to server, server accepts, determines response, sends response), so the browser and server first exchange public keys that represent what the data you are sending or receiving is going to be "scrambled" against. A private key is held by the public key issuer that allows that computer to "descramble" and obtain the original content that was sent to the receiver.
So when you create a private/public key pair, the private key is kept (in confidence and secret) on the server, and the related public key is sent to the browser. The browser, likewise, does the same thing and transmits a public key to the server.
"Protecting" sensitive information is not all that's going on; you may also use SSL/TLS to prevent tampering with data, for example, or even as an additional verification step.
To get HTTPS setup and available for you to use, you need to:
Procure a public/private key (signing by a certificate authority, or CA, is potentially optional depending on your end users).
Install it into the key store on the server that is available to your web server. OpenSSL is used for both of these steps in many cases.
Setup your system to use HTTPS URLs (for all resources, not just a <form action="https://...">s).
Couple of notes:
Browsers have their own certificates, so don't worry about that.
Many CMS' and frameworks allow you to specify HTTPS at the application layer
You can use WireShark to inspect what your computer is actually sending and receiving. This can be very illuminating, especially in combination with viewing the request/response in Firebug or Chrome Net consoles.
PHP online manual has the OpenSSL "book". Here is an example of how CodeIgniter handles configuring HTTPS at the application level.
There's various tutorials on how to setup SSL on a LAMP stack. Here is a tutorial on WAMP2 HTTPS and SSL Setup if you just need a development environment.
If you have a shared hosting environment, you may not be able to do the SSL setup on the server yourself; that may be handled by the server administrator. Check with your host. DreamHost, for example, has extensive docs.
Um, on a quick google, this function (tep_href_link) appears to be part of osCommerce. If your site has an SSL certificate setup properly, forcing users to an https url should be fine. If you don't know how to do that look into Location headers or mod_rewrite.
Also, as an aside, one thing you will need to do, is to ensure all links on the page are going over https. That will increase the likelihood of getting the green lock or w/e when a user comes to the page, assuming the cert isn't self-signed.
Is it possible to create a login process that requires a public/private key through a web browser? The public key would be stored on the server and the private key would be kept (and encrypted) by the user.
I basically want to do something similar to what SSH does, but through the web. Perhaps a custom method of HTTP Authentication (other than "Digest").
I know that it may not be possible to do this with a stock browser, so extensions to make this work are acceptable (Chrome/Firefox).
The keys would ideally be encrypted on a USB Stick. When the USB stick is unplugged in has to be impossible to login (don't want the browser to cache it).
This would be used internally.
Edit: Client certificates would be what I'm looking for, but how do I store these certificates on a USB stick? Also, is there information on how to authenticate a user using PHP?
This is Client authentication via certificates.
Your server should be configured to require a client certificate and also be configured with a truststore.
All the browsers support this.
You just have to import the client keystore having the private key and certificate to the machines set of certificates.
For windows it is in internet options
I doubt you'll be able to do this with a web application. The browser is sandboxed from the operating system and you would be unable to have the web application detect the presence of a USB drive nor would you be able to read any data off of it with the web application. So you would need the browser to do that for you, and they are not designed to work that way.
When you load a client cert into the browser it gets loaded into certificate storage. Those are different depending on browser and OS. On OSX they go into KeyChain. On Windows some will go into the OS key store and some will go into the browsers own keystore (Firefox I believe works this way). But none of them will allow you to define an external keystore and then encrypt and decrypt the key you're trying to protect as it reads and writes from that drive.
What you are doing would only be possible if you wrote your own desktop application (essentially your own browser) that did this for you.
It is possible you could do it with an Adobe AIR application. Adobe AIR supports reading and writing from a USB drive, it supports encrypted databases (128-bit AES/CBC crypto with SQLite) where you could store the data you are trying to protect, and it's cross-platform.
With any of these solutions you will likely be stopped at the requirement of need to ensure the USB key is plugged in. That is likely tough to do. How would you stop the user from simply copying the files from the USB key to the hard disk and then using the key from there so that they did not need to use the USB key?
To get to that level of control you may need to look at a truly native solution. C++, Objective-C, or Java. Java is going to be the only one that offers you a cross-platform solution.
If the USB key is a convenience to the end user as opposed to a requirement, then Adobe AIR would be a solid solution. If not, then it's time to brush up on your desktop software development skills.
Here is how I did web based login using RSA public/private key in php:
On registration, server saves user's public key and gives user an ID
On login, user is asked to enter his ID and private key
Registration is very simple.
But login is done in this way:
Server generates a string that contains some data: random string, current time, user's ip
That string is encrypted twice with AES with two passwords: nonce1 = pass2( pass1( string ) )
Same string is encrypted again with AES with two passwords, but in reverse order: nonce2 = pass1( pass2( string ) ) and the result is encrypted with user's public key: nonce2encrypted = encryptPubKeyRSA( userPubKey, nonce2 )
P.S. The string is encrypted with two passwords, to be harder to make a brute force attack.
The login form contains three hidden inputs: nonce1, nonce2encrypted, and nonce2 without value.
Then the user is asked to enter his private key in a textarea that is outside <form> tag (to be sure that it will not be sent to the server on form submit), a javascript will decrypt nonce2encrypted and set decrypted value to nonce2. Then the textarea with private key is removed from html with javascript, just to be sure it will not be stored somewhere in the browser or sent to the server.
The server receives nonce1 and nonce2, and decrypts them with that two passwords. If the decrypted values are the same, the user receives a cookie and is logged in.
P.S. That cookie also contains some encrypted data, for example user ip. This does not allow somebody that stole this cookie to login from another ip.
You can view this method in action (project on github)
Client certificates are the answer. Most/All browsers import these client certificates as PKCS#12 (.p12, .pfk).
You can convert an existing x509 certificate to a PKCS#12 file with the public key (.crt), private key (.key) and CA certificate (.crt). You can do this with OpenSSL using the following command:
openssl pkcs12 -export -out client.p12 -inkey client.key -in client.crt -certfile ca.crt
If you self-sign your certificates it's important to make sure the certificate serial is different than other certificates. If they are the same you can experience errors trying to import the .p12 file (So watch out for -set_serial in openssl examples).
Unfortunately the only cross-platform way to make certificates mobile/removable is to use a smart card (using PKCS#11).
On Mac OS X Safari and Chrome access their certificates from the keychain. You can actually create a custom keychain on a USB flash drive (File -> New Keychain). After you've created the keychain you can simply drag your .p12 file into your Keychain. What's nice about this is you can control access to what application has access to the certificates, and you can have the keychain itself lock after a certain amount of inactivity.
With Safari this works beautifully. If you unplug the flash drive it stops sending that certificate after a couple seconds. If you plug it back in, it picks it up immediately. If you lock the certificate with "Keychain Access" it asks for the password. It prevents you from properly ejecting the flash drive while in use, but after a minute Safari releases its lock.
Chrome is finicky. It caches the certificate for several minutes. If you lock the keychain, it continues to use the cached version. If you try to properly unmount the flash drive it will tell you Chrome is using it until you close it. If you plug the flash drive in while Chrome is running it won't pick it up.
So it appears that Safari is the only browser to support this. Firefox and Opera both have their own key-stores.
If you want to hide your custom keychain on the flash drive you can create an invisible folder be prefixing it with a period (like "./.keys"). When creating your keychain you can view the invisible folder in the dialog window by pressing Command+Shift+".".
The answer to your question is "not possible today."
The technology is there today in the form of certificates which are supported already in all browsers. But to get what you want, the browsers would have to allow certificates to be added and managed in the "password manager" part of their user interface. People would want to sync them between devices etc.
Additionally, web sites would need similar changes for users to be able to manage the public keys stored on the web site, instead of managing their password.
The benefit of this kind of system would be that you never actually have to send your password (private key) to the web site you're logging in to. But otherwise, you still have all the management activities that you have today with passwords.
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