Dual-Device Authorization with QR Codes

- 20 min read - Text Only

What's a good way to get people authenticated and authorized on a guest computer without a password or passkey within seconds?

Intro image with "Dual Device Authorization with QR codes"

If they're already authenticated on their phone with an identity provider like Google, and they have an account on the application on-site, then they can sign in under fifteen seconds with a QR code. Here's how it works:

Step 1: Scan QR code, Step 2: Sign in with Google, Step 3: Consent

On the device they wish to get authenticated to, they select an option that displays a QR code to authenticate. Then, with their personal device, they scan that QR code and they are prompted to sign in with Google. Thankfully, they're already authenticated on their personal device, so with a few more taps they return to the application on their personal device and are presented with a consent screen. Once they accept, the guest device establishes a session as them and they can continue.

Within fifteen seconds, they can get into a guest device and use the equipment tied to it to perform their role.

What role, exactly?
hmm
glamorous
Staffing a convention! Many departments and functions are supported by the digitally transformation I've delivered over the years: Registration, Swag, Volunteers, and most recently Dealers Den and Artist Alley.

Constraints of a convention

Running a convention – especially a furry convention – demands that everybody involved has immediate access to every tool and resource they need to run the event. Once-a-year events do not offer time to troubleshoot during the event.

What access do they need?
oh
convention-time
That differs from role to role and I can only speak on the technology aspect. Registration team members can check attendees in while Operations can check in staff and log volunteer hours for non-staff.

Tools and procedures need to be robust and consistent. When reality conflicts with the tool, it needs to be flexible as well, providing escape hatches to work around exceptions along the way.

Outside of leadership and creative teams, staff for volunteer-run events have a very light workload before the event and may arrive with no training or orientation whatsoever. Given that training has to be just-in-time for the event, our processes on site have to be be easy to understand and quick to communicate.

Lastly, staff need to be independent. If they're not able to get into the tool their process uses, then they'll need help! Unfortunately, not every volunteer-run event has more than one or two IT administrators to assist, and they need sleep too!

Thankfully, Google Workspace offers several methods to help individuals recover access to their account securely while adhering to an organizational policy like two-factor authentication, so they make for a decent identity provider.

In short, the tools we use need to be easy to understand, not require training, and be accessible to those with little to no preparation.

I get that Sign in with Google makes things easier.

A sign in with Google button

Where do QR codes come in? And what if I don't have my account working?

reading

QR codes for event equipment

The equipment we have on hand for this event is old. So old that it does not have Bluetooth Low Energy that supports passkey authentication from a personal device.

Requiring two-factor authentication on such equipment would be too burdensome for staff, the tech team, and the immediate team leads overseeing them. Instead, let's consider a more flexible alternative!

We require that their personal devices have access to their workspace account instead! And through that device, extend access to the equipment in front of them. This extension may be securely performed by following a standardized method: OAuth 2.0 Device Authorization Grant, as documented in RFC8628.

While the implementation need not follow the precise API specifications as documented in RFC8628, the essential concepts within can be applied to any application where convenience is paramount when a personal device is already authenticated. For example, Discord supports QR Code Login (archived.)

Discord login screen, on the left is a username and password field, on the right is a QR code.

The essential questions now are: what goes into that QR code, how will that get this device to sign in, and how is it kept secure?
laptop-thinking

A QR code itself isn't much of a secret. It is a machine-readable 2D symbol that produces some text when decoded.

These days, even non-technical people are used to interacting with QR codes for finding information, ordering food, or paying for a transaction.

A QR code with a bow tie at a dining table

shades-with-chat-bubbles
Fun fact, QR codes use Reed–Solomon error correction codes to recover missing or corrupted data, such as when they are intentionally mangled with logos or other imagery.

Whether decorating a coaster on a dining table or glowing on a kiosk, a QR code's link ought to embed the context in which it is displayed. That context, for authorization, has two components: a link to consent and verify intent to authorize this device, and a token that uniquely identifies this device's intent to receive authorization.

painting
RFC8628 labels this link a verification_uri and the token a user_code. The combination of these two components is labeled verification_uri_complete. This combination is what QR codes display!
interesting2
The other components, such as device_code, expires_in, and interval will be described in a moment.

Consent is important!

As convenient as it would be to automatically extend authorization from one device to another, this approach adds too much security risk to implement alone. One bad QR code scan should not result in leaking a bunch of personal data to the outside world. With a simple consent check that challenges the individual to verify they intend to authorize this second device, we mitigate that risk.

Hold up! I thought you said the Device OAuth Flow is Phishable!
surprise
jo-jo
It is! Especially if someone has to type a token somewhere else! However, if the token is embedded in the QR code, this risk is dramatically reduced.
snoot-colon-three-over-table
This risk is further mitigated by applying a short lifetime to all tokens, where delivery through any other means is unlikely to succeed in the token's lifetime. That's what RFC8628's expires_in is about.

Before someone can consent to authorizing a second device, the service verifying their consent needs to know who they are! Should they not be authenticated at the time of scanning the QR code, the service should redirect them to authenticate first and then return to the consent URL.

Thankfully, modern day technologies – such as passkeys, password managers, and federated identity like Sign in with Google – authenticating to the application can occur without typing a single character and be totally secure.

Should consent be granted to authorize this secondary device within the token's lifetime, it will asynchronously establish a session where it has access to the application. This flow does not share authorization directly from the authenticated device to the requesting device. Rather, it is mediated through the service that consent is granted.

