
Teilen Sie:
Freundlicher Tech-Pädagoge, Familienvater, Verfechter der Vielfalt, streitet wahrscheinlich ein bisschen zu viel. Ehemals Backend-Ingenieur. Sprich mit mir über JavaScript (Frontend oder Backend), das erstaunliche Vue.js, DevOps, DevSecOps, alles was mit JamStack zu tun hat. Autorin auf DEV.to
Registrieren, um mit Typeform zu chatten
Lesedauer: 44 Minuten
In diesem Artikel erfahren Sie, wie Sie Folgendes einrichten können Typeform einrichtet und Daten von einem Webhook in der Node.js Framework Express.js. Sie verwenden Passport.js um einen Benutzer zu authentifizieren, verwenden Sie Node.js Server SDK von Nexmo um einen Benutzer zu registrieren, und ein JWT zu generieren, das mit Nexmo's JavaScript Client SDK.
Sie werden von einer vorgefertigten Chat-Anwendung ausgehen, die mit Nexmos JavaScript-Client-SDK und Bootstrap.
Dieses Lernprogramm beginnt mit dem master Zweig und endet mit dem tutorial-finish Zweig. Sie können zum Ende springen, indem Sie auschecken tutorial-finish und der README folgen, um schnell loslegen zu können.
Voraussetzungen
Knotenpunkt & NPM
Um dieser Anleitung zu folgen, müssen Sie Node.js und NPM installiert haben. Diese Anleitung verwendet Node.js 13.1 und NPM 6.12. Stellen Sie sicher, dass Sie mindestens Stable- oder Long-Term-Support-Versionen von Node.js installiert haben.
Wenn Sie weder Node.js noch NPM haben oder eine ältere Version verwenden, gehen Sie zu nodejs.org und installieren Sie die richtige Version falls Sie diese noch nicht haben.
Vonage API-Konto
Um dieses Tutorial durchzuführen, benötigen Sie ein Vonage API-Konto. Wenn Sie noch keines haben, können Sie sich noch heute anmelden und mit einem kostenlosen Guthaben beginnen. Sobald Sie ein Konto haben, finden Sie Ihren API-Schlüssel und Ihr API-Geheimnis oben auf dem Vonage-API-Dashboard.
Nexmo CLI
Um Ihre Anwendung einzurichten, müssen Sie die Nexmo CLI. Installieren Sie es mit NPM im Terminal.
Konfigurieren Sie nun die CLI mit Ihrem API-Schlüssel und Geheimnis, die Sie auf Ihrem Nexmo-Konto Dashboard.
MongoDB
Wir werden die Informationen in MongoDB speichern. Wenn Sie MongoDB noch nicht installiert haben, folgen Sie der korrekten MongoDB Community Edition Installationsanleitung für Ihr System.
Ngrok
Da Sie Informationen von einer dritten Partei erhalten, müssen Sie die Anwendung, die auf Ihrem lokalen Rechner läuft, auf sichere Weise offenlegen. Ngrok ist ein sicherer Weg, um mit einem einzigen Befehl eine sofortige, sichere URL zu erhalten, mit der Sie auf Ihren lokalen Rechner zugreifen können, sogar durch eine NAT oder Firewall.
Melden Sie sich an und konfigurieren Sie ngrok indem Sie den Anweisungen auf der Website folgen.
Schriftform
Sie werden Typeform verwenden, um Eingaben von Nutzern zu erfassen, also Melden Sie sich jetzt für ein kostenloses Typeform-Konto an.
E-Mail-SMTP-Anbieter
Sie werden E-Mails verschicken. Sie benötigen den Hostnamen, den Port, ein Login und ein Passwort für einen SMTP-Anbieter.
Sie können mit Google Mail zum Senden von E-Mails aus einer Anwendung.
Git (optional)
Sie können git verwenden, um die Demoanwendung von GitHub zu klonen.
Wenn Sie mit git nicht vertraut sind, enthält diese Anleitung auch Anweisungen zum Herunterladen des Projekts als ZIP-Datei.
Folgen Sie dieser Anleitung zur Installation von Git
Anfangen
Die Anwendung, mit der Sie beginnen, ist eine Chat-Anwendung, die mit Bootstrap und dem Nexmo JavaScript-Klienten-SDK. Sie ist durch die Bearbeitung statischer Dateien konfigurierbar, wird aber mit Express.jsgestartet, einem leichtgewichtigen Node.js-basierten http-Server.
Grundlegende Installation
Klonen Sie die Demo-Anwendung direkt von GitHub.
Wenn Sie mit den Git-Befehlen nicht vertraut sind, können Sie auch die Demo-Anwendung als Zip-Datei herunterladen herunterladen und lokal entpacken.
Wechseln Sie nach dem Klonen oder Entpacken in das neue Verzeichnis der Demoanwendung.
Installieren Sie die npm-Abhängigkeiten.
Neben Node.js wird ein Paket namens nodemoninstalliert, das Ihren Server automatisch neu lädt, wenn Sie Dateien bearbeiten.
Starten Sie die Anwendung auf die übliche Weise.
Starten Sie die Anwendung, aber stattdessen mit nodemon.
Tipp: Wenn Sie die Anwendung mit
nodemonausführen, müssen Sie das nicht tun, wenn ich Ihnen vorschlage, die Anwendung neu zu starten, danodemones für Sie tut. Wenn Sie sich jedoch erneut bei der Anwendung authentifizieren müssen, müssen Sie das trotzdem tun, da die Sitzungsinformationen im Speicher gespeichert werden und nicht für die Verwendung eines anderen Speichers konfiguriert sind.
Unabhängig davon, wie Sie die Anwendung ausführen, können Sie sie in Ihrem bevorzugten Browser ausprobieren, der die Anwendung lokal finden sollte: http://0.0.0.0:3000/.

