Groovy, Twitter, and Basic Authentication

The other day, Scott Davis published an article at developerWorks entitled Practically Groovy:  SwingBuilder and the Twitter API, Part 2.  I’m sure you won’t be surprised to hear that it’s a good article.  No surprise there, given Scott’s excellent reputation and abilities.

As it turned out, though, I was teaching a Java Web Security class when the article came out and we’d already discussed mechanisms for doing authentication.  In the article, Scott pointed out that while Twitter prefers OAuth authentication (see here for details), they allow for HTTP Basic authentication.

Scott wrote a nice Groovy GUI client, based on Groovy’s excellent SwingBuilder.  The authentication part looked like this:

def authString = "username:password".getBytes().encodeBase64().toString()
def conn = addr.toURL().openConnection()
conn.setRequestProperty("Authorization", "Basic ${authString}")

The process starts with a username and a password and concatenates them together with a colon in the middle. Then you convert the result into a byte array by calling getBytes(). Then, as you can see from the GroovyDocs, Groovy adds an encodeBase64() method to byte[]. The return type is a Writable, which is then converted back to a String using the normal toString() method.

Add the word “Basic” in front of it and you’ve got an authorization header that can be used in an HTTP request.

Okay, that’s cool, and it works, but whoa is that dangerous. Say I’m a sniffer on the network. I see a request go by, and inside it I find:

Authorization: dXNlcm5hbWU6cGFzc3dvcmQ=

We now have a beautiful illustration of the difference between encoding and encrypting. Just because this is Base 64 encoded doesn’t mean it can’t be read. All I have to do is write:

def (user,pass) = new String("dXNlcm5hbWU6cGFzc3dvcmQ=".decodeBase64()).split(':')

and lo and behold, I’ve got the username and password. This works because Groovy gives the String class a nice, convenient decodeBase64() method, and String has a constructor that takes the resulting byte array as an argument. I’m also using the new (as of Groovy 1.6) mechanism that allows me to return two separate values from a method call, so here I return the username and password separately from the split() method.

Of course, the real reason this works is that HTTP basic authentication passes the encoded string in nice, clear text. No decryption is required. If this was being transmitted over HTTPS, at least the network would be encrypted, but there’s no requirement for that.

Yikes. I’d guess the Twitter web site itself uses form authentication over HTTPS, but I wonder how many of those client-side Twitter applications are just doing basic authentication like this?

Maybe I should change my Twitter password.

Just for reference, here’s a complete script showing both encoding and decoding, with some assertions for completeness:

def u = 'username'
def p = 'password'
def encoded = "$u:$p".getBytes().encodeBase64().toString()
println "$u:$p -> $encoded"
assert encoded == 'dXNlcm5hbWU6cGFzc3dvcmQ='
def (user,pass) = new String(encoded.decodeBase64()).split(':')
println "(user,pass) = ($user,$pass)"
assert user == u
assert pass == p

About Ken Kousen
I teach software development training courses. I specialize in all areas of Java and XML, from EJB3 to web services to open source projects like Spring, Hibernate, Groovy, and Grails. Find me on Google+ I am the author of "Making Java Groovy", a Java / Groovy integration book published by Manning in the Fall of 2013, and "Gradle Recipes for Android", published by O'Reilly in 2015.

3 Responses to Groovy, Twitter, and Basic Authentication

  1. TheKaptain says:

    Indeed, basic auth is convenient, but the only thing that can keep it secure is dictating(and enforcing) a policy where https is ALWAYS used.
    Thanks for the clear description of the problem! And for pointing out the encode/decode methods that Groovy provides for simplifying the creation of the credential string.

  2. worked says:

    Twitter is turning off basic authentication June 2010.

  3. Ken Kousen says:

    Yeah, I heard about that. I think that’s a good idea. Now I have to dig into this OAuth stuff, though. 🙂

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: