22

After extensive research, I have not been able to find a clear answer to my question. Firstly, can anyone tell me the basic logic of handling "login functionality" for a native iphone app connecting to a web service? For instance, the facebook app ask for a username and password immediately after launch, and from there you have full access to your account in all successive views of the app. Each time you post something etc, you do not have to re-login... Can someone please explain this process to me? Is it done through cookies or sessions? is Keychain involved?

I have a semi-working app right now but I'm almost positive I could be doing it better and more securely. Here is what I'm doing:

1) Set up a local server with a database of users (username and password columns and other tables etc.) using mysql. Wrote a simple web-service that takes in POST data and queries the database to check that the username exists... and if it does, that the passwords are equal. Using sha1 hashing. Echo true or false accordingly.

2) My app has an initial login screen with a 2 textfields (1 for username and 1 for password) and a button that calls the login method. My login method does the following:

  • init an *NSURL with a string (the url of my web service: @"http://webservice.com/login.php")
  • init an *ASIFormDataRequst with that url
  • set the post value with the password and email text in the text fields
  • set the delegate to itself
  • call startAsycronous on the request
  • implemented the requestFininshed method to retrieve the "true" or "false" echo-ed from the webservice
  • depending on the response, move forward to the next view, else, make an alert telling the user to retry

So, my questions are:

1) Is this secure for sending passwords? (via ASIHTTPRequest and the POST method?) 2) In the succeeding views, the user should be able to interact with their account (like posting messages and status's and pictures on the Facebook) How do I persist the user's logged in status so that every time the user interacts with the database, I can ensure that the user is still logged in and that it's the same user? For instance, the only way I can think of doing this is if I store a cookie on the users device with the username and password, and then every successive interaction with the web service / database, it does an authentication with the cookie values (username and password).

There has got to be a better way of doing this? Maybe sessions or cookies? or by using keychain??

Thanks for the help guys, and sorry for the long question!


momo
  • 21,233
  • 8
  • 39
  • 38
bradleyrzeller
  • 303
  • 2
  • 3
  • 9

1 Answers1

14

Here are my thoughts based on what I know:

1) Is this secure for sending passwords? (via ASIHTTPRequest and the POST method?)

