I'm designing a web site that will have a mobile companion (initally iPhone only). The web site will be an ASP.Net MVC 3 application. I'll also have an ASP.Net Web API site (MVC 4) to expose services to the iPhone application. The iPhone app will have its own form to capture username and password from the user and send that to the web API in JSON headers.
I want to consider security from the start rather than an after thought. I'm not a security expert by any means. I've done a good deal of research to see how other's are handling authentication of a mobile application client from a web service. I think I've come up with a decent solution that doesn't involve hooking into to third party oAuths.
I would greatly appreciate any and all opinions, advice, criticism and general WTFs that any of you can offer. :)
My biggest concerns are:
- Ensuring that calls made to the web API are authorized
- Minimizing the risk of replay attacks (hence timestamps in the calls below)
The iPhone app will be developed as such:
Two strings are hard-coded into the iPhone app (same values for every user):
- Application ID
This is a string that is used to identify the type of client that is accessing the web API (iPhone, Android, Windows phone, etc). - Application's Hashing Salt
This is a string that is used to salt hashes for user-agnostic requests.
Two strings are stored in the iPhone app's local database (values unique to each user):
- API User Access Token
This is a string (token) provided to the client by the web API upon successful authentication and allows the client to access the web API without sending the username and password in each request. - User's Hashing Salt
This is a string that is used to salt hashes for requests made against established user accounts.
The iPhone will make calls to the web API in the following manner:
API Method: Create Account
Client Sends:
- New Account Data (Username, Password, First Name, Last Name, etc..)
- Application ID
- UTC Timestamp
- Hash of UTC Timestamp + Application ID salted with Application's Hashing Salt
API Returns:
- New User's Hashing Salt
The idea here is that, when creating an account, I can use the application's hardcoded salt since it's not a huge security risk if that salt ever got out (through decompilation or some other means).
But for methods that access and modify the user's data I'll use a salt that is owned only by that user so it can't be used by an attacker to impersonate others.
API Method: Get Account
(Used for getting user's hashing salt for accounts that were created on the web site but haven't yet been synced on the iPhone. This happens when a user tries to log in on the iPhone and iPhone detects that it has no record for that username.)
Client Sends:
- Username
- Password (hashed with Application's Hashing Salt)
- Application ID
- UTC Timestamp
- Hash of UTC Timestamp + Application ID salted with Application's Hashing Salt
API Returns:
- Existing User's Hashing Salt
API Method: Log In (Authenticate)
Client Sends:
- Username
- Password (hashed with User's Hashing Salt)
- Application ID
- UTC Timestamp
- Hash of UTC Timestamp + Application ID salted with User's Hashing Salt
API Returns:
- API User Access Token
API Method: Any Command (i.e. Create Post, Update Profile, Get Messages, etc...)
Client Sends:
- Command Data
- API User Access Token
- Application ID
- UTC Timestamp
- Hash of UTC Timestamp + Application ID + API User Access Token salted with User's Hashing Salt