Update (2024): Reading this today, it may be difficult to imagine that when this project was posted, the idea of logging in via a QR code was new and exciting. That it later became accepted and commonplace is a testament to the fact that it was, and remains to be, a good idea. With the latest server updates the demo (written for PHP 4) will no longer run and I see no reason to upgrade it, but hopefully this page still provides some historical interest.
This was based on a proposed idea by idris83. A feature many sites, such as facebook, would benefit from. I whipped up this little prototype when I read the idea.
Unlike the original idea though, this version does not need any special app installed. All you need is a phone with a web browser and a QR code reader.
As most people stay logged in to their social networking sites anyway, first visit the page below on your phone and hit log in via username. Choose anything.
Next visit the page on a public computer (or where ever you like). Hit log in via QR code, and scan it. This code contains a URL with a disposable session key which identifies the public computer. Since your phone has already been authenticated, when it visits the site with the new session, the site can simply duplicate the log in details into the public computer's session.
Aside from making this very quickly one afternoon so there are inevitably bugs and security flaws (and the database is just a plain text file), the principle itself doesn't have any security holes if it were implemented properly.
The principle of what's going on is outlined in this schematic.
Phone logs in (and stays logged in) to website in the normal way.
↓
Public computer accesses website and is assigned a session key, and an authorizing key.
↓
Public computer displays authorizing key as QR code, and polls the site with its session key.
↓
Phone reads QR code and visits the site with the authorizing key, and its login details.
↓
The server now has everything it needs to assign the login details to the public computer's session.
By remembering the session association on the server, the phone could be used to log out of the public computer remotely too.
For the simplicity of this prototype both keys are the same, since I wasn't worried about security for this proof of concept.
Here's the source code for the sake of it.
<?php//A secure database would be used.$db="database.txt";if($_GET['ns']and$_COOKIE['LogIn']){$fh=fopen($db,'a');
fwrite($fh,"{$_GET['ns']}>{$_COOKIE['LogIn']}\n");
fclose($fh);die("Success - check your other computer.");}if($_GET['check']){if(file_exists($db))$sessions=file($db);elsedie();foreach($sessionsas$k=>$value){$d=explode(">",$value);if($d[0]==$_GET['check']){
setcookie('LogIn',$d[1],time()+24*60*60);//Delete the disposable keyunset($sessions[$k]);$fh=fopen($db,"w");foreach($sessionsas$value)
fwrite($fh,$value);
fclose($fh);die("Success");}}die();}switch($_GET['action']){case"login":if($_POST['username']){
setcookie('LogIn',htmlentities($_POST['username']),time()+24*60*60);die("<script>window.location='?action='</script>");}elseecho"<form method='post'>Enter username:<input type='text' name='username'><input type='submit' value='Log in'></form>";break;case"qrlogin":$key=md5(time());//Don't care about security for the sake of this proof-of-conceptecho"<body onload=\"ajax(page,'scriptoutput');\">";
google_qr($_SERVER['SCRIPT_URI']."?ns=".$key,200);?><scripttype="text/javascript">varpage="QRlogin.php?check=<?phpecho$key;?>";functionajax(url,target){// native XMLHttpRequest object//document.getElementById(target).innerHTML = 'Loading...';if(window.XMLHttpRequest){req=newXMLHttpRequest();req.onreadystatechange=function(){ajaxDone(target);};req.open("GET",url,true);req.send(null);// IE/Windows ActiveX version}elseif(window.ActiveXObject){req=newActiveXObject("Microsoft.XMLDOM");if(req){req.onreadystatechange=function(){ajaxDone(target);};req.open("GET",url,true);req.send(null);}}setTimeout("ajax(page,'scriptoutput')",1000);}functionajaxDone(target){// only if req is "loaded"if(req.readyState==4){// only if "OK"if(req.status==200||req.status==304){results=req.responseText;if(results=="Success"){window.location='?action=';}document.getElementById(target).innerHTML=results;}else{document.getElementById(target).innerHTML="ajax error:\n"+req.statusText;}}}</script><divid='scriptoutput'></div></body><?break;case"logout":
setcookie('LogIn',"",-1);die("<script>window.location='?action='</script>");default:if($_COOKIE['LogIn'])echo"You are logged in as {$_COOKIE['LogIn']}. <br/><br/>Note the log-in cookie expires after a day - on your average social networking site, people usually tick 'keep me logged in'.<br/><br/><a href='?action=logout'>Log out</a>";elseecho"You are not logged in.<br/><br/><a href='?action=login'>Log in via user name</a><br/><br/><a href='?action=qrlogin'>Log in via QR code</a>";}function google_qr($url,$size='150',$EC_level='L',$margin='0'){$url= urlencode($url);echo'<img src="http://chart.apis.google.com/chart?chs='.$size.'x'.$size.'&cht=qr&chld='.$EC_level.'|'.$margin.'&chl='.$url.'" alt="QR code" width="'.$size.'" height="'.$size.'"/>';}?>