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 am a Java Champion and the author of the books "Modern Java Recipes" (O'Reilly Media), "Gradle Recipes for Android" (O'Reilly Media), and "Making Java Groovy" (Manning), as well as over a dozen video courses at Safari Books Online. I'm a regular member of the No Fluff, Just Stuff conference tour and have given talks all over the world. Through my company, Kousen IT, Inc, I've taught training courses to and worked with thousands of developers.

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s

%d bloggers like this: