web-dev-qa-db-de.com

Wie wird das Frontend nach der Serverauthentifizierung mit dem JSON-Web-Token versehen?

Bisher habe ich mich nur mit vom Server gerenderten Apps befasst, bei denen sich ein Benutzer über einen Benutzernamen/ein Kennwort oder einen OAuth-Anbieter (Facebook usw.) anmeldet und der Server lediglich ein Sitzungscookie setzt, während er auf die entsprechende Seite umleitet.

Jetzt versuche ich jedoch, eine App mit einem moderneren Ansatz zu erstellen, mit React auf dem Frontend und einem JSON-API-Backend. Anscheinend besteht die Standardauswahl darin, ein JSON-Web-Token für die Authentifizierung zu verwenden. Ich habe jedoch Probleme, herauszufinden, wie ich das JWT dem Client zur Verfügung stellen soll, damit es in einer Sitzung/im lokalen Speicher oder an einem anderen Ort gespeichert werden kann.

Beispiel zur besseren Veranschaulichung:

  1. Der Benutzer klickt auf den Link (/auth/facebook), um sich über Facebook anzumelden

  2. Der Benutzer wird umgeleitet und erhält das Facebook-Anmeldeformular und/oder den Berechtigungsdialog (falls erforderlich).

  3. Facebook leitet den Benutzer mit einem Autorisierungscode an /auth/facebook/callback zurück, der Server tauscht diesen gegen ein Zugriffstoken und einige Informationen über den Benutzer aus

  4. Der Server findet oder erstellt den Benutzer in der Datenbank unter Verwendung der Informationen und erstellt dann eine JWT, die eine relevante Teilmenge der Benutzerdaten (z. B. ID) enthält.

  5. ???

An dieser Stelle möchte ich nur, dass der Benutzer mit dem JWT im Schlepptau zur Hauptseite für die React-App (sagen wir /app) umgeleitet wird, damit das Frontend übernehmen kann. Aber ich kann mir keine (elegante) Möglichkeit vorstellen, dies zu tun, ohne dabei das JWT zu verlieren, außer es in die Abfragezeichenfolge für die Umleitung (/app?authtoken=...) einzufügen - aber das wird in der Adressleiste angezeigt, bis ich es entferne es manuell mit replaceState() oder was auch immer, und scheint mir ein bisschen komisch.

Wirklich, ich frage mich nur, wie das normalerweise gemacht wird, und ich bin mir fast sicher, dass ich hier etwas verpasse. Der Server ist Node (Koa mit Passport), wenn das hilft.

Bearbeiten: Um klar zu sein, ich frage, was der beste Weg ist, dem Client ein Token bereitzustellen (damit es gespeichert werden kann) nach einem OAuth-Redirect-Flow mit Passport.

11
Inkling

Ich bin vor kurzem über das gleiche Problem gestoßen und habe hier und anderswo keine Lösung gefunden und schrieb diesen Blogpost mit meinen tiefgehenden Gedanken.

TL; DR: Ich habe drei mögliche Ansätze gefunden, um die JWT nach OAuth-Logins/Redirects an den Client zu senden:

  1. Speichern Sie die JWT in einem Cookie und extrahieren Sie sie in einem späteren Schritt auf dem Front-End oder dem Server (z. B. extrahieren Sie sie mit JS auf dem Client oder senden Sie eine Anfrage an den Server. Der Server verwendet das Cookie, um die JWT abzurufen, und gibt die JWT zurück die JWT).
  2. Senden Sie die JWT als Teil der Abfragezeichenfolge zurück (die Sie in Ihrer Frage vorschlagen).
  3. Senden Sie eine vom Server gerenderte HTML-Seite mit einem <script>-Tag zurück, das Folgendes enthält:
    1. Speichert die eingebettete JWT automatisch in localStorage.
    2. Leitet den Client automatisch auf die gewünschte Seite um.

(Da das Anmelden bei JWTs im Wesentlichen gleichbedeutend ist mit "Speichern der JWT in localStorage", war meine Lieblingsoption # 3, aber möglicherweise gibt es Nachteile, die ich nicht berücksichtigt habe. Ich bin daran interessiert, was andere hier denken.)

Hoffentlich hilft das!

7
GT2000
  1. Client: Öffnet ein Popup-Fenster über $ auth.authenticate ('Anbietername').
  2. Client: Melden Sie sich bei diesem Anbieter an, und autorisieren Sie die Anwendung.
  3. Client: Nach erfolgreicher Autorisierung wird das Popup zu Ihrer App zurückgeleitet, z. http: // localhost: 3000 , mit dem Code für den Abfragezeichenfolgecode (Autorisierungscode).
  4. Client: Der Code-Parameter wird an das übergeordnete Fenster zurückgesendet, das das Popup-Fenster geöffnet hat.
  5. Client: Das übergeordnete Fenster schließt das Popup-Fenster und sendet eine POST -Anforderung an den Parameter/auth/provider withcode.
  6. Server: Autorisierungscode wird gegen Zugriffstoken ausgetauscht.
  7. Server: Benutzerinformationen werden mit dem Zugriffstoken aus Schritt 6 abgerufen.
  8. Server: Suchen Sie den Benutzer anhand seiner eindeutigen Provider-ID. Wenn bereits Benutzer vorhanden sind, greifen Sie den vorhandenen Benutzer an, oder erstellen Sie ein neues Benutzerkonto.
  9. Server: Erstellen Sie in beiden Fällen von Schritt 8 ein JSON-Web-Token, und senden Sie es an den Client zurück.
  10. Client: Analysieren Sie das Token und speichern Sie es nach dem Neuladen der Seite für die spätere Verwendung im lokalen Speicher.

    Ausloggen

  11. Client: Token aus dem lokalen Speicher entfernen
0
sabarinathan u

hier ist eine Login-Anfrage von der Serverseite. Es speichert das Token im Header:

router.post('/api/users/login', function (req, res) {
  var body = _.pick(req.body, 'username', 'password');
  var userInfo;

models.User.authenticate(body).then(function (user) {
      var token = user.generateToken('authentication');
      userInfo = user;

      return models.Token.create({
        token: token
      });
    }).then(function (tokenInstance) {
      res.header('Auth', tokenInstance.get('token')).json(userInfo.toPublicJSON());
    }).catch(function () {
      res.status(401).send();
    });
});

hier ist die Anmeldeanforderung auf der Antwortseite, wo ich das Token aus dem Header abhole und das Token im lokalen Speicher einstelle, sobald der Benutzername und das Kennwort die Authentifizierung durchlaufen haben:

handleNewData (creds) {
    const { authenticated } = this.state;
    const loginUser = {
        username: creds.username,
        password: creds.password
    }
    fetch('/api/users/login', {
        method: 'post',
        body: JSON.stringify(loginUser),
        headers: {
            'Authorization': 'Basic'+btoa('username:password'),
            'content-type': 'application/json',
            'accept': 'application/json'
        },
        credentials: 'include'
    }).then((response) => {
        if (response.statusText === "OK"){
            localStorage.setItem('token', response.headers.get('Auth'));
            browserHistory.Push('route');
            response.json();
        } else {
            alert ('Incorrect Login Credentials');
        }
    })
}
0
jared thomas