Many large web services nowadays support 2-step verification to enhance the security for their users. With 2-step verification you have to supply a one-time-token besides your usual username/password so in case someone steals your password it won’t help them much, because they don’t have (hopefully) the device which provides this one-time-token for you. You may know this from your bank or even enabled it on Google Apps, Facebook or Amazon.
The main point about 2-step verification is that something else than your computer provides that token. If it’s on your computer and that one gets stolen (or hacked into), it won’t help much for the additional security. That’s why you need a second device for those tokens. Some banks do that with SMS/Text Messages (Facebook, too), other give you special devices for that (eg. RSA keys) and the last group does it with your smartphone.
Google provides an app called Google Authenticator which exactly does that, is available for Android, iPhone and Blackberry and is Open Source. The ideal candidate for an implementation in PHP.
We had this request from a client to have a backend system which is available from everywhere (so they can ditch their VPN for that) but is somehow secure nevertheless. I was at that time playing with the 2-step verification stuff of Google apps and thought that this must be doable in PHP as well. So I reverse engineered the android code and came up with this little GoogleAuthenticator.php library.
If you implement this library in your application, you can tell to your clients, they should just download the Google Authenticator app and then scan the QR Code you provide them on their first login. Depending on your security requirements, you can now ask them for that token on every login or every other day or whatever you need. And of course any time they use another computer/browser.
We actually didn’t implement the library in any real life project yet (that will come), but for now I made a little, quick and dirty framework-less example available here. Please read the code and the comments to understand how it’s supposed to work. It would be great if anyone would implement that into an Symfony 2 bundle (or the whole security framework of Symfony 2).
If you have any question about the library, do not hesitate to ask in the comments.