There are two ways a requesting device like a kiosk will receive an authorization grant: the first is by polling often for an authorization grant every few seconds, or the second is by listening to a network socket or WebSocket. Whether pull or push, some secret state is established between the authorization-granting service and the device requesting authorization, as a direct connection is likely infeasible.

alright-then-keep-your-secrets

To stay logged in with Google, your personal device maintains an HTTP cookie with some unique data that indicates your relationship with them as a service. Often, this cookie has some unique and unguessable Session ID or a signed or encrypted assertion that describes who you are for every request.

cryptography-on-my-computer
Some signed assertions end up being JSON Web Tokens for sessions on the web. Don't do this! Cryptographers hate JWTs! The open nature of JWTs permits many mistakes that undermine their safety in practice. For example, see How many days since a JWT alg none vulnerability.

Like your phone's relationship with Google, the device requesting authorization has its own secret state. It may be communicated with a cookie or by an explicit token on every request to the consenting service asking for an authorization grant. In both cases, this ephemeral credential is kept secret to the requesting device.

dramatic-shades
RFC8628 labels this ephemeral credential as device_code, which must only be used by the device requesting an authorization grant and not shared to any other device.

The requesting device should show the QR code until it expires, at which point another should be generated or requested with an entirely different unique token that identifies this device to the consent service.

To recap:

  • A QR code is bound to the session on the requesting device, which links to an authorization service with a token identifying the requesting device.
  • The user consents to grant access to the requesting device.
  • The requesting device constantly polls for access using its own secret to obtain an authorization grant.
  • Upon authorization grant, the requesting device establishes a session with the authorization grant.

By combining federated identity and QR code log in, I can rest assured that staff can get into convention equipment with minimal friction.

What if my account doesn't work? Or… what if I'm not a staff member, but have a role to do?
peek

An escape hatch

There's always some edge case that threatens the integrity of our technical designs. We have a third party on site that needs access to this system to provide security services. Should a badge be lost, or a child loses their guardian, or a medical emergency occurs, this team needs immediate access to relevant information to document, mitigate, and resolve issues.

dont-bust-failed
I won't be adding username- and password-based authentication. I have no interest in burning CPU cycles to bcrypt or its successors.

Beyond federated identity, I need a solution that works for this team during and only during the event.

Introducing one-time passphrases!

Like Google backup codes, these unguessable computer-generated phrases are single use. Unlike Google and many others, they are generated in the likeness of Diceware, allowing easy transcription to a sheet of paper to be used as needed by the intended recipient.

XKCD comic describing pass phrases which are easier to remember and harder for computers to brute-force

There will also be no username for these one-time-pass phrases. At most, there will be thirty-two valid pass phrases during the convention. Requiring any secondary input, such as a user name, to identify the intended user would provide negligible security benefit and only challenge its usability on site.

Also, these one-time passphrases have a limited lifetime. They cannot be used for any long-lasting sessions and cannot be used outside the timeline designated at their creation. This timeline will be locked down either to each day or to the whole convention. Either way, it will still be impractical to brute force a passphrase of six randomly selected words with so few valid passphrases at any given moment.

In the extraordinary event someone does not have a functioning or authenticated personal device to authorize their station for their shift, a shift lead will have the capability to produce one-time passphrases for their shift – which is immediately consumed upon first and only use.

Roads left untraveled

There are secure alternatives that I'd switch to, if we had lots of money and ran this event every weekend. Security keys like Yubico's Yubikeys would be great! Why use a password when a device-bound passkey provides a safer environment organization wide?

money-on-fire

Costs! I don't have $6,000 to spend on security. I will never have $6,000 to spend on security for a volunteer-run organization that runs once a year.

One less-secure alternative is scanning one's own badges! That's like running around with "my username and password" stapled to your shirt as you walk around. A no *&cks-given security solution if I've seen one.

What about synced passkeys? The kind on your phone?
pick-me
heart-happy
A great question! And I hope folks are using exactly this to get into their Google account.

Syncable passkeys are great for personal devices. They have no place on guest devices however! Cross-Device Authentication would be awesome, if our hardware had Bluetooth Low Energy. 😉

With federated identity implemented, it doesn't make much sense to have yet another place for passkeys to be used. Also, onboarding folks has already been such a hassle. We cannot complicate onboarding further by requiring a second registration to exist, federated identity is the easiest to manage at scale.

thats-not-how-this-works-thats-not-how-any-of-this-works
It has been three months since we sent free staff registration invites to staff. The convention is less than a week away. Some staff still haven't registered for the convention with their organization account.
maybe-you-should-not
I can't explain it.

Lastly, any email-based one-time-passcodes or magic links would only complicate the process over what I've implemented.

QR-code-assisted authorization with federated identity on a personal device is the best arrangement I can deliver for this event.

How might I implement this for my event?
blep

Some code!

First, scan RFC8628 for general guidance. I also understand that some actual code might help speed up your understanding here. Check out QR Code Login on GitHub, a sample repository I've created for a functioning example of this concept.

The essential steps are practically lifted right from RFC8628! Rewritten, they are the following:

  1. A person chooses to log in by QR code instead of the other methods.
  2. The server generates a verification URL and gives a unique token (not included in the verification URL) to the client to poll for future updates.
  3. The browser shows this verification URL as a QR code and tells the user to scan it to continue logging
  4. The person scans the QR code and, if necessary, is forced to authenticate on their phone. Afterwards, they are prompted to consent to sharing their account with this device.
  5. While the person is busy authenticating and consenting, this device polls the server for an update using its unique token.
  6. If consent is given, the server tells this device that it is now authorized, and it proceeds. Otherwise, it continues to poll unless given an error, such as the consent request expiring.