BrowserID

Ich schreibe gerade einen Artikel für das t3n Magazin über aktuelle Sign-In-Mechanismen und hab mir in dem Zuge BrowserID mal etwas genauer angeschaut. Ich bin wirklich extrem überrascht mit wie wenig Arbeit es sich in z.B. WordPress einbauen lässt.

BrowserID besteht eigentlich nur aus einem JS-File,ein paar Zeilen JS-Code:

<script src="https://browserid.org/include.js" type="text/javascript"></script>
<script type="text/javascript">
navigator.id.get(function(assertion) {
    if (assertion) {
        // This code will be invoked once the user has successfully
        // selected an email address they control to sign in with.
    } else {
        // something went wrong!  the user isn't logged in.
    }
});
</script>

und dem anschließenden Verifizieren der assertion:

$ curl -d "assertion=&audience=https://mysite.com" "https://browserid.org/verify"
{
    "status": "okay",
    "email": "lloyd@example.com",
    "audience": "https://mysite.com",
    "expires": 1308859352261,
    "issuer": "browserid.org"
}

Den ausführlichen Ablauf der Authentifizierung findet ihr auf Github.

Um BrowserID in WordPress zu integrieren lädt man also zuerst den JS-Code in den Login Header:

// add the BrowserID javascript-code to the header
add_action('login_head', 'bi_add_js_header');
function bi_add_js_header() {
  echo '<script src="https://browserid.org/include.js" type="text/javascript"></script>';
  echo '<script type="text/javascript">'."\n";
  echo 'function browser_id_login() {
    navigator.id.get(function(assertion) {
      if (assertion) {
        window.location="' . get_site_url(null, '/') .'?browser_id_assertion=" + assertion;
      } else {
        // do nothing!
      }
    })
  };'."\n";
  echo '</script>';
}

und platziert den BrowserID-Button auf der Login-Seite:

// add the login button
add_action('login_form', 'bi_add_button');
function bi_add_button() {
  echo '<p><a href="#" onclick="return browser_id_login();"><img src="https://browserid.org/i/sign_in_blue.png" style="border: 0;" /></a></p>';
}

