Starbucks mobile application is one of the most famous cases in ecommerce. The author of the material is a programmer who empirically proves why you should open the API of this application.
Motivation
Pay tribute to the Starbucks application - it's just great. I use it (at least) once a day. It has everything I need from a great mobile service - coffee,
playlists of the 80s hits in Spotify and the opportunity to avoid live communication with other people. I’m clearly not alone in my preferences, as
20% of Starbucks operations in the US are now done through mobile phones.
')
In addition to the
integration of Slack and
coffee buttons, there are many other integrations that could be implemented if the company opened its API for third-party developers. She is clearly moving in this direction, as she has both a Twitter account and a (password-protected) developer website.
However, I could not wait and therefore decided to take matters into my own hands.
It was not easy
Starbucks application turned out to be a tough nut to crack. Despite the “openapi.starbucks.com” URL, we had to wade through serious jungle before analyzing the calls made by the application. Like any other payment processing application, Starbucks has taken numerous security measures to protect the API used by its application from unauthorized use. Here are some of them:
Monitoring Network Requests
To begin with, I needed a way to observe the requests and responses exchanged between the Starbucks application and its server. I usually just set up my iPhone on
Charles (or
mitmproxy ), and that was enough.
But not at this time! Since the application uses certificate pinning, I could not intercept its requests, as usual. Instead, I had to dig out my old phone on Android,
get root-rights , install a framework called
Xposed, and finally install an
extension that is embedded in running applications and disables SSL pinning.
MuahahaAfter its launch, I was able to start viewing requests using the Charles proxy server. However, this turned out to be more of a false hope, since not all requests could be easily reproduced. However, I was able to request basic information, such as the nearest stores, menus, and card balances.
The result of a query about the nearest store. Now you know where I work. Oops.“It's easy,” I thought, “I'll just place an order, connect to a proxy server, and then replay the requests!”
And no.
As it turned out, Starbucks access tokens are valid for only one hour, so you can’t just take and use the token that your phone uses. This creates certain difficulties ...
Login
The OAuth endpoint used by the application checks three parameters before issuing a token:
- Query string parameter sig. Security researcher Ryan Pikren found out that this is a client key, a client secret key, and the current UNIX timestamp, concatenated together and passed through an MD5 hash function .
- The form parameter "deviceFingerprint". This is a list of the various device attributes encoded with base64 and encrypted AES-256. It also changes regularly as the current time and uptime of the device are included in the fingerprint.
- HTTP header "X-Cbt". Another line of the secret key in base64 encoding.
I started trying to form some of them myself. I was able to get the encryption key used to create the deviceFingerprint using jailbreaked iPhone to decrypt frameworks within the Starbucks application. After studying the
Hopper framework for some time, I was eventually able to track the call to the
Apple CCCrypt function.
www.youtube.com/watch?v=o8ZnCT14nRcThen I linked the SBXData framework (a framework that I had previously decrypted on a jailbroken phone) into a hastily created application and used
Fishhook to reassign this function to my own implementation. This allowed me to upload the key and its associated parameters to the console:

Similarly, we managed to figure out how to generate the “X-Cbt” header. For brevity, I will leave this task to you :)
Conclusion
After I was able to sign and fingerprint my input requests, I combined everything into a small Node.js module that allows you to use some of the basic Starbucks API functions. Good news: it is (mostly) posted
here on github!
Voila! Programmable coffee.
