OAuth2 mit Java: Versenden eines Tweets über die Twitter-API

In diesem Artikel werden die Grundlagen zu OAuth2 und das Setup einer OAuth2-Anwendung aus den letzten Artikeln anhand eines neuen Beispiels angewendet. Das beispielhafte Java-Programm in diesem Artikel soll sich automatisch bei Twitter authentifizieren und anschließend einen Tweet versenden können. Der Benutzer kann die Authentifizierungs-Anfrage bestätigen und den Authorization Code an das Programm weitergeben, welches ihn dann ein Access-Token umtauschen kann.

Abhängigkeiten

Da hier das Rad nicht neu erfunden werden soll, werden wir auf einige Bibliotheken zurückgreifen. Hier die Dependencies im Maven-Format:

<dependency>
   <groupId>commons-io</groupId>
   <artifactId>commons-io</artifactId>
   <version>2.6</version>
</dependency>

<dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
   <version>4.5.6</version>
</dependency>

<dependency>
   <groupId>oauth.signpost</groupId>
   <artifactId>signpost-commonshttp4</artifactId>
   <version>1.2.1.2</version>
</dependency>

Apache Commons IO wird verwendet, um mittels der IOUtils-Klasse den Inputstream, der als Antwort auf die Anfragen vom Webserver zurückkommt, in einen String zu aggregieren. Apache HTTP-Components wird für die Kommunikation über HTTP verwendet und SignPost unterstützt allgemein den OAuth2-Prozess. Es hilft dabei, zunächst den Authorization-Code anzufordern, ihn in ein Access-Token umzutauschen und dieses dann an die API-Calls anzuhängen.

Ein Erster Tweet

Zunächst versuchen wir einmal, überhaupt einen Tweet über die Twitter-API zu verschicken. Nachdem wir eine OAuth2-Anwendung in Twitter als App aufgesetzt haben (vergleichbar wie bei GitHub in einem vorherigen Blogartikel), können wir uns dort ein fertiges Access-Token mit einem Secret holen (siehe Abbildung unten).

Twitter-Java-Connector App im App-Dashboard von Twitter Developers

Dieses Token mit Secret können wir dann für unseren ersten Test-Tweet verwenden. Der Java-Code dazu:

public static void tweet(String tweetText, String accessToken, String accessTokenSecret) throws Exception { // OAuthConsumer mit KEY und SECRET erstellen
        final OAuthConsumer oAuthConsumer = new CommonsHttpOAuthConsumer(API_KEY, API_KEY_SECRET); // Access-Token und Secret setzen
        oAuthConsumer.setTokenWithSecret(accessToken, accessTokenSecret); // API-Call erstellen
        final HttpPost httpPost = new HttpPost("https://api.twitter.com/1.1/statuses/update.json?status=" + tweetText); // API-Call mit Access-Token versehen
        oAuthConsumer.sign(httpPost);
        try (final CloseableHttpClient httpClient = HttpClientBuilder.create().build()) { // API-Call ausführen
            final HttpResponse httpResponse = httpClient.execute(httpPost);
            System.out.println(IOUtils.toString(httpResponse.getEntity().getContent(), Charset.forName("UTF-8")));
        }
    }

Die tweet-Methode erhält als Parameter insgesamt drei Textstrings. Der erste beinhaltet den Tweet, der zweite das Access-Token und der dritte das Secret zum Access-Token. In Zeile 3 wird zunächst ein Objekt vom Typ OAuthConsumer erstellt, welches bei der Initialisierung den API-Key und das API-Secret (siehe Twitter-Developers-Screenshot oben) erhält. Dieser OAuthConsumer bekommt anschließend in Zeile 5 das Access-Token mit Secret gesetzt, welches vorher an die Methode übergeben wurde. Danach wird ein Objekt vom Typ HttpPost erstellt, welches die POST-Anfrage an den Twitter-API-Endpunkt zum Tweeten enthält. Dieses Anfrageobjekt erhält dann vom OAuthConsumer das Token (Zeile 11) und wird über einen HttpClient abgeschickt (Zeile 15). Die Anfrage kommt als Input-Stream und wird mit Hilfe der Klasse IOUtils in Zeile 16 in einen String transformiert. Der Methodenaufruf sieht wie folgt aus:

