Voucher

The new Apple TV is amazing but the keyboard input leaves a lot to be desired. Instead of making your users type credentials into their TV, you can use Voucher to let them easily sign into the TV app using your iOS app.

How Does It Work?

Voucher uses Bonjour, which is a technology to discover other devices on your network, and what they can do. When active, Voucher on tvOS starts looking in your local network and over AWDL (Apple Wireless Direct Link) for any Voucher Server, on iOS.

Once it finds a Voucher Server, it asks it for authentication. Here’s the demo app:

Sample tvOS App

The demo iOS app can then show a notification to the user (you can show whatever UI you want, or even no UI):

iOS app shows a dialog

If the user accepts, then the iOS app can send some authentication data back to the tvOS app (in this case, an auth token string)

Sample tvOS App

Installation

Voucher is available through Carthage and CocoaPods. You can also manually install it, if that’s your jam.

Carthage

github "rsattar/Voucher"

CocoaPods

pod 'Voucher'

Manual

  • Clone the repo to your computer
  • Copy only the source files in Voucher subfolder over to your project

Using Voucher

In your tvOS app, when the user wants to authenticate, you should create a VoucherClient instance and start it:

tvOS (Requesting Auth)

When the user triggers a “Login” button, your app should display some UI instructing them to open their iOS App to finish logging in, and then start the voucher client, like below:

import Voucher

func startVoucherClient() {
    let uniqueId = "SomethingUnique";
    self.voucher = VoucherClient(uniqueSharedId: uniqueId)
    
    self.voucher.startSearchingWithCompletion { [unowned self] authData, displayName, error in

        // (authData is of type NSData)
        if authData != nil {
            // User granted permission on iOS app!
            self.authenticationSucceeded(authData!, from: displayName)
        } else {
            self.authenticationFailed()
        }
    }
}

iOS (Providing Auth)

If your iOS app has auth credentials, it should start a Voucher Server, so it can answer any requests for a login. I’d recommend starting the server when (and if) the user is logged in.

Void in

let alertController = UIAlertController(title: "Allow Auth?", message: "Allow \"\(displayName)\" access to your login?", preferredStyle: .Alert)
alertController.addAction(UIAlertAction(title: "Not Now", style: .Cancel, handler: { action in
responseHandler(nil, nil)
}))

alertController.addAction(UIAlertAction(title: "Allow", style: .Default, handler: { action in
let authData = "THIS IS AN AUTH TOKEN".dataUsingEncoding(NSUTF8StringEncoding)!
responseHandler(authData, nil)
}))

self.presentViewController(alertController, animated: true, completion: nil)

}
}

“>

import Voucher

func startVoucherServer() {
    let uniqueId = "SomethingUnique"
    self.server = VoucherServer(uniqueSharedId: uniqueId)

    self.server.startAdvertisingWithRequestHandler { (displayName, responseHandler) -> Void in

        let alertController = UIAlertController(title: "Allow Auth?", message: "Allow \"\(displayName)\" access to your login?", preferredStyle: .Alert)
        alertController.addAction(UIAlertAction(title: "Not Now", style: .Cancel, handler: { action in
            responseHandler(nil, nil)
        }))

        alertController.addAction(UIAlertAction(title: "Allow", style: .Default, handler: { action in
            let authData = "THIS IS AN AUTH TOKEN".dataUsingEncoding(NSUTF8StringEncoding)!
            responseHandler(authData, nil)
        }))

        self.presentViewController(alertController, animated: true, completion: nil)
        
    }
}

Recommendations

Use tokens, not passwords

While you can send whatever data you like back to tvOS, you should you pass back an OAuth token, or better yet, generate some kind of a single-use token on your server and send that. Cluster, for example, uses single-use tokens to do auto-login from web to iOS app. Check out this Medium post that shows how I do it! The same model can apply for iOS to tvOS logins.

Voucher can’t be the only login option

In your login screen, you must still show the manual entry UI according to the App Store Submission Guidelines (Section 2.27). Add messaging that, in addition to the on screen form, the user can simply open the iOS app to login.

Todo / Things I’d Love Your Help With!

  • Encryption? Currently Voucher does not encrypt any data between the server and the client, so I suppose if someone wanted your credentials (See Recommendations section above), they could have a packet sniffer on your local network and access your credentials.

  • Make Voucher Server work on OS X, and even tvOS! Would probably just need new framework targets, and additional test apps.

Further Reading

Check out Benny Wong‘s post on why Apple TV sign in sucks. He also has a demo tvOS Authing project, which you should check out!

Requirements

  • iOS 7.0 and above
  • tvOS 9.0
  • Xcode 8

License

Voucher is available using an MIT license. See the LICENSE file for more info.

I’d Love to Know If You’re Using Voucher!

Post to this Github “issue” I made to help us track who’s using Voucher
?

GitHub

https://github.com/rsattar/Voucher