WWPass PassKey Lite is the most advanced and convenient replacement for usernames and passwords

Add QR code login to a web site

Step 1: Register your web site

Start with creating your personal account at WWPass Developers site. Register your web site (URL) and obtain WWPass credentials: a private key and certificate signed by WWPass CA.

Step 2: Modify your code

To implement WWPass QR code login, place a <div> or <span> element to the sign-in page - placeholder for QR code image - and add a javascript function call. You will also need to implement two callback URLs on server side. Here is a code snippet

<div id="qrcode_id"> </div>
    
<script src="static/js/jquery-2.0.3.min.js"></script>
<script src="https://cdn.wwpass.com/packages/wwpass.qrcode.js/2.0/wwpass.qrcode.min.js"></script>
<script>

options = {
    'render': 'qrcode_id',
    'ticketURL' : location.href.substring(0, location.href.lastIndexOf('/')+1) + "getticket.php",
    'callbackURL' : location.href.substring(0, location.href.lastIndexOf('/')+1) + "account.php",
        
};

wwpassQRCodeAuth(options);
</script>
    

The wwpassQRCodeAuth() function takes a JavaScript Object as an argument. Mandatory parameters:

  • render - id of the hypelink element where QR code will be placed
  • ticketURL - address of the page on your server, which communicates to WWPass network, requests ticket and returns it in JSON object. The page does not need any graphical representation. In practice its code does not depend on particular site, mostly on chosen server programming language and environement.
  • callbackURL - address of the page on your server which gets control after successful user authentication. The page receives an authenticated ticket as a GET parameter.

Here are samples of ticketURL callbacks:

        
<?php
require_once('config.php');
require_once('static/lib/wwpass.php');

  try {
            $wwc = new WWPASSConnection(KEY_FILE, CERT_FILE, CA_FILE);
            $ticket = $wwc->getTicket(600, NEED_AC?'p':'');
      }
      catch (Exception $e) {
            $err_msg = 'Caught exception: '. $e->getMessage();
            echo $err_msg; 
            exit();
      }
            
// Prevent caching.
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Mon, 01 Jan 1996 00:00:00 GMT');
header('Content-type: application/json');

$data = array("ticket" => $ticket);

echo json_encode($data);

...
from WWPassClientTornado import WWPassClient
...
class GetTicketHandler(tornado.web.RequestHandler):
    
    @tornado.web.asynchronous
    def get(self):
                
        self.settings['wwc'].get_ticket(self.onTicket) 

    def onTicket(self,result,data,ud):
        if result:
            logging.info("ticket: %s",data)
            o = {'ticket':data}
        else:
            o = {'error':str(data)}
        self.write(json.dumps(o))
        self.finish()        
        

Below is a snippet of callbackURL - the page which receives authenticated ticket. In the example the ticket is used to obtain a PUID (provider's user ID) - site specific unique identifier of the keyholder.

        
<?php
require_once('config.php');
require_once('static/lib/wwpass.php');

    $ticket=$_REQUEST['ticket'];

    try {
        $wwc = new WWPASSConnection(KEY_FILE, CERT_FILE, CA_FILE);
        $puid = $wwc->getPUID($ticket, NEED_AC?'p':'');
        $db = mysqli_connect(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME);                
        $puid = mysqli_real_escape_string($db, $puid);
        $result= mysqli_query($db, "SELECT * FROM `users` WHERE `puid` ='$puid';");

...
import mysql.connector 
from WWPassClientTornado import WWPassClient
...

class AccountHandler(BaseHandler):
    
    @tornado.web.asynchronous
    def get(self):
                
        if len(self.get_arguments("ticket")) > 0:
            status =  self.get_argument('status')
            self.ticket =  self.get_argument('ticket')
            self.settings['wwc'].get_puid(self.onPUID,self.ticket)

    def onPUID(self, result, puid, user_data):
        cnx = mysql.connector.connect(user=options.DB_USERNAME, password=options.DB_PASSWORD,
                              host=options.DB_HOST, database=options.DB_NAME)
        cursor = cnx.cursor();
        query = "SELECT `created`, `name` FROM `users` WHERE `puid`= %s;"
        cursor.execute(query,(puid,))
        ...