This post is a continuation of my series of posts concerning the authentication of the AVS Java client. See here for the prior post.
In our current configuration we need a so called “Companion App” to take care of the initial authentication with the LWA (Login with Amazon) service. This companion app will should allow us to log on to amazon and tell the Amazon service that a certain product (our raspberry Pi) is allowed to make calls on my behalf, with my credentials. To do that, the companion app needs to know a few things about my device. It should call the Java Client on my Pi to get more information. After that It should request an Authorization Code from the LWA Service and send it back to the Raspberry Pi. It can use it to get a refresh token.
Luckily Amazon provides a sample application for a companion app as well. Both for Android and for iOS. That’s great. I own a Mac, so can easily compile iOS version using XCode. The companion app is written in Objective-C. A language that’s not new to me, but it’s been a while since I did something with it. Let’s dive in to what it does exactly.
I opened the project in XCode, but what I see is that it’s missing a file. A certificate.
This certificate is used to encrypt all of the traffic to and from the companion app. Where do we get such a certificate? The answer is simple. You generate it yourself. That’s called a self signed certificate. You can find the details here, but I’ll walk you through what I did.
First, I opened a terminal on my Mac (these steps apply to a Mac, so for the exact steps on windows, please see the details on the GitHub site.) and navigated to the JavaClient directory of the Alexa sample app. Open the file ssl.cnf :
sudo nano ssl.cnf
Next, I entered the values as in the screenshot below. A few important things :
- The country name has to be 2 letters
- I entered the exact same information as in the ssl.cnf on the Raspberry Pi
- I entered an extra IP address as I was going to address the Raspberry Pi using another IP address that the first two.
Ctrl-x y enter to get out of nano.
In the same directory you can also see a script called “generate.sh”. If you check out the contents you can see something like this :
See how it generates the certificate using all kinds of exotic commands and finally copies the certificate in the right place.
Before you can execute the script, you have to make it executable :
chmod 777 generate.sh
Next, execute it :
When all is done, and you return to Xcode, the file should no longer be highlighted red.
The next thing to do is tell Amazon that I’m going to connect using a Companion App. There’s two things to do : first I need to tell amazon how my app is called, and second I need to tell my app to log on with a certain key.
Go into Xcode, and in the properties of the application target, on the General tab, copy the Bundle Identifier to the clipboard.
Go to the Amazon Developer Portal en navigate to your device’s security profile. On the “iOS Settings” tab, enter a API Key Name (an identifier for the API Key), and paste in the Bundle Identifier. Click Add.
After everything is refreshed, you will find a key here:
You need to paste this key in the AlexaCompanionAppSample-Info property list. Locate it in Xcode, and add an extra key to it called “APIKey” (exactly, mind the capitals). Edit the value, and paste in the key.
We’re all ready to build. Click the “Play” button to start the device simulator and start the application. Next, the application will run, and it will prompt you for a device address. Type the static ip, followed by the 8433 port. This port is also used by the JavaClient op the Pi.
Important : Make sure the Javaclient is running on the Pi!
If you’re lucky a screen will appear letting you sign into amazon. I wasn’t so lucky. I got this error :
The operation couldn’t be completed. (nsurlerrordomain error – 1012.)
I can tell you this : there’s not much usable info on this on the entire bloody internet. But hey. There’s code debugging. After some debugging I stumbled on the piece of code below. It checks a “result” variable for 2 specific values : kSecTrustResultProceed or kSecTrusResultUnspecified. Only in those 2 cases it continues. The result in my case was kSecTrustResultRecoverableTrustFailure.
Well, it says “recoverable”, so that might still work, I figured. So I adjusted the code accordingly
Rebuild and run.
And what do you know. It worked. Logged in with amazon on the iPhone simulator, and the following appears :
That’s cool. Looking at the JavaClient on the Pi: The bearer token is filled in!
Looking at the config.json file : the refreshToken is saved!
Missing accomplished. After some hours of painstaking search, I finally got it working with automatic authentication. The road is open for all kinds of great things!