OAuth, twitter4j, and JavaFX

I’ve started developing a text-only client for Twitter. The impulse came from getting fed up with all the auto-playing promoted tweets that were clogging my timeline. I looked around and found a library to handle all the Twitter API calls and started coding. The example code was all a bit bare-bones, but mostly it was straightforward. The one thing so far that I think could use a bit more explanation is the login process, and that’s the point of this post.

There are tons of tutorials for how to do OAuth in a web app, but there are precious few that deal with doing authentication from within a desktop application without resorting to switching out to a web browser. This method gets around that problem by using the built-in web browser component in JavaFX, the WebView.

First, I created a simple FXML file with a GridPane that contains a WebView inside a ScrollPane, a TextField, and a Button. The WebView is for displaying the Twitter OAuth screens.

In the controller class, I initialize the WebView with the request for access:

@Override
public void initialize(URL location, ResourceBundle resources) {
    try {
        // get the initial OAuth request token
        _twitter = TwitterFactory.getSingleton();
        _requestToken = _twitter.getOAuthRequestToken();
        // fetch the auth URL (in a WebView, to let the user login and then grant authorization to the app)
        _view.getEngine().load(_requestToken.getAuthorizationURL());
    } catch (Exception e) {
        __l.error("Exception trying to perform OAuth login", e);
    }

}

It turns out that when the user grants access, Twitter displays a multi-digit number. What needs to happen is, the user copies the number into the TextField and clicks the Ok button. Here’s that handler:

@FXML
@SuppressWarnings("unused")
public void handleOK(ActionEvent evt) {
    String oauthPIN = _pin.getText();
    AccessToken accessToken;
    try {
        if (!oauthPIN.isEmpty()) {
            accessToken = _twitter.getOAuthAccessToken(_requestToken, oauthPIN);
        } else {
            accessToken = _twitter.getOAuthAccessToken();
        }
        // now we have an AccessToken, we send it to the callback for application use and storage
        _tokenConsumer.accept(accessToken, _stage);
    } catch (TwitterException te) {
        if (401 == te.getStatusCode()) {
            __l.error("Unable to get the access token.", te);
        } else {
            __l.error("Exception getting access token", te);
        }
    }

}

The callback gets registered during setup; it’s a method on the main window that accepts the AccessToken and persists it into the app’s preferences, and closes the login window.

Published by pirateguillermo

I play the bagpipes. I program computers. I support my family in their various endeavors, and I enjoy my wonderful life.

Leave a Reply

To respond on your own website, enter the URL of your response which should contain a link to this post's permalink URL. Your response will then appear (possibly after moderation) on this page. Want to update or remove your response? Update or delete your post and re-enter your post's URL again. (Find out more about Webmentions.)

Discover more from Mechadarwin

Subscribe now to keep reading and get access to the full archive.

Continue reading