You need to make sure you are sending this information via https (SSL) and not a plain Http. The reason is, you don't have control over where the user wireless access point is. For all you know, the user could connect to open access point that is belong to a particular hacker. Having it transmitted will enable him to sniff the packet and get the required information to access the WebService even though the password is hashed. Having it send via https would ensure that the packet is encrypted with strong key. Even if a hacker manage to sniff the packet out, it will take him a long time before he/she is able to decrypt the message.

  1. In the succeeding views, the user should be able to interact with their account (like posting > messages and status's and pictures on the Facebook) How do I persist the user's logged in status > so that every time the user interacts with the database, I can ensure that the user is still logged in and that it's the same user?

One commonly employed method to do this is to get the session token after the user logged in. That is, you create a random generated ID that you return upon successful login. You would then map this token with the user id in the backend and it is associated with a session time out. You refresh this time out every time the user connects to a webservice and time it out after certain period to avoid breach of security. You would then persist the session token in your device and then used that for subsequent call. As long the session is alive then the user is logged in. As the token is associated with a specific user, you also ensure the identity of the caller.

To prevent someone else using other people token is the reason why you need SSL to secure the channel and prevent sniffing. Assuming that you have secured your connection channels, the only way to get the token is

  1. to verify the identity via login
  2. The phone is stolen by hackers who could take the token by inspecting the local storage.

The mapping is necessary so you could validate the token is a real token that has been associated with the user via login activity. Furthermore,for number 2, you can offer remote wipe out feature that basically kills the mapping and making that token invalid.

Another very important part of this token is the token cannot be guessable and have to be random cryptographically (see Randomness Recommendations for Security). If the token is only based on pseudo randomness, a clever hacker might be able to guess its algorithm and can guess its next/previous token and has a possibility of obtaining any valid token in the table.

There are many algorithm to generate this token. For example, Java Programming Language provides a SecureRandom class in order to provide cryptographically randomness and .NET has similar secure RandomGenerator class.

If you want to look at the algorithm OATH has proposed Time-Based One-Time Password Algorithm (TOTP) which is an extension of HOTP. Most of the languages/platforms would have the cryptographically strong random generator that you could leverage immediately though without you having to write it yourself.

Depending on your service implementation/platform, you might want to ask SO for a suitable class/module for cryptographically random generator such as the one asked here "How do you generate cryptographically secure random numbers with php"

Community
  • 1
  • 1
momo
  • 21,233
  • 8
  • 39
  • 38
  • Thanks for your response! In regards to https, where is this functionality located? On the server, in the application, or both? It seems like it could be a configuration to my server, or maybe a change in the way I send the request from the iphone... And also, I am not sure I fully understand what you said about the session token. Is this a correct understanding: First authenticate username and password... – bradleyrzeller Sep 04 '11 at 21:00
  • Then if not valid, return false; if valid then generate a random ID for this user, and insert into the database for this user. Then return this ID to the user to store on the phone. For every future connection with the web service, you have to pass the ID and username? and then check to see if that pair is valid? If you have to do that every time, it seems like it would be the same thing as passing it the username and password, rather than add complexity with adding a random ID generator... – bradleyrzeller Sep 04 '11 at 21:02
  • https is configured on the server side and the iPhone should just change the URL from http to https. As for the token, you don't pass the user id and username and check the pair, but you will pass the generated id (session token) and check if that token is still alive. If it is, then you are ok, otherwise you redirect the user to login page (or whatever you decide appropriate for you app) – momo Sep 04 '11 at 21:13
  • O okay, that makes more sense. But as far as the randomly generated ID, why would we have to map each token to a user id? If all you are checking is to see if the token is still alive, that doesn't seem to guard against people connecting to the web service via someone else's token... Wouldn't you need to check 1) the token is still alive and 2) that the user associated with that token, is the user making the request...? – bradleyrzeller Sep 04 '11 at 21:58
  • To prevent someone else using other people token is the reason why you need SSL to secure the channel and prevent sniffing. Assuming that you have secured your connection channels, the only way to get the token is 1. to verify the identity via login 2. The phone is stolen by hackers who could take the token by inspecting the local storage. The mapping is necessary so you could validate the token is a real token that has been associated with the user via login activity. Furthermore,for number 2, you can offer remote wipe out feature that basically kills the mapping and making that token invalid – momo Sep 04 '11 at 22:06
  • Thanks again! So for all successive connections to the web service after login, am I only checking whether or not the token is still alive? Or am I also checking to make sure the token "is a real token that has been associated with the user via login?" If so, then I must pass the web service my token and username, so that the webservice can verify that the token is still alive and that it is associated with the same user... Also, as far as what to store on the device, I only have to store the token? not the username and password right? And should the token be encrypted or just plain text? – bradleyrzeller Sep 04 '11 at 22:19
  • You make sure the token is alive and is in your mapping table (the one that maps userid with tokenid). You don't need to pass the username as if it is in your mapping table then you know that it is a valid token with a user associated via login (as it is the only way to get the token and having it put into mapping table). Store the token encrypted, so at least if someone steals the phone, he needs to figure out the encryption algorithm + key to get it which by then hopefully the token expires or has been remotely wiped. You need only to store the token in the phone – momo Sep 04 '11 at 22:44
  • Also, I am not discouraging you to put additional check with username. It's not typically implemented as you have verified user's identity and taking every step to ensure the security of the token, but it doesn't hurt either if you want to do it. If you do that, you would need to store the username and the token on the phone though. Additionally, you could store client's certificate on the phone to ensure only trusted entity (like the publisher of the app) send the webservice. It requires more configuration on server and code change in your iOS. – momo Sep 04 '11 at 22:50
  • I see. But what I am saying is that if I have a table in my database (we'll call it token_mappings) that has three columns: user_id and token and expiration_date, every time a user logs in, I would add a row to that table with the user_id, the generated token, and an expiration date. So the question here is what if some hacker steals the token to ANY of the tokens in that table. Then the hacker could potentially make requests as ANY logged in user if you just check if the token is in that table... – bradleyrzeller Sep 05 '11 at 00:08
  • How does he steal any of the token? You have secured the communication, you provide remote wipe and you will secure the DB from external access. If the hacker gains access to the DB, it's a bigger problem as he/she would probably get more info than the token. You brought up a good point about gaining access to ANY token as hackers are known to be able to guess the next session token if it is based only on pseudo randomness hence the need for the id to be completely random so the hackers won't be able to guess it (other than by huge amount of luck). – momo Sep 05 '11 at 01:34
  • Okay. So as far as generating that random token, is there a standardized way of doing this? I did a little searching, and OAth came up quite a bit, but I am not familiar with that technology. Also, once I return that token to the device, how do I go about storing it? Keychain? or just write it to a file? Thanks! – bradleyrzeller Sep 06 '11 at 17:57
  • I just updated my answer with your question. Keychain is a lot harder to break so you should probably use it. Once the phone is stolen, everything could be broken and your best bet is to provide users with a way with remote ability to wipe the token. – momo Sep 06 '11 at 18:47