10

I'm building a simple API that will be used in an android app (that only about 3-4 users will ever have). The app connects to the server and sends GET/PUT requests.

I've read through my googling that if you are using SSL, sending passwords as plaintext without encrypting them with something like HMAC is OKAY.

People, do, however, recommend that you use "basic authentication" which is basically username:password encoded in base64 in the HTTP header. Is there a reason why I shouldn't just send the body fields "username" and "password" unencoded if I am using SSL? If a hacker really was to somehow get through the SSL why would it matter if it was encoded using base64? Surely if he is able to somehow get through the SSL he would be able to base64 decode?

Just wanted your opinions on if I should even bother doing base64 encode, thanks.

  • 4
    The base64 encoding is not meant to encrypt or obfuscate. It is used because the character set in base64 helps alleviate problematic characters that may cause trouble in HTTP. – amccormack Jun 13 '15 at 1:36
  • 1
    Ahhh I did not know that! Is there any benefit of sending that base64 encoded string in the HTTP header as "Authorization" versus sending it in the body as a form field? – Shivang Saxena Jun 13 '15 at 1:49
  • I'm putting together an answer for this as it requires a bit of an explanation. – amccormack Jun 13 '15 at 1:52
11

The point of difference between using HTTP Authentication vs Application specific authentication is where you want the authentication and authorization logic to be handled.

HTTP Authentication means that the HTTP layer (apache, nginx, IIS, etc) will responsible for maintaining authentication. Application authorization means that the web application (java, php, django, etc) would control authentication and authorization.

Why the difference?

Remember that HTTP is stateless. Thus, by adding an authorization component, HTTP can prevent or allow users to access certain resources. The most likely use of this kind of authorization is when you don't have any application logic yourself. For example, if you want to allow file directory browsing in apache, but only to certain users, you can modify the .htaccess file to restrict the directory to certain users.

However there are many reasons why applications handle the authorization logic instead of the HTTP server. First, most applications handle sessions. This is done by using cookies. Thus, only the cookie value must be retransmitted. If you are handling sessions in the application layer, it will almost always be easier to handle authorization in this layer as well. Almost always, sessions are preferred because the content of your application will be dependent on "who" is doing something.

But my application can read the HTTP Headers, why use forms if HTTP provides a mechanism?

A further benefit to using sessions includes the implicit ability to log out. Because HTTP authorization has no concept of a session, you can't really log out. It would be up to the browser (or in your case, the Android application) to forget the credentials, but the server has no control over it. Even if your server wants to enforce some kind of log out, it can't with HTTP Authorization.

Security benefits of form based authentication

Because form based authentication generally involves sessions, it is usually more secure, so long as the security of your resources are dependent on sessions.

Security benefits of HTTP Authentication

HTTP Basic authentication is worse than forms based authentication because of the lack of sessions. However, you can get some benefits by using HTTP Digest Authentication, which computes hashes against credentials and nonces to avoid sending plain text credentials. Thus there is a tradeoff between sending clear credentials or letting the server side application maintain the session.

Can't I compute hashes on the client side before transmitting the credentials?

For browser based applications, many people think using javascript to compute a hash before sending a credential is better than using a plain text password, but these people are wrong. In order to protect the password, the server sends client code that it must run. However, if an attacker is in a position to talk to the client, he can substitute this code for his own. Thus, the security benefit of using javascript to compute a hash is so minimal it is rarely done.

Since you mentioned using this API within an Android Application, hashing does make sense. Because you can compute the hash with a predefined client routine, there are clear benefits to using a hashing mechanism as described in RFC 2607. I would still recommend performing authorization in the application layer though, as you want to manage sessions for a user.

2

I like to tell people "HTTP Basic Auth is deprecated, don't use it!" in favor of forms-based authentication. However, over SSL it is indeed secure in transit and not vulnerable to easy interception. On the browser level, forms-based authentication tends to be more secure. For an android app using a REST api, I would recommend a token-based system. However, I would not say that basic auth over SSL is insecure; I'd call it "barely acceptable."

The purpose of hashing the password with something like SHA256-HMAC is not only to secure the password in transit. In this case the server is only receiving the hash of the password and is validating that. In such a way, the hash is in fact the password. HMAC adds additional security on top of that preventing an attacker from easily sending the same hash.

Hashing the password ensures that the server never knows what the user's password actually is. So, if the database is stolen, the user's passwords at least cannot be reverse-engineered.

Note that proper implementation of this requires "salting" the hashes with a unique salt per user to prevent an attack using "rainbow tables." Do research this if you plan to implement password hashing.

  • 1
    Thank you for your response! Just to clarify, every time you say "forms-based authentication" do you mean sending "username" and "password" as plaintext as form fields, like I described in the OP? Or do you mean using HMAC to create a digest and sending that? I am already salting my hashes (with a unique salt) before storing them, I was just wondering if I should follow http basic auth standard procedures and base64 user:pass or just send it unencrypted/unencoded as a form field. – Shivang Saxena Jun 13 '15 at 1:26
  • 2
    As a best practice, I would recommend using an HTTP form field (post request) that encodes on the client side sends the password with SHA2-HMAC. I think that without using hashing, sending it as an HTTP request in the body is only marginally better than using HTTP basic authentication; but I would not recommend either. If you're already salting and hashing in your database, good job; go all the way and have the client send you hashes too. – Herringbone Cat Jun 13 '15 at 1:51
  • If using an HMAC, I'd also include a server supplied nonce, to help prevent replay attacks. – amccormack Oct 17 '15 at 2:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.