Json Web Token in Flow

Begrifflichkeiten

JWT: Ein signiertes und gegebenenfalls verschlüsseltes JsonWebToken

Client: Beispielsweise eine ReactApp, die mit einer API kommuniziert, oder einfach eine Webseite die per Javascript eine API anspricht.

Server: Hier werden die Tokens erstellt und ausgeliefert - eine API, die die Tokens verwendet muss nicht auf diesem Server liegen.

API: Ein Dienst auf einem Server, mit dem sich ein Client mittels eines Tokens authentifiziert.

Flow: Verwendetes PHP Framwork, das unter vielen anderen Dingen ein robustes und erweiterbares Authentifzierungsframework enthält.


Kurzbeschreibung Json Web Token

Meist für APIs genutzt, kann ein Client (oder der Benutzer eines Clients) sich an einem Authentifizierungsendpunkt ein Token abholen, das seine Informationen (Rechte, Rollen, etc.) beinhaltet. Dieses Token ist signiert, bei sensiblem Inhalt verschlüsselt und für einen begrenzten Zeitraum (oft eine Stunde) gültig. Eine API kann nun einen Authentifizierungsmechanismus bereitstellen, bei dem nur das Token mitgeschickt werden muss. Auf API Seite sind alle nötigen Informationen und Sicherheitsmaßnahmen im Token enthalten. So muss die API kein Session Handling oder Ähnliches implementieren.


Implementierung in Flow

Flow benötigt für eine eigene Authentifizierungsmethode zwei Dinge: einen Provider, der die Authentifizierung durchführt, und ein Token das eine Schnittstelle zum Prüfen des JWT bereitstellt.

Konfiguration

Die beiden Implementierungen müssen dann noch dem Authentication Framework mitgeteilt werden, das funktioniert über die Settings.yaml, in der ein neuer Provider mit zugehörigem Token regestriert wird.
Der Schlüssel direkt in providers kann dabei frei gewählt werden und wird beispielsweise genutzt um bestimmte Bereiche (Controller o.Ä.) mit Json Web Tokens zu schützen.
provider und token müssen hier ein FQDN sein, also den kompletten Namespace enthalten.

Weiterführende Links

Unter https://jwt.io/ gibt neben einer guten Einführung zu Json Web Tokens auch eine Liste von Implementierungen für unterschiedliche Sprachen inklusive Checkliste, was geht und wie sicher.
Die volle Breitseite mit guter Dokumentation bietet https://github.com/Spomky-Labs/jose.
Hier die Dokumentation von Flow zum Thema eigene Authentifizierung: #implementing-your-own-authentication-mechanism.
Der ganze Artikel ist wirklich super geschrieben, wenn man sich mit dem Security Framwork von Flow auseinandersetzt!

Der grobe Aufbau des implementierten Providers so:

<?php
class JsonWebTokenProvider extends AbstractProvider {
    /**
     * @var \TYPO3\Flow\Http\RequestHandler
     * @Flow\Inject
     */
    protected $requestHandler;

    /**
     * @return array
     */
    public function getTokenClassNames() {

        return [JsonWebToken::class];

    }

    /**
     * @param TokenInterface $authenticationToken
     * @throws UnsupportedAuthenticationTokenException
     * @return void
     */
    public function authenticate(TokenInterface $authenticationToken) {
        if (!($authenticationToken instanceof JsonWebToken)) {
            throw new UnsupportedAuthenticationTokenException('This provider cannot authenticate the given token.', 1486136719);
        }
        /**
          * Prüft das eingehende Token und setzt den Status entsprechend.
          * Hier wird die checkJwt() des Tokens genutzt.
          * Der neue Status kann dann einer der folgenden sein: AUTHENTICATION_SUCCESSFUL, WRONG_CREDENTIALS
          * oder NO_CREDENTIALS_GIVEN.
          */
    }
}

Der grobe Aufbau des implementierten Tokens sieht so aus:

<?php
class JsonWebToken extends AbstractToken implements SessionlessTokenInterface {
    /**
     * Für leichtes Anpassen laden wir JWT spezifische statische Daten aus den Settings, wie zum Beispiel den Key zum Signieren der JWTs.
     * @Flow\InjectConfiguration(path="authentication.jwtSecret")
     * @var string
     */
    protected $secret;

    /**
     * @param ActionRequest $actionRequest
     * @return void
     */
    public function updateCredentials(ActionRequest $actionRequest) {
        /**
          * Entnimmt dem Request das JWT (beispielsweise POST, oder Cookie und setzt entsprechend den Status des Tokens auf NO_CREDENTIALS_GIVEN oder AUTHENTICATION_NEEDED.
          */
    }

    /**
     * @param string $encodedJwt
     * @return bool
     */
    public function checkJwt($encodedJwt = '') {
        /**
          * Nimmt das JWT entgegen und prüft den Inhalt mit einer entsprechenden Json Web Token Bibliothek. Weiter unten dazu ein paar Links.
          */
    }
}

Settings.yaml

TYPO3: 
  Flow:
    security:
      authentication:
        providers:
          'JsonWebTokenProvider':
            provider: 'Namespace\JsonWebTokenProvider'
            token: 'Namespace\JsonWebToken'

Kategorien

Devblog

Tags

PHP

Hat Dir der Artikel gefallen?