Starbucks Button

A button to order your favorite drink at the closest Starbucks.
An Amazon AWS IoT Button project using undocumented Starbucks API's.

Fully Customizable:

Set Drink

Set Location

Set Card

Building the Button

An exercise in reverse engineering and making.  

"Mobile Ordering" is a feature native to the iOS and Android Starbucks app. Let's see how hard it would be to do this from an AWS IoT Button.

 

‚Äč

Starbucks doesn't have any public API documentation, so I needed to reverse engineer the app myself.

Step 1: Bypass Certificate Pinning

After trying to proxy the Starbucks app's traffic, I realized the app uses Certificate Pinning to make reverse engineering more difficult. To bypass this, I needed help from the Android-SSL-TrustKiller tool.

Andy Android Emulator

SuperUser

Cydia Substrate

SSL TrustKiller

I now have a rooted Android emulator that forces all apps to accept any SSL certificate. Moving right along...

Step 2: Monitoring App Traffic

It turns out the latest Starbucks app requires a newer version of Android than the emulator supports.

So I headed over to APK Mirror to download an older version of the Starbucks app.

Unfortunately, the only version of the app that can be installed on the emulator is no longer supported by Starbucks. Using my HTTPS Proxy of choice, Charles, I checked out what was going wrong.

The app seemed to be reporting its version number and receiving instructions to show the "Update Required"  screen. To stop this from happening, I added a Charles Rewrite Rule to change "4.0" to "7.0."

The app then let me continue and use the Mobile Order feature.

Finally, I could start monitoring API calls.

Step 3: Spoofing API Calls

Since I had visibility into the app's behavior, I could start recreating the API calls myself in Python. After digging around some, I discovered Starbucks's backend is hosted by the API Management company, Mashery, and their mobile app uses OAuth for authentication with signed token requests. These signatures seemed to expire after a few minutes.

In order to generate my own signatures, I needed to extract the cryptographic keys that are hardcoded in the app.

Hashing a concatenation of the client_id, client_secret, and a UTC epoch timestamp allowed me to create my own signatures. I could then use my Starbucks credentials to obtain a Bearer Token, which is required for authenticating subsequent calls.

Step 4: Writing a Library

Next, I wrote a Python library to take care of spoofing API calls for me.

This library can be used to interface with any Starbucks account. (The credentials below are fictitious)

Placing an order requires a store_id, card_id, and a drink JSON file.

Step 5: Making an AWS Lambda Function

Since I could finally programmatically place Mobile Orders, it was time to upload my code to the cloud.

I used environment variables to dynamically insert my credentials. This will let me change the configuration without uploading new code. I also used Amazon's SNS service to send my phone a text message confirming the order.

Lastly, I hooked up an AWS IoT Button to my new Lambda function. That's it!