tweet("Test%20Tweet", ACCESS_TOKEN, ACCESS_TOKEN_SECRET);

Hier das Resultat:

Test Tweet

Und die Antwort:
{"created_at":"Mon Jan 14 15:26:40 +0000 2019","id":1084834189063663616, .... }

Das war jetzt natürlich etwas einfach, da wir dem Programm ja bereits alles gegeben haben, was es zur Authentifizierung bei der Twitter-API benötigt. Im nächsten Schritt soll das Programm daher selbstständig einen Authorization Code anfordern und in ein Access-Token umtauschen.

Tweet mit automatischer Authentifizierung

Jetzt soll also zunächst einmal ein Authorization Code vom entsprechenden Endpunkt der Twitter-API nach Bestätigung durch den Benutzer angefordert werden. Dieser soll dann beim Access-Token-Endpunkt umgetauscht werden. Schließlich soll mit diesem Access-Token ein Tweet gesendet werden. Der entsprechende Java-Code:

final String AUTH_URL = "https://api.twitter.com/oauth/authenticate";
        final String ACCESS_TOKEN_URL = "https://api.twitter.com/oauth/access_token";
        final String REQUEST_TOKEN_URL = "https://api.twitter.com/oauth/request_token"; // OAuthConsumer mit KEY und SECRET erstellen 
        final OAuthConsumer oAuthConsumer = new DefaultOAuthConsumer(API_KEY, API_KEY_SECRET); // OAuthProvider mit den korrekten URLs definieren 
        final OAuthProvider provider = new DefaultOAuthProvider(REQUEST_TOKEN_URL, ACCESS_TOKEN_URL, AUTH_URL); // Authorize-URL anfordern
        final String authUrl = provider.retrieveRequestToken(oAuthConsumer, OAuth.OUT_OF_BAND); // Authorize-URL im Webbrowser anzeigen
        Desktop.getDesktop().browse(URI.create(authUrl)); // PIN/Authorization Code per Konsole anfordern 
        System.out.print("Authorization Code eingeben: ");
        final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        final String pin = br.readLine(); // PIN in Access-Token umtauschen 
        provider.retrieveAccessToken(oAuthConsumer, pin); // API-Call mit erhaltenem Token und Secret 
        tweet("Test%20Tweet", oAuthConsumer.getToken(), oAuthConsumer.getTokenSecret());

Im ersten Schritt (Zeile 6) wird wieder ein OAuthConsumer mit API-Key und API-Secret erstellt. Zusätzlich wird dieses Mal noch ein Objekt vom Typ OAuthProvider erstellt, welches später die Authorize-URL anfordern und den Authorization Code in ein Access-Token umtauschen soll. Dafür benötigt der OAuthProvider die URLs, um Tokens anzufordern, Tokens umzutauschen und sich zu authentifizieren.

Zunächst lässt der OAuthProvider einen Link generieren, auf dem der Benutzer die App autorisieren und einen Authorization Code generieren kann (Zeile 12). Dieser wird dann gleich im Webbrowser geöffnet:

Der Benutzer muss nun die App autorisieren.

Nachdem die Autorisierung durch den Benutzer mittels eines Klicks auf die blaue “Autorisiere App“-Schaltfläche geschehen ist, wird der Benutzer auf eine Seite weitergeleitet, auf welcher der Authorization Code angezeigt wird. Dieser kann dann manuell vom Benutzer kopiert werden. Im Java-Code wartet in den Zeilen 18-20 ein Scanner auf diesen Authorization Code.

Nachdem der Scanner den Code eingelesen hat, wird schließlich vom OAuthProvider in ein Access-Token mit Secret umgetauscht, welches dann gleich im OAuthConsumer abgelegt wird (Zeile 23). Abschließend kann mit der tweet-Methode aus dem vorherigen Codebeispiel der Tweet wie gehabt verschickt werden (Zeile 26).

Short URL for this post: https://wp.me/p4nxik-3e1
Steffen Jacobs

About Steffen Jacobs

Java Consultant & Developer at Orientation in Objects GmbH. Follow me on Twitter and find me on LinkedIn and Xing. Some of the source code associated with the blog articles can be found on GitHub.
This entry was posted in Web as a Platform and tagged , , , . Bookmark the permalink.

Leave a Reply