Da die Anwendung unkonfiguriert ist, sehen Sie eine sehr einfache, leere Chat-Anwendung, an die Sie keine Nachrichten senden können. In der realen Welt mit Fehlerbehandlung könnten Sie dem Benutzer einen Verbindungsfehler anzeigen.
Aber wenn Sie jetzt die Browser-Konsole überprüfen, sehen Sie nur einen Nexmo-API-Fehler für ein fehlendes Token. Das bedeutet, dass die Anwendung versucht hat, eine Verbindung herzustellen, aber kein Benutzer-Token für den Zugriff auf die API bereitgestellt hat.
Prüfen Sie, ob ngrok richtig konfiguriert ist, indem Sie ngrok in einer separaten Registerkarte oder einem Fenster ausführen, um npm.

Sie müssen diesen ngrok Befehl und npm zur gleichen Zeit ausführen. Das bedeutet, dass Sie zwei Terminalfenster oder Registerkarten zur Verfügung haben müssen, die sich beide im Anwendungsverzeichnis befinden.
Tipp: Wenn Sie später bestimmte Aufgaben wiederholen müssen, wie z.B. das Übertragen von Daten aus Typeform an den Webhook, können Sie die ngrok's Webinterface unter http://127.0.0.1:4040 öffnen, während es läuft und wiederholen. eine Anfrage wiederholen.
Solange Sie nicht für ngrok bezahlen, wird Ihre URL jedes Mal anders sein, wenn Sie es starten. Denken Sie daran, wenn Sie später Ihren Typeform-Webhook konfigurieren. Wenn Sie ngrok beenden, müssen Sie Typeform mit der neuen URL neu konfigurieren, wenn Sie es wieder starten.
Tipp: Wenn Sie sich mit einem Tool wie Postman oder mit dem Schreiben von manuellen cURL-Anfragen vertraut sind, können Sie, sobald Sie Ihre erste Webhook-Anfrage von Typeform erhalten haben, eine Anfrage erstellen, um diese später wiederholen zu können.
Chatten
In den Voraussetzungen haben Sie Ihre CLI mit Ihrem Nexmo-API-Schlüssel und Geheimnis eingerichtet. Jetzt können Sie CLI-Befehle ausführen, um eine Nexmo-Anwendung, einen Benutzer und eine Konversation zu erstellen, den Benutzer mit der Konversation zu verbinden und ein JWT zu erzeugen, damit Ihr Benutzer chatten kann.
Nexmo Konfiguration
Sie werden einige der zurückgegebenen IDs verwenden müssen, wenn Sie einige der Befehle ausgeführt haben. Machen Sie sich Notizen, indem Sie Ihre Anwendungs-, Gesprächs- und Benutzer-IDs kopieren und einfügen.
Nexmo-Anwendung erstellen
Dieser Befehl erstellt eine neue Nexmo-Anwendung mit RTC-Funktionen (Echtzeitkommunikation). Sie werden die Ereignisse in Ihrer Anwendung nicht aufzeichnen, daher können Sie eine Beispiel-Webadresse für die Ereignis-URL angeben. Der private Schlüssel wird in einem Dateipfad Ihrer Wahl ausgegeben.
Tipp: Ihre Anwendung wird auch in einer Konfigurationsdatei (
.nexmo-app) in dem Verzeichnis ausgegeben, in dem Sie diesen Befehl ausgeführt haben. Das bedeutet, dass einige weitere Befehle aus diesem Verzeichnis für diese Anwendung relevant sind, z. B. das Erstellen von Benutzern und Konversationen.
Nexmo-Konversation erstellen
Wenn Sie eine Anwendung erstellt haben, können Sie eine Konversation erstellen. Der Konversation treten Ihre Benutzer bei, um Nachrichten hin und her zu senden.
Erstellen Sie Ihren Benutzer
Erstellen Sie nun einen Benutzer. Dies wird der Benutzer sein, mit dem Sie sich authentifizieren. Im Moment brauchen Sie nur einen Benutzernamen und einen Anzeigenamen.
Benutzer zur Konversation hinzufügen
Führen Sie diesen Befehl mit Ihrer Konversations-ID und Benutzer-ID aus, um der Konversation mit Ihrem Benutzer beizutreten.
Benutzer-Token generieren
Verwenden Sie diesen Befehl, um ein Benutzer-Token in Form eines JWTs zu generieren, das von der API, aber auch von Nexmos JavaScript Client SDK verwendet werden kann. Es wird ein JWT zurückgegeben, das Sie verwenden können und das in 24 Stunden abläuft, oder 86400 Sekunden.
Konfigurieren Sie die Anwendung
Um Ihre Anwendung zu konfigurieren, bearbeiten Sie die views/layout.hbs Datei und suchen Sie die JavaScript-Konfiguration um Zeile 61.
<script>
var userName = '';
var displayName = '';
var conversationId = '';
var clientToken = '';
</script>Konfigurieren Sie die Anwendung zunächst so, aber am Ende des Leitfadens werden Sie in der Lage sein, sich mit einem magischen Link zu authentifizieren, und die clientseitige Anwendung wird Ihr Benutzer-Token aus Ihrer autorisierten Sitzung abrufen.
Bearbeiten Sie die Konfiguration mit den Werten, die Sie mit den obigen Befehlen erzeugt haben.
<script>
var userName = 'luke.oliff@vonage.com';
var displayName = 'Luke Oliff';
var conversationId = 'CON-123...y6346';
var clientToken = 'eyJhbG9.eyJzdWIiO.Sfl5c';
</script>Jetzt können Sie die Anwendung erneut starten und mit sich selbst chatten... denn niemand sonst kann sich anmelden.

