Skip to content

OAuth Problem

We’d like to publicly show our appreciation for Twitter’s role in helping to minimize premature publicity of this threat, even at its own expense, taking the heat as if it was their own issue in order to allow other companies to address this threat.
Die Abschaltung der OAuth Authentifizierung bei Twitter Services führte zu einem Pressesturm. Das ReadWrite Web Blog hat jetzt eine (etwas aufgeblasene) Zusammenfassung der Ereignisse veröffentlicht. Persönlich finde ich - jetzt nachdem die Fakten klar sind - die ganzen Reaktionen etwas übertrieben. Immerhin ist es weiterhin so, dass Millionen von Anwender OAuth nicht nutzen (können) und Ihre Web 2.0 Passwörter weiterhin in dutzenden Third-Party Anwendungen eingeben um deren Dienste zu nutzen. Ein Session Fixation Angriff, wie er bei OAuth möglich ist hat dabei doch wesentlich weniger weitreichende Konsequenzen. Entsprechend ist auch das Ergebnis, dass alle OAuth APIs wieder aktiviert wurden, und das Protokoll nur in einem langfristigen Community Prozess noch etwas verbessert werden kann. Interessanterweise scheint die Flickr API Authentication dieses Problem z.B. nicht zu haben. Zum einen wird nach einem Authorisierungsversuch der Benutzer auf eine festgelegte WebSeite des Anbieters verwiesen, und zum anderen kann der Authorisierungstoken (frob) nur vom Dienstanbieter mit einem Signierten Request in einen Auth Token umgewandelt werden. Ich hab mir mal ne Mühe gemacht eine kleine Google Appengine Anwendung zu erstellen die diesen Vorgang vorführt.

Ticker auf dem iPhone

Für mich ist das iPhone ein praktischer Begleiter, der oft den Blick auf den Notebook erspart. Ich wechsle öfters zwischen dem Twitter Client, der Xing Status Meldung, Mails, diversen Web Seiten und Feeds hin und her. Um das etwas zu verbessern habe ich nach einem Ticker gesucht. Zwar hat das iPhone OS noch nicht den Event-Push Dienst, den Apple für 3.0 angekündigt hat, aber es gibt im Cydia Repository ein nettes Winterboard Widget mit Namen iTicker. Dieses zeigt auf der Springboard Menu Seite RSS Einträge an. Das ganze ist eine HTML Seite mit etwas CSS und JavaScript kann man also gut seinen Bedürfnissen anpassen. Ich habe es so erweitert, dass es 2 Einträge pro Seite anzeigt und das Author Feld farblich abgesetzt voranstellt. Da stellt sich jetzt nur die Frage, welchen Feed ich hier anzeigen will. Es gibt einige Diente die Meldungen bereitstellen die für mich relevant sind. Manche Dinge sind dabei wichtiger und sollen nicht im endlosen Updates-Strom untergehen. Manche Meldungen erhalte ich über mehrere Feeds. Aber es gibt ja zum Glück Yahoo Pipes. Hier kann ich mehrere RSS Feeds aggregieren, filtern und nachbearbeiten. Zum Beispiel nehme ich mindestens das letzte Tweet meiner Frau (wenn dies nicht älter als einen Tag ist) und einige Tweets aus dem Facebook Friends News Feed. Das kopiere ich alles zusammen, entferne Duplikate anhand vom Link und schneide den Namen aus dem Titel ab und stecke Ihn (falls nicht schon vorhanden) in das Author Feld. Im iTicker habe ich die Pipe fest hinterlegt, kann deren Inhalt aber jederzeit grafisch zusammenstellen. Bei dem ganzen Unterfangen hat es mir geholfen dass ich die iTicker Dateien einfach auf dem Windows Rechner bearbeitet habe. Diese sind in Firefox lauffähig, und dank Firebug Extension war das JavaScript und CSS Debugging auch recht einfach. Um auf dem iPhone Änderungen zu machen habe ich die Dateien per SSH und vi geändert, anschliessend hilft mir die SBSettings Erweiterung das Springboard schnell neu zu starten ("Respring"). Jetzt muss ich nur noch herausfinden wie ich die Updates des Feeds besser kontrollieren kann. Irgendwie scheint da noch eine Google JS Feeds Library nicht ganz mitzuspielen.

Lambdas in Java

Gerade bastle ich an einem Wrapper für DataSources der im Umgang mit Datenbanken helfen soll (zusätzliche Statistiken, blocking bei DB Fehlern und pausieren von DB Anfragen). Dabei wrappe ich zwei Methoden getConnection() und getConnection(String, String). Nur der Aufruf der realen Methode unterscheidet sich, der restliche Code ist in beiden Methoden gleich:

CODE:
public Connection getConnection(String user, String pass) ... {     verifyState();       while(true) {         try {             Connection c = ds.getConnection(user, pass);             verifyConnection(c); // throws SQLEx             return c;         } catch (SQLException e) {             handleException(e); // throws SQLEx         }     } } public Connection getConnection() ... {     verifyState();       while(true) {         try {             Connection c = ds.getConnection();             verifyConnection(c); // throws SQLEx             return c;         } catch (SQLException e) {             handleException(e); // throws SQLEx         }     } }

Im Sinne von DRY (don't repeat yourself) ist dies aber unschön, weil der (in Realität noch komplexere) Retry code doppelt vorkommt, und ich immer beide Methoden anpassen muss. Dieses Problem kommt oft bei Frameworks vor, und nennt sich "the whole in the middle" Muster. Eine Lösung wäre:

CODE:
public Connection getConnection(String user, String pass) {     return smartConnect(true, user, pass); } public Connection getConnection() {     return smartConnect(false, null, null); } Connection smartConnect(boolean hasArgs, String user, String pass) {     verifyState();       while(true) {         try {             Connection c;             // --- the whole in the middle             if (hasArgs)                 c = ds.getConnection(user, pass);             else                 c = ds.getConnection();             // ---             verifyConnection(c); // throws SQLEx             return c;         } catch (SQLException e) {             handleException(e);         }     } }

Das funktioniert aber nur im einfachsten Fall und es verkompliziert leider den Framework code, was auch wieder der Verständlichkeit schadet.

In C# 3.0 kann man das (wie ich grade gesehen habe) mit einer Lambda Action lösen (man kann also im Prinzip anonyme Funktionsblöcke übergeben). In Java müßte man dazu ein Objekt übergeben:

CODE:
public Connection getConnection(String user, String pass) {     return smartConnect(         new ConnectionProvider() {              Connection provide() { return ds.getConnection(user, pass); }}); } public Connection getConnection() {     return smartConnect(         new ConnectionProvider() {             Connection provide() { return ds.getConnection(); }}); } Connection smartConnect(ConectionProvider cp) {     verifyState();       while(true) {         try {             Connection c = cp.provide();             verifyConnection(c); // throws SQLEx             return c;         } catch (SQLException e) {             handleException(e); // throws SQLEx         }     } } abstract class ConnectionProvider {   Connection provide(); }

Der smartConnect() code wird damit lesbarer, und man kann auch komplexere Aktivitäten injizieren (eventuell mit Argumenten zur provide() methode), aber man muss jetzt noch eine extra Klasse definieren und alles in allem wird es auch mehr Code. Bei jedem Aufruf wird ein zusätzliches Objekt erzeugt. Ich denke ich werde also eher bei dem "if" Ansatz bleiben.

Ich vermute mal der Syntaktische Zucker "Lambda Expression" erzeugt bei C# auch ein extra Call Objekt, aber es fällt wesentlich weniger zusätzlichen Code beim Aufruf an.