Nach dem klick auf den Button öffnet sich das Autorisierungs-Fenster von BrowserID und nach dem erfolgreichen Sign-In wird die gerade implementierte Methode navigator.id.get(function(assertion) {} aufgerufen.

BrowserID login window

Im nächsten Schritt muß man die erhaltene assertion über BrowserID.org verifizieren. Da ich den notwendigen POST nicht über JavaScript absetzen will, leite ich einfach auf eine Seite weiter und übergebe die erhaltene assertion als GET-Paramater.

if (assertion) {
  window.location="' . get_site_url(null, '/') .'?browser_id_assertion=" + assertion;
}

Jetzt kann der POST bequem über WordPress abgesetzt werden.

// the verification code
add_action('parse_request', 'bi_verify_id');
function bi_verify_id() {
  global $wp_query, $wp, $user;

  if( array_key_exists('browser_id_assertion', $wp->query_vars) ) {
    // some settings for the post request
    $args = array(
      'method' => 'POST',
      'timeout' => 30,
      'redirection' => 0,
      'httpversion' => '1.0',
      'blocking' => true,
      'headers' => array(),
      'body' => array(
        'assertion' => $wp->query_vars['browser_id_assertion'], // the assertion number we get from the js
        'audience' => "http://".$_SERVER['HTTP_HOST'] // the server host
      ),
      'cookies' => array(),
      'sslverify' => 0
    );

    // check the response
    $response = wp_remote_post("https://browserid.org/verify", $args);

    if (!is_wp_error($response)) {
      $bi_response = json_decode($response['body'], true);

      // if everything is ok, check if there is a user with this email address
      if ($bi_response['status'] == 'okay') {
        $userdata = get_user_by('email', $bi_response['email']);
        if ($userdata) {
          $user = new WP_User($userdata->ID);
          wp_set_current_user($userdata->ID, $userdata->user_login);
          wp_set_auth_cookie($userdata->ID, $rememberme);
          do_action('wp_login', $userdata->user_login);

          wp_redirect(home_url());
          exit;
        } else {
          // show error when there is no matching user
          echo "no user with email address '" . $bi_response['email'] . "'"; 
          exit;
        }
      }
    }
    
    // show error if something didn't work well
    echo "error logging in"; 
    exit;
  }
}

Gibt es einen User mit der entsprechenden E-Mail – Adresse wird er eingeloggt, falls nicht, wird ein Fehler ausgegeben.

Bei der Demo hab ich mir aus Zeitgründen ein wenig Code bei Marcel Bokhorst geliehen, dessen BrowserID-Plugin wesentlich ausgereifter und vollständiger ist als der kleine Demo-Code den ich hier zusammengestückelt habe.

Wenn euch das zu schnell ging und ich auf einige Details nicht genügend eingegangen bin, könnt ihr gerne fragen 🙂

Ich habe den kompletten Code übrigens auch auf Github hochgeladen… das ist einfacher als sich alles zusammen zu kopieren.

HTML5 LogoDass HTML5 ein paar neue input-types definiert, habe ich durch die hcard-input-brainstorming so am Rande auf geschnappt, mir aber nichts weiter dabei gedacht… Durch Zufall bin ich heute aber über folgenden Tweet von Sylvia Egger gestoßen:

Just implemented native #HTML5 form validation on #wp comments form – it‘ quite simple & should be in #wp default theme

und habe bissle recherchiert… Mit den neuen Input-Types ist es doch tatsächlich möglich Input-Felder über den Browser validieren zu lassen… Ich bin begeistert! 🙂

Trägt man beispielsweise eine Nicht-Email-Adresse in folgendes Feld…

<input type="email" />

bekommt man…

Email Validation im Firefox

Schön wenn man sich noch über solche Kleinigkeiten freuen kann oder 😉

Lange rede kurzer Sinn: Da WordPress alle Formulare an zentraler Stelle definiert, ist es ziemlich einfach sie mit ein paar neuen Input-Types zu versehen. Mit dem folgenden Code wird das Kommentar-Formular mit den Typen „email“ und „url“ und das Suchformular mit dem Typ „search“ (funktioniert nur in den WebKit-Browsern) erweitert:

Code-Update: Eric Eggert hat mich in den Kommentaren darauf hingewiesen, dass man mit <input required /> auch noch die Pflichtfelder validieren kann. Danke!

Code-Update 2: Dank maxe werden jetzt auch die WordPress Settings berücksichtigt (Comment author must fill out name and e-mail) und das „Comment“-Feld ist natürlich auch required

<?php
/*
Plugin Name: html5 input-types
Plugin URI: http://notiz.blog/
Description: Adds the new HTML5 input-types to WordPress' default forms
Version: 0.1
Author: pfefferle
Author URI: http://notiz.blog/
*/

add_filter("comment_form_default_fields", "change_comment_input_types");

function change_comment_input_types($fields) {
  if (get_option("require_name_email", false)) {
    $fields['author'] = preg_replace('/<input/', '<input required', $fields['author']);
    $fields['email'] = preg_replace('/"text"/', '"email" required', $fields['email']);
  } else {
    $fields['email'] = preg_replace('/"text"/', '"email"', $fields['email']);
  }

  $fields['url'] = preg_replace('/"text"/', '"url"', $fields['url']);

  return $fields;
}

add_filter("get_search_form", "change_search_form_input_types");

function change_search_form_input_types($form) {
  return preg_replace('/"text"/', '"search"', $form);
}

add_filter("comment_form_field_comment", "change_comment_field_input_types");

function change_comment_field_input_types($field) {
  return preg_replace('/<textarea/', '<textarea required', $field);
}
?>

Funktioniert als Plugin und in Child-Themes (einfach in die functions.php kopieren).

Danke auch an Marc Görtz der mich über Twitter reichlich mit Links zu dem Thema versorgt hat:

Testen könnt ihr das übrigens hier auf notiz.blog.

Erst filtern, dann abonnieren!Die Informationsflut im Internet nimmt immer mehr zu und FeedReader bieten bisher keine wirkliche Möglichkeit diese Informationen sinnvoll zu filtern und da man nicht wirklich (zeitnah) Einfluss auf die Weiterentwicklung von NetNewsWire, Google Reader & Co. hat, bleibt nur noch eins: Erst filtern, dann abonnieren!

NoisePress erlaubt Seitenbesucher, einen RSS/ATOM-Feed mit Hilfe von APML vorzufiltern.

(Zum ausprobieren braucht man ein APML-Profil. Wer keines hat, sollte sich entweder das WordPress Plugin installieren oder heimlich Carstens Profil benutzen 😉 )

Warum mit APML filtern?

Man könnte natürlich auch mit WordPress-Bordmitteln eine Menge Rauschen ausfiltern, und wirklich nur das abonnieren was gerade wichtig ist:

Das Problem: Ändert sich dieses Interesse, müssen alle Feeds mühsam aussortiert (und neue gesammelt) werden. Außerdem besteht die Gefahr, dass einige spannende Themen, die nicht genau die abonnierte Kategorie/den abonnierten Tag besitzen, durch das Raster fallen können.

Das Prinzip von NoisePress: APML ist eine Art semantische Tag-Clound die das Interesse einer Person widerspiegelt. Das Interessens-Profil wird in der Regel automatisch generiert und sollte sich somit auch den diversen Interessensveränderungen anpassen.

Am Beispiel WordPress Plugin: Das Plugin erstellt ein APML-File anhand der Häufigkeit der verwendeten Tags und Kategorien. Schreibt jemand viel über OpenID, kann man davon ausgehen, dass er das Thema für wichtig hält. Ändert sich der Fokus des Blogs, wird OpenID auch im APML-Feed immer irrelevanter.

Hört sich nach Geek-Zeugs an?

Richtig! 🙂 …aber NoisePress ist auch erst einmal nur ein Test ob meine Idee überhaupt funktioniert! Im besten Fall soll der User von all der Technik gar nichts mitbekommen. Ich hoffe dass sich Firefox‘ Account Manager oder XAuth schnell weiter entwickeln und ich eine dieser Techniken für NoisePress missbrauchen könnte.

Ich würde mich übrigens sehr über ein bisschen Feedback freuen!

OpenID-Plugin für Safari
Safari 5 (mit Addon-Support) ist gerade mal eine starken Woche alt und schon gibt es die erste OpenID-Erweiterung.

OpenID-Plugin für Safari

Das Plugin kann zwar nicht viel mehr als OpenID-Felder automatisch auszufüllen, aber wie heißt es so schön… immerhin mal ein Anfang.

» openid.safariextension

{ „protocol“:“pubsubhubbub“, „format“:“json“ }
Monica Keller (Facebook) und Martin Atkins (Six Apart) arbeiten an einer JSON-Variante von pubsubhubbub. Besonders Facebook, deren OpenGraph-API ausschließlich auf der JavaScript serialisierung basiert, scheint großes Interesse an dem offenen Push-Protokoll zu haben. Schön dass der Internet-Gigant sich die Mühe gibt, einen Standard voran zu treiben, anstatt ein eigenes Format zu entwickeln.

» Spec: PubSubHubbub for JSON
» Talk: PubSubHubbub for JSON

HTML5 Microdata
Ein weiterer ausführlicher Artikel über Microdata mit ein paar schönen Anwendungsfällen.

» HTML5 Microdata: Welcome to the Machine

Ich habe mal ein kleines Plugin geschrieben welches den WordPress-Atom-Feed mit der ActivityStream-Syntax erweitert.

 <entry>
  <id>http://notiz.blog/?p=1775</id>
  <author>
    <name>Matthias Pfefferle</name>
    <uri>http://notiz.blog</uri>
  </author>
  <...>
  <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
  <activity:object>
    <activity:object-type>http://activitystrea.ms/schema/1.0/blog-entry</activity:object-type>
    <activity:object-type>http://activitystrea.ms/schema/1.0/article</activity:object-type>
    <id>tag:notiz.blog,2009-07-13:/post/1775</id>
    <title type="html"><![CDATA[Matthias Pfefferle posted a new blog-entry]]></title>
    <link rel="alternate" type="text/html" href="http://notiz.blog/2009/07/14/webstandards-kolumne/" />
  </activity:object>
</entry>

Die Syntax ist dazu gedacht, dem Feed-Parser/Feed-Reader zu erklären um was für einen Eintrag es sich handelt. Bei WordPress sind die <entry />s ausschließlich Blogposts/Artikel…

<activity:object-type>http://activitystrea.ms/schema/1.0/blog-entry</activity:object-type>
<activity:object-type>http://activitystrea.ms/schema/1.0/article</activity:object-type>

…die gepostet wurden.

<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>

Und für die Dienste wie NoseRub, die die Aktivität gerne in einen Satz packen, gibt’s das ganze auch noch in Prosa.

<title type="html"><![CDATA[Matthias Pfefferle posted a new blog-entry]]></title>

Das ActivityStream Schema definiert übrigens noch ’ne ganze Reihe an weiteren Objekten und Verben, die auf alle möglichen Aktionen im Netz passen. Falls ihr also noch welche findet, die zu WordPress passen könnten… lasst es mich wissen 😉

Es gibt leider aber auch ein paar Probleme mit der Syntax und diversen Feed-Readern, die das zweite <title /> im <activity-object /> mit interpretieren und dann beide Titel ausgeben… aber da ja auch MySpace und Facebook die ActivityStream-Syntax einsetzen ist dieser Fehler sicherlich bald bei jedem Feed-Reader behoben 😉

Viel Spaß beim ausprobieren!

Gute Neuigkeiten! Michael Kaply, der die Weiterentwicklung von Operator (ein Microformats Addon für Firefox) Ende 2008 eingestellt hat…

Operator – Deciding what to do with Operator is difficult. […] That being said, I’m going to do a few fixes for Operator, call it 1.0 and then stop development.

widmet sich jetzt doch wieder dem de facto (Microformats) Browser Plugin

The biggest news I have is that I have resumed work on Operator. In particular, I’m fixing bugs, adding a few usability enhancements and adding support for new microformat stuff like the value class/pattern for dates. I’m also considering completely removing the “Actions” toolbar and switching to interacting only with the data. I’m definitely looking for feedback on that one.

Wer Ideen zu neuen Features oder Funktionen hat, kann diese gerne auf Michaels Weblog loswerden.
Mein Wunsch: Microdata support 🙂

(Ich hoffe dass die Angekündigten value-class-pattern Änderungen eventuell auch irgendwann in die native Microformats Firefox API aufgenommen werden.)

Ich lese in letzter Zeit wieder immer häufiger von Microformats-Implementierungen im Internet Explorer 8. Geht es da „nur“ um die schon angekündigten Webslices? Weiß jemand mehr?

Übrigens hat Mix Online, „a community for web designers and developers“ von Microsoft, gerade ein recht schickes Microformats Toolkit mit dem Namen Oomph veröffentlicht.

Weiterlesen

Die beste Methode sich mit einer Sache zu beschäftigen ist, einen sinnvollen Anwendungsfall zu schaffen… Bei dem „näher beschäftigen“ mit Ubiquity ist ein WordPress-Plugin rausgekommen 🙂

Das WordPress-Plugin erstellt eine Ubiquity-Suche für das eigene Weblog (Quellcode) mit dem Command „search-<Blog-Titel>“

ubiquity-wordpress-command.jpg

Das kann teilweise (wie im Falle meines Blogs: search-notizblog-a-private-weblog-written-by-matthias-pfefferle) ziemlich lang werden, was aber nicht weiter schlimm ist da auch schon der Anfang des Commands (z.B. search-notizblog) reicht…

Viel Spaß beim ausprobieren 🙂

Wie schon im Lifestream erwähnt, habe ich mir (um das Template nicht ändern zu müssen) ein simples six groupsLivecommunity WordPress-Plugin gebaut und vielleicht findet ja auch noch jemand anders Verwendung dafür… 🙂

Funktionsweise:

Wenn irgendwas nicht so funktioniert wie es soll, lasst es mich wissen.