I've seen a few people comment on how OAuth is impossible on the new Apple TV due to the lack of any form of web view. In building Fetch for the Apple TV we needed to interact with an OAuth provider (Put.io) in order to authenticate.
Before I even knew that the Apple TV didn't support a web view, I never in a million years thought about displaying one to authenticate users. It would have been a truly horrendous experience for the user. Instead, I looked to authenticate from a secondary device — an iPhone for example.
The YouTube app on the existing Apple TV does this by redirecting users to a URL and inviting them to enter a code. Here's a crappy picture I found on Google:
I wanted to build something similar for Fetch on tvOS but realised we had two kinds of users: those with Fetch on iOS and those without.
Let's start with those without.
Users Without The iOS App
To create the authentication method we wanted I knew I'd have to build some kind of middleman service but what exactly would that need to do?
- It would need to generate a 1-time URL
- It would need to redirect users to the OAuth provider to authenticate
- It would need to tell the Apple TV the user had authenticated and send it the code
Here's how I imagined it to work:
To achieve this I built a very simple API in Laravel. It generates a random URL (and a token, more on that later) when the Apple TV asks for it. The TV then pings another endpoint waiting for an access token.
The user can visit the URL on their phone or computer and login via OAuth as expected. The provider sends them back to our API and the Apple TV receives its token and logs them in.
One complete, the single-time URL is deleted and cannot be accessed accidentally again.
Users With the iOS App
But what about users with Fetch for iOS? They've already authenticated once and considering we're using the same client ID from our OAuth provider, isn't there a way we can send that over?
I had thought about sending the access token over the local network but Apple didn't include all the multi-peer stuff. We'd already built the middleman API so decided to take advantage of that.
As well as a URL the Apple TV also receives a token when it first pings the server. We use this token to generate a QR code that a reader within our iOS app can scan. The scanning of the code sends it along with the OAuth token to an endpoint on the server. As the Apple TV is already listening for changes, the user can login within seconds. It's actually really, really nice.
Here's a rough idea what it looks like:
And that's it! If enough people think it'll be useful, I'll pop the middleman service I built up on Github. I'd also be interested to see if anyone else has a better approach to this. Comment or tweet me.
UPDATE: I've uploaded the middle man example over on Github