Unlock a door using your Google account and a QRCode

January 22, 2019

Generate a QRCode on your smartphone with your Google account and use it to unlock a door.

Introduction

Few days ago, with @loicdesroc, we talk about new solutions to open doors (especially for professional purposes). At please-open.it, we have a solution based on bluetooth communication, the user’s smartphone acting like a remote control. We exposed that here :

Have you tried an onboarding pass on your smartphone in the airport ? Something like this :

A QRcode is very easy to read with a simple camera.

In this post, we will provide you instructions how to build a such system for a door, using a raspberry pi and an usb camera.

It is based on oauth2 tokens. In this example, we built something using Google Account. You can do the same with any oauth2 provider (github, facebook, twitter…). For specific needs, we built a backend at please-open.it with special features like calendar restrictions on accounts. For your professional needs, write us an email : contact@please-open.it

Wiring

Relay

We use a simple relay module like this :

VCC goes on 2
GND on 6
IN on 16 (gpio 4).

A red led is soldered on 18 (+) and 20 (GND)

The relay drives an electric door lock like this :

Drive GPIO

With wiring pi, a simple command can drive all gpio on the pi : http://wiringpi.com/the-gpio-utility/

            
                gpio mode 4 out;
                gpio mode 5 out;
                gpio write 4 0;
                gpio write 5 0;
            

Then :

                        
                gpio write 4 1 ;
                sleep 2 ;
                gpio write 4 0 ;
            

Or :

                        
                gpio write 5 1 ;
                sleep 2 ;
                gpio write 5 0 ;
 

Web application

A simple web application will connect to your Google Account (with your authorization) and generates a QRcode containing your authentication token.

This token gives access to your first name, last name, email and profile picture only.

Google Login

Oauth playground will help you understand how to use Google Oauth https://developers.google.com/oauthplayground

Follow this simple tuto : https://developers.google.com/identity/sign-in/web/sign-in

Don’t forget to register your application. We have done it, you can access it on https://login.please-open.it.

    
            <html lang="en">
                    <head>
                       <meta name="google-signin-client_id" content="<youid>.apps.googleusercontent.com">
                       <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
                       <script src="https://apis.google.com/js/platform.js" async defer></script>
                    </head>
                    <body>
                       <div class="g-signin2" data-onsuccess="onSignIn"></div>
                       <script>
                           function onSignIn(googleUser) {
                               var profile = googleUser.getBasicProfile();
                               console.log(googleUser.Zi.access_token)
                               console.log('Name: ' + profile.getName());
                               console.log('Image URL: ' + profile.getImageUrl());
                               console.log('Email: ' + profile.getEmail()); // This is null if the 'email' scope is not present.
                           }
                       </script>
                    </body>
                    </html>
    

DONE ! A token is generated.

QR code generation

There is multiple javascript libraries for QRCode generation.

First of all, we tried this library :

https://github.com/jeromeetienne/jquery-qrcode

It does the job, but we need more options for code generation. By default, this library generates a QR code with a medium redundancy. So the code needs to store more informations and become difficult to read.

Example using unitag, 4 qrcodes containing the same informations with different redundancies :

Low :

Medium :

Quality :

Strong :

Why using redundancy ? It depends on :

Those styles affects data, that’s why redundancy is needed. In your case, we want less redundancy.

This library has more parameters, including redundancy ! https://larsjung.de/jquery-qrcode/

So let’s generate a QRCode with it, containing a token :

            
                $('#qrcode').qrcode({
                    render: 'canvas',
                    background: '#FFFFFF',
                    size: 300,
                    ecLevel: 'L',
                    text: googleUser.Zi.access_token
                });             
            
        

An example of usable page is available on https://login.please-open.it

Source

Entire source code is available : https://github.com/please-openit/public-webapp-qrcode-app

Embedded code

Read QR code

Zbarcam is an opensource software available for various distributions :

