U2F ist ein von Google getriebener Standard, welcher unter dem Namen “FIDO” geführt wird. In Zusammenarbeit mit Yubico wurde die FIDO Alliance gegründet, welche fortan die Weiterentwicklung des FIDO-Standards übernimmt und überwacht. Kern dieses Standards ist ein USB-Dongle, welcher in Zusammenarbeit mit einer Software (bspw. Google Chrome) in der Lage ist eine Zweifaktor-Authentifizierung mittels eines Hardware-Dongles im Web zu realisieren. Einige Dienstleister bieten bereits die Möglichkeit an, den Login-Prozess mit Hilfe eines solchen USB-Dongles zusätzlich abzusichern. Neben den klassischen Verfahren wie One-Time-Passwords (OTP), welche ohne spezielle Soft- und Hardwarebindung auskommt, ist der Zugriff des Browsers auf das USB-Gerät für die U2F-Authentifizierung eine notwendige Voraussetzung und wird daher aktuell nicht von allen Browsern nativ unterstützt.
Um die in diesem Beitrag gezeigten Beispiele selbst ausprobieren zu können ist ein FIDO kompatibler Hardware-Dongle wie bspw. der ”YubiKey” notwendig. Zudem wird eine Node.JS-Umgebung in Version 4 benötigt. Aktuell ist der Zugriff auf den Dongle nur über Google Chrome ohne Zusatzsoftware möglich, sodass es sich anbietet, die Beispiele in diesem Browser auszuprobieren.
localhost
aufgerufen wird. Darüberhinaus ersetzt U2F nicht den klassische Loginansatz. Dieser ist weiterhin notwendig und auch Grundvoraussetzung für die Implementierung von U2F. Um U2F einsetzen zu können und Benutzern zu erlauben einen Dongle mit ihrem Benutzerkonto zu verknüpfen ist daher eine Benutzersession obligatorisch. Ferner werden sowohl im Frontend als auch im Backend entsprechende Bibliotheken benötigt, welche den FIDO-Standard implementieren. Yubico bietet hierfür ein JavaScript an, welches im Frontend eingebunden werden kann: https://demo.yubico.com/js/u2f-api.js.
Für den Einsatz im Backend bietet sich die npm-Abhängigkeit u2f an, welche den serverseitigen Part implementiert.
An (application) facet is how an application is implemented on various platforms. For example, the application PayPal may have an Android app, an iOS app, and a Web app. These are all facets of the PayPal application. (Quelle: Yubico)Ist der "registration request" erstellt, wird dieser der Session angehängt, um den "request" zu einem späteren Zeitpunkt validieren zu können (Zeilen 6-16).
{% gist aec55b34e94bdde175399d31b9494a49 u2f.registration.request.js %}
{% gist aec55b34e94bdde175399d31b9494a49 u2f.process-request.js %}
Der Browser spricht nun den Dongle an und aktiviert diesen. Um der Anfrage zuzustimmen muss der Benutzer aktiv einen Knopf auf dem Dongle drücken, um so seine Zustimmung zum Pairing des Dongles mit der Anfrage zu geben. Tut der Benutzer dies nicht, wird ein Fehler geworfen, welcher mit dem Error-Code 5 angibt, dass die Benutzerinteraktion zu lange gedauert hat und ein erneuter “registration request” angefordert werden muss.
Gibt der Benutzer jedoch seine Zustimmung, wird eine Antwort auf die gegebene “Challenge” erstellt, die anschließend wieder an den Server gesendet werden muss.
{% gist aec55b34e94bdde175399d31b9494a49 u2f.handle.post.js %}
Ähnlich wie bei der Registrierung eines Dongles (vgl. 1. Registration Request), muss vom Server eine Challenge angefordert werden, die auf den Daten des gespeicherten Dongles basiert. Hierfür wird auf Basis des gespeicherten keyHandles ein Sign-Request erstellt, welcher an den Client geschickt wird.
{% gist aec55b34e94bdde175399d31b9494a49 u2f.login.request.js %}
{% gist aec55b34e94bdde175399d31b9494a49 u2f.ui.login.request.js %}
Der vom Server gesendete authRequest wird der sign(<…>) Funktion übergeben und das Ergebnis zurück an den Server gesandt. Dieser muss nun prüfen, ob die erzeugte Antwort valide ist.
{% gist aec55b34e94bdde175399d31b9494a49 u2f.login.verification.js %}
u2f.register([req], [], cb);Dem Aufruf der Funktion register jedoch muss die AppId als erster Parameter übergeben werden. Der korrekt funktionierende Aufruf gestaltet sich daher wie folgt:
u2f.register(req.appId, [req], [], cb);
u2f.register
korrekt verwendet wird. Besondere Beachtung gilt dem zweiten Parameter, welcher als Array übergeben werden muss. Ferner ist die AppId korrekt zu wählen: Zum einen ist es zwingend erforderlich, dass der Server über SSL, also HTTPS verfügt und die AppId entsprechend gestaltet wird: https://localhost. Ein Slash am Ende der URL führt ebenfalls zu ungewollten Seiteneffekten und Fehlern.