Implement Magic Login for TV devices


I don’t know if that is the correct term for it, but it sure is magic to non-developers. I recently noticed this technique on the Youtube app on my TV. Here’s how it works:

  1. Begin the login process on Youtube app. It shows a unique 4 character code for the TV.
  2. Open Google app on your phone and navigate to the “authenticate other devices” page.
  3. It asks for a confirmation for the TV login on the mobile without entering anything and logs you in after the confirmation.


So how does it work? It’s pretty simple, really. As soon as you open the authentication screen on the TV, it generates a unique code and starts playing an ultrasonic sound in a loop. The phone is capable of hearing this sound and identifying what code it is broadcasting. After that, it’s all a matter of communicating the right things over the API on the TV and the phone.


Let’s see how we can do this. We will use the Chirp SDK for this purpose. The SDK will do all the heavy lifting of generating and identifying the tones, so all we need is to build a way for it.

TV App

Let’s start with the implementation on the TV. Since most of the devices use a different programming language, I wouldn’t dive into a language-specific guide. But for completeness, here’s a sample 4 liner in JS:

const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const connect = new ChirpConnect(APP_KEY, audioContext);

const payload = new Uint8Array([0, 1, 2, 3]) // TODO: Replace with your code

If your device isn’t compatible in generating the payload, fret not, because there’s an API that does that too. All you need is to download the file that<<YOUR HEX ENCODED CODE>> generates and play it on a loop on your TV app.

Mobile App

The next step is to integrate it into your mobile app so you can detect these tones and perform your magic code for logging in the user. Again, setting up the SDK is as simple as it gets. Do this somewhere in viewWillAppear:

connect = ChirpConnect(appKey: APP_KEY, andSecret: APP_SECRET)
let configError: Error = connect.setConfig(<YOUR CONFIG STRING>)
let startError: Error = connect.start()

connect.receivedBlock = {
  (data : Data?, channel: UInt?) -> () in
  guard let data = data else { return }
  print("Received code \(String(data: data, encoding: .ascii))")
  // TODO: Initiate Login

The receivedBlock will be executed with the data that it receives and you can initiate the login process from there.

Of course, all of this needs to be aided with APIs on the backend to generate a unique code and then log the user in if requested from an authenticated end-point, but those are details that I will leave for you as the backend for most apps will very widely.

Published 30 Oct 2018

I build mobile and web applications. Full Stack, Rails, React, Typescript, Kotlin, Swift
Pulkit Goyal on Twitter