https://www.systutorials.com/docs/linux/man/1-zbarcam/

Install it just with :

            
                apt-get install zbar-tools
            
        

A raspberry pi is not powerful enough to analyse high definition images fluently, so I decided to decrease the resolution :

            
                zbarcam --prescale=640x480
            
        

Use any qrcode generator (IE : https://www.qr-code-generator.com) and test your camera. You will probably need to adjust focus.
zbarcam output qrcode content like this : qrcode:"content or your qr code"

Get user infos

openID provides a set of services behind some URL described in a “discovery document”.

Google has one, described here : https://developers.google.com/identity/protocols/OpenIDConnect#discovery

An HTTP GET to https://www.googleapis.com/oauth2/v3/userinfo with the token in an “Authorization” header will return a json object with informations about the user.

            
                curl -X GET https://www.googleapis.com/oauth2/v2/userinfo -H 'Authorization: Bearer '$token                    
            
        

Verify the user in a list

We have a JSON structure with user informations. We extract the email using jq :

            
                    apt-get install jq
                    jq -r .email                    
            
        

(-r removes double quotes)

Then, a simple “grep” in a text file to verify if the email is present. WC will count number of output lines

            
                count=$(grep $email emails.txt | wc -l)                    
            
        

A simple if terminates the job :

            
                if [ $count = 1 ]; then
                    // account is authorized
                else
                   // forbidden
                fi
                done;
            
        

Revoke token

Still in the discovery document : https://developers.google.com/identity/protocols/OpenIDConnect#discovery

And endpoint is dedicated for token revocation. It takes a token in parameter in a GET request.

            
                curl -H https://accounts.google.com/o/oauth2/revoke?token=$token
            
        

Complete script (decode_token.sh)

            
                    #!/bin/bash
                    gpio mode 4 out;
                    gpio mode 5 out;
                    gpio write 4 0;
                    gpio write 5 0;
                    while : ; do
                     read token
                     token=$(echo $token | cut -d':' -f2)
                     email=$(curl -X GET https://www.googleapis.com/oauth2/v2/userinfo -H 'Authorization: Bearer '$token | jq -r .email)
                     count=$(grep $email emails.txt | wc -l)
                    
                     if [ $count = 1 ]; then
                       gpio write 4 1 ;
                       sleep 2 ;
                       gpio write 4 0 ;
                       curl -H https://accounts.google.com/o/oauth2/revoke?token=$token
                     else
                       gpio write 5 1 ;
                       sleep 2 ;
                       gpio write 5 0 ;
                     fi
                    done;                    
            
        

Command line start

We put the command line in a bash script, in case we need to adjust some variables or add logs redirection :

please-open-it.sh

            
                #!/bin/bash

                /usr/bin/zbarcam --nodisplay --prescale=640x480 /dev/video0 | bash /home/pi/decode_token.sh                    
            
        

please-open-it.service

            
                [Unit]
                Description=Please Open It Service
                After=network.target
                
                [Service]
                Type=simple
                WorkingDirectory=__WORKING_DIRECTORY__
                ExecStart=/home/pi/please-open-it.sh
                StandardOutput=journal
                
                [Install]
                WantedBy=multi-user.target                    
            
        

Then install the service using systemd

            
                systemctl enable please-open-it.service
                systemctl start please-open-it.service
            
        

Source

Entire source code is available : https://github.com/please-openit/embedded-qrcode-app

Mounting

Door lock is screwed on the case. A big nut ensure the locking system.

A USB camera (standard HD webcam) is glued on the left side. The focus is adjusted for the distance between the phone on the glass and the lens.

Want more ?

We have developped a platform that implements many functionnalities on top of oauth protocol, like calendar restrictions or pay by use. This plateform is design to work with any oauth provider. It means if your team has Gsuite accounts you can manage physical access to offices without any card, badge etc... Just a smartphone and an account on your existing infrastructure.

If you are interested, please send us an email : contact@please-open.it