From Slack integrations to coffee buttons, if Starbucks were to open up their API to the public, there are a ton of integrations that third-party developers could create. Tendigi CTO Nick Lee over at the Tendigi blog couldn’t wait so he reverse-engineered the Starbucks mobile app to work out how its API worked.
It wasn’t so easy, though. Starbucks API can be accessed via the URL ‘openapi.starbucks.com’ but you have to jump thru a few hoops to analyze the calls the app makes. The coffee giant uses a bunch of security measures to keep your payments secure, including SSL certificate pinning, fingerprinting attributes of your mobile phone to see if it’s “phonelike”, encrypting that fingerprint using AES, with a 256-bit key and a random initialization vector and signing requests with the current timestamp.
First things first, Nick wanted to observe outgoing requests and API responses. In this case, he couldn’t just point his iPhone at Charles or mitmproxy. Certificate pinning forbids this. Instead, he rooted an old Android phone and installed the Xposed framework with an extension that injects itself into apps and disables SSL pinning. Then he could watch requests with the Charles proxy. This way, he managed to see nearby stores, menu items and card balances from API requests. Not all requests were so easy to track, though.
For these, he needed to login. The Oauth endpoint for the API has three params that it needs to grant a token: the ‘sig’ query string, the ‘deviceFingerprint’ param and the ‘X-Cbt’ HTTP header. From security expert Ryan Pickren, Nick knew that the ‘sig’ string is just the client key, client secret and UNIX timestamp concatenated and converted to an MD5 hash. The ‘deviceFingerprint’ is a base64-encoded list of device attributes encrypted with AES-256. The ‘X-Cbt’ HTTP header, on the other hand, is a base64-encoded secret.
To get these three params, Nick tried creating them himself. He got the encryption key for the deviceFingerprint by using a jailbroken iPhone to decrypt frameworks inside the app. He was also able to track down a call to Apple’s CCCrypt function.
With these measures and bit more magic, Nick was able to sign and fingerprint login requests. He put everything together by creating a Node.js module to access basic Starbucks API functions. You can find this module here on Github.