Erstellen eines Typformulars
Sie können so viele Daten aus Ihrem Typeform erfassen, wie Sie möchten. Für diesen Leitfaden sollten Sie jedoch sicherstellen, dass Sie mindestens ein E-Mail-Feld im Formular haben.
Sobald Sie Ihr Typeform erstellt haben, klicken Sie auf die Seite Verbinden Registerkarte auf Ihrer Typeform-Bearbeitungsseite und klicken Sie auf Webhooks.
Klicken Sie auf Einen Webhook hinzufügen und geben Sie die URL als https://<your_url>.ngrok.io/webhooks/magiclink. Klicken Sie dann auf Webhook speichern.

Nach der Erstellung können Sie zurückgehen und ein Geheimnis hinzufügen, um zu überprüfen, ob die Anfragen, die Ihren Webhook erreichen, tatsächlich von Typeform kommen.
Wenn Sie Ihr Typeform jetzt ausfüllen und es abschicken, während Ihre Anwendung läuft, erhält das Typeform eine 404 Not Found Fehler und versucht es erneut. Wenn eine Webhook-Anforderung aus irgendeinem Grund fehlschlägt, wiederholt Typeform die Anforderung an Ihren Endpunkt dreimal unter Verwendung eines Back-off-Mechanismus nach 5, 10 und 20 Minuten.
Umgebungsvariablen
Von nun an werden Sie Ihre Anwendung mit Anmeldeinformationen konfigurieren, die sich nicht nur von Umgebung zu Umgebung unterscheiden können, sondern die Sie auch nicht zusammen mit Ihrem Quellcode übertragen möchten.
dotenv war bereits eine Abhängigkeit des Ausgangsprojekts, also schauen Sie in der .env Datei, die bereits den Standardport für die Anwendung enthält. Sie werden bald auf diese Datei zurückkommen, um weitere Umgebungsvariablen hinzuzufügen.
Einen Webhook hinzufügen
Um nun Ihren potenziellen Fehler zu beheben 404 Not Found Fehler zu beheben, fügen Sie den Webhook hinzu, indem Sie in der Anwendung eine neue Datei namens routes/webhook.js. Fügen Sie in der neuen Datei den folgenden Code ein.
var express = require('express');
var router = express.Router();
/* POST webhook generates a magic link email to the provided email address */
router.post('/magiclink', (req, res, next) => {
console.log(req.body);
// always return a response...
res.sendStatus(200);
});
module.exports = router;
Bearbeiten Sie app.js und fügen Sie den Webhook-Router hinzu.
// ...
var indexRouter = require('./routes/index');
var webhookRouter = require('./routes/webhook');
// ...
app.use('/', indexRouter);
app.use('/webhooks', webhookRouter);
// ...Wenn npm und ngrok laufen, sollten Sie nun in der Lage sein, Ihr Typeform abzuschließen und eine Webhook-Anfrage zu erhalten. Die Payload wird Daten enthalten, die wie folgt aussehen und in dem Fenster ausgegeben werden, in dem Sie die Anwendung mit npm gestartet haben.
{
...
"form_response": {
...
"answers": [
{
"type": "email",
"email": "email@example.com",
"field": {
"type": "email",
}
}
]
}
} Erfassen Sie die Antwort
Bevor Sie den Webhook bearbeiten, konfigurieren Sie einige Variablen für das Typeform und die Frage in Ihrer Umgebungsdatei .env. Für FORM_FIELD_REFmüssen Sie Ihre Typeform-Frage bearbeiten und die Frage-Referenz in Ihren Frageeinstellungen. FORM_URL ist die öffentliche URL zum Ausfüllen des Formulars.
Gehen Sie nun zurück zu Ihrer Webhook-Route unter routes/webhook.js und bearbeiten Sie sie so, dass sie Code enthält, der die E-Mail-Adresse extrahiert.
//...
require('dotenv').config();
/* POST webhook generates a magic link email to the provided email address */
router.post('/magiclink', (req, res, next) => {
// find answers from the typeform response
let { answers } = req.body.form_response;
const answer = answers
.find(answer => process.env.FORM_FIELD_TYPE === answer.type && answer.field.ref === process.env.FORM_FIELD_REF);
// it'll probably be an email
const email = answer[process.env.FORM_FIELD_TYPE];
console.log(email);
// always return a response...
res.sendStatus(200);
});
Dieser Code findet eine Antwort vom Typ email Typs mit dem passenden Frage-Referenz (nur für den Fall, dass Sie mehr als eine E-Mail-Adresse in Ihrem Formular erfassen!) und gibt schließlich den Wert der Antwort zurück. Der Typ und die Referenz wurden in der Datei .env Datei festgelegt.
Das Ergebnis ist die Zeichenkette, die in der Typeform-Frage eingegeben wird.
Benutzer speichern
In diesem Tutorial wird weiterhin davon ausgegangen, dass Sie nur ein einziges E-Mail-Feld von Typeform erfassen und keine weiteren Benutzerinformationen. Es werden andere abgeleitete Informationen über den Benutzer gespeichert, wenn er erstellt wird.
Sie verwenden Mongoose für die Speicherung Ihrer Benutzer in der Datenbank. Mongoose bietet eine unkomplizierte, schema-basierte Lösung zur Modellierung Ihrer Anwendungsdaten. Mongoose enthält integrierte Typenzuordnung, Validierung, Abfrageerstellung, Hooks für die Geschäftslogik und vieles mehr - und das sofort nach dem Auspacken.
Mongoose installieren
Um die Erstellung von Benutzern und deren Details zu erfassen, installieren Sie mongoose in Ihrem Projekt.
MongoDB-Verbindung konfigurieren
Konfigurieren Sie das Projekt so, dass Mongoose in der Lage ist, eine Verbindung zur MongoDB-Datenbank herzustellen. Diese Anleitung verwendet die Standard MacOS Werte, die von dem abweichen können, was Sie benötigen, je nachdem, welche Entwicklungsumgebung Sie verwenden.
Bearbeiten Sie .env und fügen Sie die folgende Konfiguration hinzu.
Sie können entscheiden your-database-name Hier können Sie sich entscheiden, denn es wird erstellt, wenn es noch nicht vorhanden ist.
Verbindung zu MongoDB
Konfigurieren Sie nun Ihre Anwendung so, dass sie sich mit Mongoose verbindet, wenn sie ausgeführt wird, indem Sie die Datei bin/www Datei bearbeiten und diesen Code am Ende einfügen.
/**
* Database config
*/
const mongoose = require('mongoose');
// Set mongoose promises to global
mongoose.Promise = global.Promise
// Set up default mongoose connection
mongoose.connect(process.env.MONGO_URL, { useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false });
// Get the default connection
const db = mongoose.connection;
// Bind connection to error event (to get notification of connection errors)
db.on('error', onError); Benutzerschema und Modell
Alles in Mongoose beginnt mit einem Schema. Jedes Schema wird einer MongoDB-Sammlung zugeordnet und definiert die Form der Dokumente innerhalb dieser Sammlung. Während MongoDB ohne Schema auskommt, verwendet Mongoose Schemas, um das Standardobjekt vor der Änderung zu formalisieren.
Erstellen Sie eine neue Datei für das Schema unter schemas/user.js und fügen Sie den folgenden Code hinzu.
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const UserSchema = new Schema({
name: {
type: String,
required: true
},
display_name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
user_id: {
type: String
},
member_id: {
type: String
}
});
module.exports = UserSchema;Ein Modell dient der Erstellung von Dokumenten, mit denen Sie Elemente in einer MongoDB-Sammlung erstellen, bearbeiten, aktualisieren und löschen können. Erstellen Sie eine neue Datei für das Modell unter models/user.js und fügen Sie den folgenden Code ein.
const mongoose = require('mongoose');
const UserSchema = require('../schemas/user');
const User = mongoose.model('User', UserSchema);
module.exports = User;Beachten Sie, dass das Modell das Schema für die Rückgabe eines User Dokument.
Suchen und Speichern von Benutzern
In diesem Fall verwenden Sie die E-Mail-Adresse als String-Identifikator oder Benutzernamen Ihres Benutzers. Die E-Mail-Adresse wird schließlich auch zu ihrem Anzeigenamen. Wenn Sie möchten, können Sie diese beiden Dinge einzeln in Ihrem Typeform erfassen.
Bearbeiten Sie routes/webhook.js und fügen Sie den folgenden Code hinzu, um Benutzer anhand ihres Benutzernamens zu finden und sie anzulegen, wenn sie noch nicht existieren.
//...
var User = require('../models/user');
/* POST webhook generates a magic link email to the provided email address */
router.post('/magiclink', (req, res, next) => {
// ...
User.findOne({ name: email }, (err, user) => {
// error handling here
// if our user is new, save it and output it
if (null === user) {
user = new User({
name: email,
email: email,
display_name: email
});
user.save((err) => {
// error handling here
console.log(user);
res.sendStatus(200);
});
// otherwise, just output it
} else {
console.log(user);
res.sendStatus(200);
}
});
});
Dieser Code versucht, einen Benutzer anhand seiner E-Mail-Adresse zu finden und erstellt einen Benutzer, wenn er noch nicht existiert. Dies unterstützt nicht die Aktualisierung eines bestehenden Benutzers. Wenn sie bereits existierten, könnten Sie einen Fehler machen. Später werden wir einen magischen Link zur Anmeldung generieren, anstatt einen Fehler zu melden.
Einen magischen Link generieren
Ihr Webhook wird Ihrem Benutzer einen magischen Link per E-Mail schicken, mit dem er sich beim Dienst authentifizieren kann.
Installieren Sie jsonwebtoken mit npm.
Bearbeiten Sie .env um einen geheimen Schlüssel zu erstellen, der für die Tokengenerierung verwendet werden kann.
Bearbeiten Sie nun also routes/webhook.js um den magischen Link zu erzeugen und ihn auf dem Server auszugeben.
//...
var jwt = require('jsonwebtoken');
var createMagicLink = (req, payload) => {
var token = jwt.sign(payload, process.env.SECRET);
return `${req.protocol}://${req.get('host')}/auth?token=${token}`;
}
/* POST webhook generates a magic link email to the provided email address */
router.post('/magiclink', (req, res, next) => {
// ...
// ...
if (null === user) {
// ...
user.save((err) => {
// ...
console.log(createMagicLink(req, user.toObject()));
res.sendStatus(200);
});
// otherwise, just output it
} else {
console.log(createMagicLink(req, user.toObject());
res.sendStatus(200);
}
// ...
});
Wir fügen einen JWT zu einer magischen Link-URL als Methode zur Identifizierung des Benutzers hinzu, wenn dieser versucht, auf die Website zuzugreifen.
Es ist wichtig zu wissen, dass ein JWT den Besitz der Daten garantiert, nicht die Verschlüsselung. Es handelt sich um eine URL-sichere Methode zur Darstellung von Ansprüchen, indem sie als JSON-Objekte kodiert werden, die digital signiert oder verschlüsselt werden können. Das digitale Signieren eines JWT ermöglicht die Validierung gegen Änderungen. Die Verschlüsselung hingegen sorgt dafür, dass der Inhalt des JWT nur von bestimmten Parteien gelesen werden kann.
In diesem Fall verwendet der Leitfaden keine RSA- oder andere asymmetrische Verschlüsselung, sondern signiert die Daten stattdessen mit der standardmäßigen synchronen HMAC SHA256-Signierung der JWT-Bibliothek.
Die Verwendung eines JWT auf diese Weise verifiziert, dass der magische Link von Ihrer Anwendung stammt, von Ihrem SECRET und kann nicht geändert werden.
Wenn Sie jetzt Daten an den Webhook von Typeform übermitteln, sollte die Ausgabe ein Link zur Anwendung sein, der wie eine viel längere Version dieser Seite aussieht:
https://<Ihre_Url>.ngrok.io/webhooks/auth?token=eyJhbCJ9.eyEflLxN.N9eq6b5o
Ein Klick auf den Link führt zu einem 404-Fehler. Das müssen wir beheben.

Authentifizierung mit Passport.js
Passport.js beschreibt sich selbst als unaufdringliche Authentifizierung für Node.js. Es ist unglaublich flexibel und modular und kann unauffällig in eine Anwendung wie diese integriert werden.
Passport.js installieren
Installieren Sie passport, die passport-jwt Strategie und express-session damit sie für die Authentifizierung und die Aufrechterhaltung einer Sitzung verwendet werden kann.
Erstellen eines Authentifizierungsendpunkts
Erstellen Sie eine neue Datei namens routes/auth.js mit diesem Quellcode.
var express = require('express');
var router = express.Router();
/* GET authenticate user with magic link and direct to home */
router.get('/', (req, res, next) => {
res.redirect(req.protocol + '://' + req.get('host') + '/');
});
module.exports = router;
Dieser Router leitet Sie auf die Homepage weiter. Sie erreichen diesen Router jedoch nur, wenn Sie beim Anfordern der Seite durch den JWT autorisiert sind.
Bearbeiten Sie app.js und fügen Sie diesen Code hinzu, um die Pass-Authentifizierung zu einer neuen Auth-Route hinzuzufügen.
// ...
var indexRouter = require('./routes/index');
var webhookRouter = require('./routes/webhook');
var authRouter = require('./routes/auth');
// ...
var User = require('./models/user');
var session = require('express-session');
var passport = require('passport');
var jwtStrategy = require('passport-jwt').Strategy;
var jwtExtractor = require('passport-jwt').ExtractJwt;
app.use(session({
secret: process.env.SECRET,
resave: true,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());
passport.serializeUser((user, done) => {
done(null, user._id);
});
passport.deserializeUser((id, done) => {
User.findById(id, (err, user) => {
done(err, user);
});
});
passport.use(new jwtStrategy({
jwtFromRequest: jwtExtractor.fromUrlQueryParameter('token'),
secretOrKey: process.env.SECRET
}, (payload, done) => {
return done(null, payload);
}))
app.use('/', indexRouter);
app.use('/webhooks', webhookRouter);
app.use('/auth', passport.authenticate('jwt', { session: true }), authRouter);
// ...
Dieser Code authentifiziert jede Anfrage an den /auth Endpunkt mit Hilfe des JWT-Extraktors von passport-jwt Strategie. Er wird versuchen den token aus einem Query-String-Parameter zu validieren.
Nach der Authentifizierung erstellt die Anwendung eine Sitzung, und die Benutzerdaten werden verfügbar als req.user.
Um dies zu testen, bearbeiten Sie routes/index.js und fügen Sie diesen Code vor der res.render() Zeile ein.
console.log(req.user);Starten Sie nun die Anwendung neu und erzeugen Sie einen magischen Link mit Ihrer Typeform-Anfrage. Wenn Sie auf den Link klicken, werden Sie nach der Authentifizierung zurück zum Chat weitergeleitet. Aber in Ihrer Konsole werden Sie einige Benutzerdaten ausgeben, die wie folgt aussehen:

Stellen Sie sicher, dass niemand auf den Chat zugreifen kann, wenn er nicht authentifiziert ist, indem Sie die Datei routes/index.js so bearbeiten, dass sie genau so aussieht.
var express = require('express');
var router = express.Router();
require('dotenv').config();
var isAuthenticated = (req, res, next) => {
if(req.isAuthenticated()){
next();
} else{
res.redirect(process.env.FORM_URL);
}
}
/* GET home */
router.get('/', isAuthenticated, (req, res, next) => {
res.render('index', { title: 'Nexmo Typeform Chat', user: req.user.display_name });
});
module.exports = router;
Entfernen der console.log-Ausgabe, die Sie gerade oben hinzugefügt haben; der Chat wird die aktuellen Benutzerdaten nicht mehr auf der Konsole protokollieren. Stattdessen wird der Anzeigename in den Bereich der zu rendernden Vorlagen aufgenommen. Diese Änderung wird auch auf das Typeform umleiten, wenn sie nicht angemeldet sind.
Bearbeiten Sie views/layout.hbs und geben Sie den Anzeigenamen aus. Suchen Sie username und ersetzen Sie ihn durch {{user}}Der umgebende Code sollte am Ende wie folgt aussehen.
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" href="#">
<span data-feather="home"></span>
{{user}}
</a>
</li>
</ul>Wenn sie eingeloggt sind, können wir auch die Mitglieder des Chats (aus der Datenbank) auf der Seite anzeigen. Bearbeiten Sie routes/index.js und schließe die res.render in die User.find ein, die alle registrierten Benutzer anzeigt.
// ...
var User = require('../models/user');
// ...
/* GET home */
router.get('/', isAuthenticated, (req, res, next) => {
User.find((err, users) => {
res.render('index', { title: 'Nexmo Typeform Chat', members: users, user: req.user.display_name });
})
});
Bearbeiten Sie views/layout.hbs erneut und finden Sie diesen gesamten Block:
{{!-- {{#each members}} --}}
<li class="nav-item">
<a class="nav-link text-muted" href="#">
<span data-feather="file-text"></span>
other member
</a>
</li>
{{!-- {{/each}} --}}Ersetzen Sie ihn durch diesen Funktionscode.
{{#each members}}
<li class="nav-item">
<a class="nav-link text-muted" href="#">
<span data-feather="file-text"></span>
{{this.display_name}}
</a>
</li>
{{/each}}Starten Sie die Anwendung neu und rufen Sie sie erneut über Ihren magischen Link auf. Jetzt sollten Sie einige Benutzerinformationen auf der Seite sehen.

Sie greifen immer noch auf den Chat auf der Website zu, indem Sie die hartcodierten Testdaten verwenden. Es ist an der Zeit, Ihre Nutzer bei Nexmo zu registrieren und sie auch auf die Konversation zugreifen zu lassen.
Registrierte Benutzer zum Chatten auf Nexmo bringen
Derzeit melden sich Benutzer an, nutzen den Chat aber nur über Ihre fest programmierten Benutzerdaten.
Nexmo-Knoten installieren und konfigurieren
An diesem Punkt werden Sie zum ersten Mal mit dem Nexmo-Dienst innerhalb Ihrer Node-Anwendung interagieren.
Installieren Sie nexmo jetzt mit diesem Befehl.
Konfigurieren Sie einige Variablen für Nexmo in Ihrer Umgebungsdatei .env. Sie benötigen denselben API-Schlüssel und dasselbe Geheimnis, das Sie bei der Konfiguration nexmo-cli zu Beginn verwendet haben. Außerdem benötigen Sie die Anwendungs-ID und den Pfad des privaten Schlüssels, die Sie bei der Ausführung von nexmo app:createsowie die Konversations-ID, die Sie beim Aufruf von nexmo conversation:create.
Erstellen Sie eine Dienstprogrammdatei unter util/nexmo.js die die Konfiguration der nexmo Bibliothek konfiguriert.
const Nexmo = require('nexmo');
require('dotenv').config();
let options = {};
module.exports = new Nexmo({
apiKey: process.env.NEXMO_API_KEY,
apiSecret: process.env.NEXMO_API_SECRET,
applicationId: process.env.NEXMO_APP_ID,
privateKey: process.env.NEXMO_PRIVATE_KEY_PATH
}, options); Nexmo-Benutzer anlegen
Als Erstes müssen Sie einen Nexmo-Benutzer parallel zu Ihrem lokalen Benutzer anlegen, wenn dieser sich anmeldet.
Bearbeiten Sie routes/webhook.js und ersetzen Sie die Datei vollständig durch diesen Code:
var express = require('express');
var router = express.Router();
var jwt = require('jsonwebtoken');
require('dotenv').config();
var User = require('../models/user');
var nexmo = require('../util/nexmo');
var createMagicLink = (req, payload) => {
var token = jwt.sign(payload, process.env.SECRET);
return `${req.protocol}://${req.get('host')}/auth?token=${token}`;
}
/* POST webhook generates a magic link email to the provided email address */
router.post('/magiclink', (req, res, next) => {
// find answers from the typeform response
let { answers } = req.body.form_response;
const answer = answers
.find(answer => process.env.FORM_FIELD_TYPE === answer.type && answer.field.ref === process.env.FORM_FIELD_REF);
// it'll probably be an email
const email = answer[process.env.FORM_FIELD_TYPE];
User.findOne({ name: email }, (err, user) => {
// error handling here
// if we can't find an existing user, prepare a new user document
if (null === user) {
user = new User({
name: email,
email: email,
display_name: email
});
}
if (null === user.user_id) {
nexmo.users.create(user.toObject(), (err, nexmoUser) => {
// error handling here
user.user_id = nexmoUser.id;
nexmo.conversations.members.create(process.env.NEXMO_CONVERSATION_ID, {
action: 'join',
user_id: nexmoUser.id,
channel: { type: 'app' }
}, (err, member) => {
// error handling here
user.member_id = member.id;
user.save((err) => {
// error handling here
console.log(createMagicLink(req, user.toObject()));
res.sendStatus(200);
});
});
});
} else {
console.log(createMagicLink(req, user.toObject()));
res.sendStatus(200);
}
});
});
module.exports = router;
Dieser neue Webhook-Code wird nach einem Datenbankbenutzer suchen und einen erstellen, wenn er neu ist, so wie es vorher der Fall war. Aber jetzt wird ein Nexmo-Benutzer erstellt und der Benutzer mit der Konversation verbunden, wobei sein Datenbankeintrag mit der Nexmo-Benutzer-ID und einer Mitglieds-ID aktualisiert wird.
Starten Sie die Anwendung neu und erstellen Sie einen neuen magischen Link für Ihren Benutzer. Klicken Sie ihn an, um sich zu authentifizieren. Die Anwendung sieht nun, dass es keinen Nexmo-Benutzer gibt, erstellt einen, fügt ihn zur Konversation hinzu und speichert ihn im Benutzerdatensatz.
Wenn Sie zur Chat-Anwendung weitergeleitet werden, sehen Sie nun, dass Ihr erstellter Benutzer der Unterhaltung beigetreten ist. Sie chatten jedoch immer noch als Ihr fest programmierter Benutzer.

Erzeugen eines Tokens für das Client-SDK
Ihre Nutzer können sich anmelden, einloggen und sogar an der Unterhaltung teilnehmen. Aber im Moment chatten sie nur mit fest einprogrammierten Benutzerdaten. Es ist an der Zeit, das zu ändern und ihnen zu erlauben, als sie selbst zu sprechen.
Öffnen Sie routes/index.js und erstellen Sie eine neue Route /jwtDenn in erster Linie werden Sie ein neues JWT speziell für den Nexmo-Dienst ausstellen, das vom Client SDK verwendet werden kann.
// ...
var nexmo = require('../util/nexmo');
/* GET home */
// ...
/* GET user data and jwt */
router.get('/jwt', isAuthenticated, (req, res, next) => {
const aclPaths = {
"paths": {
"/*/users/**": {},
"/*/conversations/**": {},
"/*/sessions/**": {},
"/*/devices/**": {},
"/*/image/**": {},
"/*/media/**": {},
"/*/push/**": {},
"/*/knocking/**": {}
}
};
const expires_at = new Date();
expires_at.setDate(expires_at.getDate() + 1);
const jwt = nexmo.generateJwt({
application_id: process.env.NEXMO_APP_ID,
sub: req.user.name,
exp: Math.round(expires_at/1000),
acl: aclPaths
});
res.json({
user_id: req.user.user_id,
name: req.user.name,
member_id: req.user.member_id,
display_name: req.user.display_name,
client_token: jwt,
conversation_id: process.env.NEXMO_CONVERSATION_ID,
expires_at: expires_at
});
})
// ...Diese neue Route verwendet die bestehende Sitzung des Benutzers, um Daten an den Browser zu übermitteln. Die Homepage liefert diese Daten als HTML, aber dieser neue Endpunkt gibt JSON zurück.
Starten Sie die Anwendung neu, folgen Sie dem magischen Link und gehen Sie dann zu https://<your_url>.ngrok.io/jwt. Sie sehen Informationen zu Ihrem aktuellen Benutzer, einschließlich einer client_token zur Verwendung im Client SDK.

Entfernen Sie die festcodierte Konfiguration
Es ist an der Zeit, das Hardcoding der Konfiguration innerhalb der Anwendung zu beenden. Bearbeiten Sie die views/layout.hbs Datei und finden Sie die Konfiguration, die Sie innerhalb der <script> Tags hinzugefügt haben. Sie sah etwa so aus.
<script>
var userName = 'luke.oliff@vonage.com';
var displayName = 'Luke Oliff';
var conversationId = 'CON-123...y6346';
var clientToken = 'eyJhbG9.eyJzdWIiO.Sfl5c';
</script>Löschen Sie die Skript-Tags und ihren Inhalt vollständig.
Wenn Sie sehen wollen, was es mit Ihrer App gemacht hat, starten Sie sie neu und authentifizieren Sie sich, um festzustellen, dass sie fast wieder ganz am Anfang steht, mit kaputtem Chat. Wenigstens sind Sie noch eingeloggt!

Benutzer-Client-Token anfordern
Sie können auf das Client-Token des Benutzers über eine URL als JSON-Daten zugreifen. Also, bearbeiten public/javascripts/chat.js und ändern Sie die authenticateUser Methode so, dass sie diese Daten abruft, um sie bei der Verbindung mit der Konversation zu verwenden.
// ...
authenticateUser() {
var req = new XMLHttpRequest();
req.responseType = 'json';
req.open('GET', '/jwt', true);
var obj = this;
req.onload = function() {
obj.joinConversation(req.response);
};
req.send(null);
}
// ...Starten Sie die Anwendung neu, authentifizieren Sie sich und genießen Sie ein kurzes Spiel, bei dem Sie den Unterschied erkennen!

Sie sehen, dass Sie jetzt als ein anderer Benutzer angemeldet sind. Nachrichten von anderen Benutzern werden anders formatiert. Wenn Sie sich also an der Unterhaltung beteiligen, sieht es so aus.

Senden Sie den Magic Link per E-Mail
Sie haben einen magischen Link, aber er wird immer noch in der Konsole ausgegeben. Es ist an der Zeit, ihn stattdessen per E-Mail zu versenden.
Installieren und konfigurieren Sie eine SMTP-Bibliothek
Installieren Sie nodemailer jetzt mit diesem Befehl.
Konfigurieren Sie einige Variablen für die nodemailer Bibliothek in Ihrer Umgebungsdatei .env.
Wenn Sie Google oder einen anderen bekannten E-Mail-Host mit aktivierter 2-Stufen-Überprüfung verwenden, müssen Sie wahrscheinlich ein Anwendungspasswort einrichten. Damit können Sie sich über die Anwendung authentifizieren, ohne dass die 2-Schritt-Verifizierung erforderlich ist.
Erstellen Sie eine neue Dienstprogrammdatei, die Folgendes konfiguriert nodemailer unter util/mailer.js mit diesem Code konfiguriert:
const mailer = require('nodemailer');
require('dotenv').config();
let options = {
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
secure: true,
auth: {
user: process.env.SMTP_AUTH_USER,
pass: process.env.SMTP_AUTH_PASS
}
};
module.exports = mailer.createTransport(options); Magic Links per E-Mail versenden
Die letzte Bearbeitung von routes/webhook.js wird das Hinzufügen der sendEmail Funktion hinzuzufügen und sie zu verwenden, um die console.log Befehle vollständig zu ersetzen.
// ...
var mailer = require('../util/mailer');
// ...
var sendEmail = (magicLink, email) => {
var mailOptions = {
to: email,
subject: 'Magic Link',
text: 'Click to login: ' + magicLink,
html: `<a href="${magicLink}">Click to Login</a>`
};
mailer.sendMail(mailOptions);
}
/* POST webhook generates a magic link email to the provided email address */
router.post('/magiclink', (req, res, next) => {
// ...
if (null === user.user_id) {
// ...
// ...
user.save((err) => {
// ...
sendEmail(createMagicLink(req, user.toObject()), user.email);
res.sendStatus(200);
});
// ...
// ...
} else {
sendEmail(createMagicLink(req, user.toObject()), user.email);
res.sendStatus(200);
}
// ...
});
// ...
Für den letzten Typ starten Sie die Anwendung neu und senden eine Webhook-Anfrage mit Typeform-Daten.
Wenn alles wie erwartet funktioniert, erhalten Sie eine E-Mail an die Adresse, die Sie an Typeform übermittelt haben, mit einem magischen Link. Klicken Sie auf den magischen Link, um sich bei der Anwendung zu authentifizieren und an der Konversation teilzunehmen.
Zeit, ein paar Freunde einzuladen!

Das ist alles, Leute!
Wenn Sie daran interessiert sind, wie die UI für dieses Tutorial erstellt wurde, lesen Sie meinen letzten Beitrag Erstellen einer einfachen Messaging UI mit Bootstrap.
Außerdem gibt es einige Dinge zu beachten, wenn Sie das Gerät in der Praxis einsetzen wollen:
Verwenden Sie ein separates Formular für die Authentifizierung, nachdem sich ein Benutzer bereits registriert hat.
Erfassen Sie einen Anzeigenamen und ein Benutzerbild in Ihrem Typeform.
Verwenden Sie eine widerrufbare undurchsichtige Zeichenfolge anstelle eines JWT innerhalb eines magischen Links.
Erlauben Sie den Nutzern, ihre Daten nach der Authentifizierung zu aktualisieren.
Zeigen Sie alle, die derzeit online sind, im Seitenmenü an.
Erlauben Sie den Benutzern, sich abzumelden.
Den Benutzern das Löschen von Nachrichten erlauben.
Erlauben Sie den Nutzern, Medien zu teilen.
Erweitern Sie freigegebene URLs als Vorschaubilder.
Wenn Sie Audio in einer bestehenden Chat-Anwendung wie dieser aktivieren möchten, können Sie sich meine Anleitung ansehen für Hinzufügen von Sprachfunktionalität zu einer bestehenden Chat-Anwendung.
Danke fürs Lesen und lasst mich wissen, was ihr denkt im Gemeinschaft Slack oder im Kommentarbereich unten 👇.
Teilen Sie:
Freundlicher Tech-Pädagoge, Familienvater, Verfechter der Vielfalt, streitet wahrscheinlich ein bisschen zu viel. Ehemals Backend-Ingenieur. Sprich mit mir über JavaScript (Frontend oder Backend), das erstaunliche Vue.js, DevOps, DevSecOps, alles was mit JamStack zu tun hat. Autorin auf DEV.to
