I know this is a popular type of question, but I haven't been able to find any other questions that address my specific needs.
Background
- I have an iOS app that retrieves data from my Ruby on Rails developed web API.
- I would like to privatize my API so that other sources cannot use the data coming from my API (ie. someone else develops an app that hits my API url and uses the data for their customers)
Requirements
- (HARD) Private API so that only authorized clients (coming ONLY from iOS app) can access the data from the API.
- (HARD) Users must not have to create user/password accounts.
- (SOFT) I have read that SSL can become a nightmare when trying to get apps approved by Apple. Since this is a small-time app (as of now), I prefer to not depend on SSL. However, if you can point me in the right direction regarding the ease of using SSL with all API traffic on iOS, I am all ears).
! Skip to the end for the question if you are losing interest :) !
Ideas thus far
Idea 1:
- iOS requests token from web, sending some UUID
- WEB responds with API_Token and Token_Expiry
- WEB stores UUID, API_Token, and Token_Expiry in database
- iOS stores API_Token, Token_Expiry locally
- iOS requests data by sending UUID and API_Token
- WEB verifies UUID and API_Token, responds with data
- Repeat Steps 5-6 until API_Token expires, then repeat from Step 1
*Idea 2: (single use API_Token)*
- iOS requests token from web, sending some UUID
- WEB responds with API_Token
- WEB stores UUID and API_Token in database
- iOS stores API_Token locally
- iOS requests data by sending UUID and API_Token
- WEB verifies UUID and API_Token, responds with data AND NEW TOKEN
- iOS gets data and saves NEW TOKEN locally
- Repeat Steps 5-7 indefinitely
Problems with these ideas
I believe there is no perfect UUID solution for iOS any longer. If the UUID can change over time (or if the user has multiple iOS devices), an authentication problem can occur.
If a hacker gets an API key, I don't want them to be able to access the data (hence the expiry or new token idea).
Question
What suggestion do you have to create a secure API between Rails and iOS?
EDIT 1:
I'm still surprised this isn't something that comes up all the time. There must be a ton of apps out there that communicate to an API but do not force user's to sign up. If SSL or OAuth is the only proper solution, please defend. I'm all ears.
I ended up rolling my own solution based on a few suggestions that I found on the web (see reference links at the end).
- iOS checks if it has an auth_token. If no, proceed to step 2, else proceed to step 4.
- iOS requests an auth_token by sending a special signature that only my iOS app and servers know how to generate.
- WEB validates the special signature and creates a unique auth_token that is saved in the DB and sent back to the iOS app.
- iOS requests data by sending the auth_token and a generated signature (again one that only my iOS and server know how to generate).
- WEB validates that the auth_token exists in the DB. It then generates an auth_signature and verifies that the request came from my iOS app.
- WEB responds with the data and a newly generated auth_token.
- WEB deletes previous auth_token from DB.
- iOS saves new auth_token locally and uses data.
- Repeat steps 4-8; If response is 401 unauthorized, restart at step 1.
References:
This GitHub Gist by @keighl is what started me off, by far the best example that I found:
https://gist.github.com/4336694
Railscast: Securing an API:
http://railscasts.com/episodes/352-securing-an-api