Griffon and OAuth
Though giving your username/password deets to a locally running Java app can be infinitely more secure than giving it to an arbitrary website, it does involve a level of trust on the user's part. OAuth gives the user the peace of mind that you aren't doing anything hinky with their account details. In this post, we'll code a simple Griffon app with OAuth to use Twitter. First you'll need to login to Twitter. Go to http://twitter.com/apps and click Register a new application. Enter some details for your app and make sure to select Client as the Application Type. Don't worry about the Callback URL or the Default Access Type. Hit save and take note of the consumer and secret keys. Copy them into your GriffonOAuthModel.groovy file.
GriffonOAuthModel.groovy
import groovy.beans.Bindable
class GriffonOAuthModel {
@Bindable twitter
def consumerKey
def secretKey
@Bindable requestToken
@Bindable accessToken
}
Twitter's client OAuth process gives you a pin code to enter so we'll need a space to enter than in our user interface which will consist of two buttons and a text field.
GriffonOAuthView.groovy
application(title:'GriffonOAuth',
//size:[320,480],
pack:true,
//location:[50,50],
locationByPlatform:true,
iconImage: imageIcon('/griffon-icon-48x48.png').image,
iconImages: [imageIcon('/griffon-icon-48x48.png').image,
imageIcon('/griffon-icon-32x32.png').image,
imageIcon('/griffon-icon-16x16.png').image]
) {
vbox {
button(id:"login", "Login with Twitter",
actionPerformed: {controller.login() })
textField(id:"pinCode", columns:10)
button(id:"done", enabled:false, "Press here when done",
actionPerformed: {controller.showLastTweet()})
}
}
Our controller handles the heavy lifting of getting a request token, launching a browser and checking the validity of the pin code. If a valid access token exists, the app retrieves the last received direct message from the authenticated account.
GriffonOAuthController.groovy
import twitter4j.*
import twitter4j.http.*
import javax.swing.JOptionPane
class GriffonOAuthController {
// these will be injected by Griffon
def model
def view
void mvcGroupInit(Map args) {
// this method is called after model and view are injected
}
def login = {
model.twitter = new Twitter()
model.twitter.setOAuthConsumer(model.consumerKey, model.secretKey)
model.requestToken = model.twitter.getOAuthRequestToken()
def url = model.requestToken.getAuthorizationURL()
BareBonesBrowserLaunch.openURL(url)
view.done.enabled = true
}
def showLastTweet = {
try {
if (!model.accessToken) {
model.accessToken = model.twitter.getOAuthAccessToken(model.requestToken, view.pinCode.text)
}
def msg = model.twitter.getDirectMessages(new Paging(1,1))[0]
def sender = msg.getSender().getName()
def text = msg.getText()
def recipient = msg.getRecipient().getName()
def output = "From ${sender} to ${recipient} \n : ${text}"
edt {
JOptionPane.showMessageDialog(null, output)
}
} catch (TwitterException te) {
if (te.getStatusCode() == 401) {
edt {JOptionPane.showMessageDialog(null, "Unable to get access token.")}
} else {
te.printStackTrace()
}
}
}
}
The last little piece is a helper class from http://www.centerkey.com/java/browser/ to launch a browser from Java. I tweaked it a bit to add listings for chrome and google-chrome (the executable filenames of Chrome on Windows and Linux respectively) so that it didn't default to a Firefox browser.
Learn more about OAuth here.
Download the source code here.