Die Authentifizierung ist einer der wichtigsten Bestandteile jeder Webanwendung. In diesem Lernprogramm werden tokenbasierte Authentifizierungssysteme und deren Unterschiede zu herkömmlichen Anmeldesystemen beschrieben. Am Ende dieses Tutorials sehen Sie eine voll funktionsfähige Demo, die in AngularJS und NodeJS geschrieben ist.
Auf Envato Market finden Sie außerdem eine große Auswahl an vorgefertigten Authentifizierungsskripts und Apps, wie zum Beispiel:
Wenn Sie mit einem Fehler in Ihrem AngularJS-Code zu kämpfen haben, können Sie ihn bei Envato Studio an araneux senden, um ihn zu beheben.
Bevor wir mit einem tokenbasierten Authentifizierungssystem fortfahren, werfen wir zunächst einen Blick auf ein herkömmliches Authentifizierungssystem.
Bis zu diesem Punkt ist alles in Ordnung. Die Webanwendung funktioniert gut und kann Benutzer authentifizieren, sodass sie auf eingeschränkte Endpunkte zugreifen können. Was passiert jedoch, wenn Sie für Ihre Anwendung einen anderen Client, z. B. für Android, entwickeln möchten? Können Sie die aktuelle Anwendung zur Authentifizierung mobiler Clients und zur Bereitstellung eingeschränkter Inhalte verwenden? Wie es derzeit steht, nein. Dafür gibt es zwei Hauptgründe:
In diesem Fall benötigen Sie eine mandantenunabhängige Anwendung.
Bei der tokenbasierten Authentifizierung werden keine Cookies und Sitzungen verwendet. Ein Token wird zur Authentifizierung eines Benutzers für jede Anforderung an den Server verwendet. Lassen Sie uns das erste Szenario mit tokenbasierter Authentifizierung neu gestalten.
Es wird der folgende Steuerungsfluss verwendet:
In diesem Fall haben wir weder eine Sitzung noch ein Cookie zurückgegeben und wir haben keinen HTML-Inhalt zurückgegeben. Das bedeutet, dass wir diese Architektur für jeden Client für eine bestimmte Anwendung verwenden können. Das Architekturschema sehen Sie unten:
Also, was ist das JWT??
JWT steht für JSON-Web-Token und ist ein Tokenformat, das in Berechtigungsheadern verwendet wird. Dieses Token hilft Ihnen, die Kommunikation zwischen zwei Systemen auf sichere Weise zu gestalten. Lassen Sie uns JWT für dieses Tutorial als "Trägertoken" umformulieren. Ein Träger-Token besteht aus drei Teilen: Header, Payload und Signatur.
Das JWT-Schema und ein Beispiel-Token sehen Sie unten.
Sie müssen den Träger-Token-Generator nicht implementieren, da Sie Versionen finden, die bereits in mehreren Sprachen vorhanden sind. Einige davon sehen Sie unten:
Sprache | Bibliotheks-URL |
---|---|
NodeJS | http://github.com/auth0/node-jsonwebtoken |
PHP | http://github.com/firebase/php-jwt |
Java | http://github.com/auth0/java-jwt |
Rubin | http://github.com/progrium/ruby-jwt |
.NETZ | http://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet |
Python | http://github.com/progrium/pyjwt/ |
Nachdem wir einige grundlegende Informationen zur tokenbasierten Authentifizierung behandelt haben, können wir nun mit einem praktischen Beispiel fortfahren. Schauen Sie sich das folgende Schema an, in dem wir es genauer analysieren:
https://api.yourexampleapp.com
. Wenn viele Personen die Anwendung verwenden, sind möglicherweise mehrere Server erforderlich, um den angeforderten Vorgang auszuführen.https://api.yourexampleapp.com
, Der Load Balancer wird zunächst eine Anforderung bearbeiten und dann den Client an einen bestimmten Server umleiten.https://api.yourexampleapp.com
, Die Back-End-Anwendung fängt den Anforderungsheader ab und extrahiert Tokeninformationen aus dem Berechtigungsheader. Mit diesem Token wird eine Datenbankabfrage durchgeführt. Wenn dieses Token gültig ist und über die erforderliche Berechtigung zum Zugriff auf den angeforderten Endpunkt verfügt, wird es fortgesetzt. Wenn nicht, wird ein Antwortcode 403 (der einen verbotenen Status anzeigt) zurückgegeben..Die auf Token basierende Authentifizierung bietet mehrere Vorteile, die ernsthafte Probleme lösen. Einige davon sind wie folgt:
Temp
Ordner, zumindest zum ersten Mal. Angenommen, Sie haben mehrere Server und auf dem ersten Server wird eine Sitzung erstellt. Wenn Sie eine andere Anfrage stellen und Ihre Anfrage auf einem anderen Server abgelegt wird, sind keine Sitzungsinformationen vorhanden und Sie erhalten eine "unautorisierte" Antwort. Ich weiß, du kannst das mit einer klebrigen Sitzung lösen. Bei der tokenbasierten Authentifizierung wird dieser Fall jedoch auf natürliche Weise gelöst. Es gibt kein ständiges Sitzungsproblem, da das Anforderungstoken bei jeder Anforderung auf einem Server abgefangen wird.Dies sind die häufigsten Vorteile der tokenbasierten Authentifizierung und Kommunikation. Das ist das Ende der theoretischen und architektonischen Diskussion über die tokenbasierte Authentifizierung. Zeit für ein praktisches Beispiel.
Sie sehen zwei Anwendungen, um die tokenbasierte Authentifizierung zu demonstrieren:
Im Back-End-Projekt werden Service-Implementierungen durchgeführt, und die Service-Ergebnisse werden im JSON-Format vorliegen. In Services wird keine Ansicht zurückgegeben. Im Front-End-Projekt wird es ein AngularJS-Projekt für Front-End-HTML geben. Anschließend wird die Front-End-App von AngularJS-Diensten aufgefüllt, um Anforderungen an die Back-End-Dienste zu stellen.
Im Back-End-Projekt gibt es drei Hauptdateien:
package.json
ist für Abhängigkeitsmanagement.models \ User.js
enthält ein Benutzermodell, das zum Ausführen von Datenbankoperationen für Benutzer verwendet wird.server.js
ist für das Booten von Projekten und die Bearbeitung von Anfragen.Das ist es! Dieses Projekt ist sehr einfach, so dass Sie das Hauptkonzept leicht verstehen können, ohne einen tiefen Tauchgang zu machen.
"name": "angle-restful-auth", "version": "0.0.1", "abhängigkeiten": "express": "4.x", "body-parser": "~ 1.0.0" , "morgan": "latest", "mongoose": "3.8.8", "jsonwebtoken": "0.4.0", "engine": "node": "> = 0.10.0"
package.json
enthält Abhängigkeiten für das Projekt: ausdrücken
für MVC, Körperparser
zum Simulieren der Nachabfrage in NodeJS, Morgan
zur Anforderungsprotokollierung, Mungo
für unser ORM-Framework, um eine Verbindung zu MongoDB herzustellen, und jsonwebtoken
zum Erstellen von JWT-Token mithilfe unseres Benutzermodells. Es gibt auch ein Attribut namens Motoren
das besagt, dass dieses Projekt mithilfe der NodeJS-Version> = 0.10.0 erstellt wurde. Dies ist nützlich für PaaS-Dienste wie Heroku. Wir werden dieses Thema auch in einem anderen Abschnitt behandeln.
var Mungo = Anfordern ('Mungo'); var Schema = mongoose.Scema; var UserSchema = neues Schema (email: String, Passwort: String, Token: String); module.exports = mongoose.model ('User', UserSchema);
Wir haben gesagt, dass wir mithilfe der Nutzlast des Nutzermodells ein Token generieren würden. Dieses Modell hilft uns, Benutzeroperationen in MongoDB durchzuführen. Im User.js
, Das Benutzerschema wird definiert und das Benutzermodell wird mithilfe eines Mungo-Modells erstellt. Dieses Modell ist bereit für Datenbankoperationen.
Unsere Abhängigkeiten sind definiert, und unser Benutzermodell ist definiert. Lassen Sie uns nun alle dazu kombinieren, um einen Dienst für die Bearbeitung spezifischer Anforderungen zu erstellen.
// Erforderliche Module var express = required ("express"); var morgan = erfordern ("morgan"); var bodyParser = required ("Körperparser"); var jwt = required ("jsonwebtoken"); var Mungo = Anfordern ("Mungo"); var app = express ();
In NodeJS können Sie ein Modul in Ihr Projekt aufnehmen, indem Sie verwenden benötigen
. Zunächst müssen wir die erforderlichen Module in das Projekt importieren:
var port = process.env.PORT || 3001; var User = erfordern ('./ models / User'); // Verbindung zu DB herstellen mongoose.connect (process.env.MONGO_URL);
Unser Service wird über einen bestimmten Hafen abgewickelt. Wenn eine Portvariable in den Systemumgebungsvariablen definiert ist, können Sie diese verwenden, oder wir haben Port definiert 3001
. Danach wird das Benutzermodell eingefügt, und die Datenbankverbindung wird hergestellt, um einige Benutzeroperationen auszuführen. Vergessen Sie nicht, eine Umgebungsvariable zu definieren-MONGO_URL
-für die Datenbankverbindungs-URL.
app.use (bodyParser.urlencoded (extended: true))); app.use (bodyParser.json ()); app.use (morgan ("dev")); app.use (Funktion (req, res, next) res.setHeader ('Access-Control-Allow-Origin', '*'); res.setHeader ('Access-Control-Allow-Methods', 'GET, POST.) '); res.setHeader (' Access-Control-Allow-Header ',' X-Requested-With, Inhaltstyp, Autorisierung '); next (););
Im obigen Abschnitt haben wir einige Konfigurationen zum Simulieren einer HTTP-Anforderungsverarbeitung in NodeJS mithilfe von Express vorgenommen. Wir erlauben Anfragen aus verschiedenen Bereichen, um ein kundenunabhängiges System zu entwickeln. Wenn Sie dies nicht zulassen, wird im Webbrowser ein CORS-Fehler (Cross Origin Request Sharing) ausgelöst.
Access-Control-Allow-Origin
erlaubt für alle Domains.POST
und ERHALTEN
Anfragen an diesen Dienst.X-angefordert-mit
und Inhaltstyp
Header sind erlaubt.app.post ('/ authenticate', Funktion (req, res)) User.findOne (email: req.body.email, Kennwort: req.body.password, Funktion (err, user) if (err) res.json (type: false, data: "Fehler aufgetreten:" + err); else if (user) res.json (type: true, data: user, token: user.token); else res.json (Typ: falsch, Daten: "Falsche E-Mail-Adresse / Kennwort");););
Wir haben alle erforderlichen Module importiert und unsere Konfiguration definiert. Jetzt müssen Request-Handler definiert werden. Wenn Sie im obigen Code eine POST
Anfrage zu /authentifizieren
mit Benutzername und Passwort erhalten Sie eine JWT
Zeichen. Zunächst wird die Datenbankabfrage mit einem Benutzernamen und einem Kennwort verarbeitet. Wenn ein Benutzer vorhanden ist, werden die Benutzerdaten mit ihrem Token zurückgegeben. Was aber, wenn kein solcher Benutzer mit dem Benutzernamen und / oder dem Kennwort übereinstimmt?
app.post ('/ signin', Funktion (req, res)) User.findOne (E-Mail: req.body.email, Passwort: req.body.password, Funktion (err, user) if (err) res.json (Typ: false, Daten: "Fehler aufgetreten:" + err); else if (Benutzer) res.json (Typ: false, Daten: "Benutzer ist bereits vorhanden!"); else var userModel = new User (); userModel.email = req.body.email; userModel.password = req.body.password; userModel.save (Funktion (err, user) user.token = jwt.sign (user.) , process.env.JWT_SECRET); user.save (function (err, user1) res.json (type: true, data: user1, token: user1.token);)); );
Wenn Sie eine machen POST
Anfrage zu /Einloggen
Mit Benutzername und Passwort wird ein neuer Benutzer erstellt, indem die veröffentlichten Benutzerinformationen verwendet werden. Auf der 19.
In dieser Zeile können Sie sehen, dass ein neues JSON-Token generiert wird jsonwebtoken
Modul, das dem zugeordnet wurde jwt
Variable. Der Authentifizierungsteil ist in Ordnung. Was ist, wenn wir versuchen, auf einen eingeschränkten Endpunkt zuzugreifen? Wie können wir auf diesen Endpunkt zugreifen??
app.get ('/ me', sureAuthorized, Funktion (req, res) User.findOne (token: req.token, Funktion (err, user) if (err) res.json (type: false.) , Daten: "Fehler aufgetreten:" + err); else res.json (Typ: wahr, Daten: Benutzer);;);
Wenn Sie eine machen ERHALTEN
Anfrage zu /mir
, Sie erhalten die aktuellen Benutzerinformationen. Um jedoch mit dem angeforderten Endpunkt fortzufahren, klicken Sie auf sureAuthorized
Funktion wird ausgeführt.
Funktion sureAuthorized (req, res, next) var bearerToken; var bearerHeader = req.headers ["Autorisierung"]; if (typeof bearerHeader! == 'undefined') var bearer = bearerHeader.split (""); BearerToken = Träger [1]; req.token = BearerToken; Nächster(); else res.send (403);
In dieser Funktion werden Anforderungsheader abgefangen und die Genehmigung
Header wird extrahiert. Wenn in diesem Header ein Trägertoken vorhanden ist, wird dieses Token zugewiesen req.token
um in der gesamten Anfrage verwendet zu werden, und die Anfrage kann mit fortgesetzt werden Nächster()
. Wenn ein Token nicht vorhanden ist, erhalten Sie eine 403-Antwort (Verboten). Gehen wir zum Handler zurück /mir
, und verwenden req.token
Benutzerdaten mit diesem Token abrufen. Wenn Sie einen neuen Benutzer erstellen, wird ein Token generiert und im Benutzermodell in der Datenbank gespeichert. Diese Token sind einzigartig.
Wir haben nur drei Handler für dieses einfache Projekt. Danach wirst du sehen;
process.on ('uncaughtException', function (err) console.log (err););
Die NodeJS-App kann abstürzen, wenn ein Fehler auftritt. Mit dem obigen Code wird dieser Absturz verhindert und ein Fehlerprotokoll wird in der Konsole gedruckt. Und schließlich können wir den Server mit dem folgenden Code-Snippet starten.
// Server starten app.listen (port, function () console.log ("Express-Server überwacht Port" + Port););
Um zusammenzufassen:
Wir sind fertig mit dem Backend-Service. Damit es von mehreren Clients verwendet werden kann, können Sie diese einfache Serveranwendung auf Ihren Servern oder möglicherweise in Heroku bereitstellen. Es gibt eine Datei namens Procfile
im Stammordner des Projekts. Lassen Sie uns unseren Service in Heroku einsetzen.
Sie können das Back-End-Projekt aus diesem GitHub-Repository klonen.
Ich werde nicht diskutieren, wie man eine App in Heroku erstellt. Sie können sich auf diesen Artikel beziehen, um eine Heroku-App zu erstellen, falls Sie dies noch nicht getan haben. Nachdem Sie Ihre Heroku-App erstellt haben, können Sie Ihrem aktuellen Projekt mithilfe des folgenden Befehls ein Ziel hinzufügen:
Git Remote hinzufügen Heroku
Jetzt haben Sie ein Projekt geklont und ein Ziel hinzugefügt. Nach dem git add
und git begehen
, Sie können Ihren Code durch Ausführen an Heroku übertragen git Push Heroku-Meister
. Wenn Sie ein Projekt erfolgreich pushen, führt Heroku das aus npm installieren
Befehl zum Herunterladen von Abhängigkeiten in die Temp
Ordner auf Heroku. Danach wird Ihre Anwendung gestartet und Sie können mithilfe des HTTP-Protokolls auf Ihren Dienst zugreifen.
Im Front-End-Projekt sehen Sie ein AngularJS-Projekt. Ich werde hier nur die Hauptabschnitte des Front-End-Projekts erwähnen, da AngularJS nicht in einem einzigen Tutorial behandelt werden kann.
Sie können das Projekt aus diesem GitHub-Repository klonen. In diesem Projekt sehen Sie folgende Ordnerstruktur:
ngStorage.js
ist eine Bibliothek für AngularJS zur Bearbeitung lokaler Speicheroperationen. Es gibt auch ein Hauptlayout index.html
und Teiltöne, die das Hauptlayout unter erweitern partials
Mappe. Steuerungen.js
dient zur Definition unserer Controller-Aktionen im Frontend. services.js
dient dazu, Serviceanfragen an unseren Service zu stellen, die ich im vorherigen Projekt erwähnt habe. Wir haben eine Bootstrap-ähnliche Datei namens app.js
In dieser Datei werden Konfigurationen und Modulimporte angewendet. Endlich, client.js
dient zum Bereitstellen statischer HTML-Dateien (oder einfach nur index.html
, in diesem Fall); Dies hilft uns, statische HTML-Dateien bereitzustellen, wenn Sie sie auf einem Server bereitstellen, ohne Apache oder einen anderen Webserver zu verwenden.
…
In der HTML-Hauptdatei des Layouts sind alle erforderlichen JavaScript-Dateien für AngularJS-Bibliotheken sowie für unsere benutzerdefinierten Controller-, Service- und App-Dateien enthalten.
'streng verwenden'; / * Controller * / angle.module ('angleRestfulAuth') .controller ('HomeCtrl', ['$ rootScope', '$ scope', '$ location', '$ localStorage', 'Main', Funktion ($ rootScope, $ scope, $ location, $ localStorage, Main) $ scope.signin = function () var formData = email: $ scope.email, Kennwort: $ scope.password Main.signin (formData, function (res) if (res.type == false) alert (res.data) else $ localStorage.token = res.data.token; window.location = "/";, function () $ rootScope.error = 'Anmeldung fehlgeschlagen';); $ scope.signup = function () var formData = email: $ scope.email, Kennwort: $ scope.password Main.save (formData, function (res) if ( res.type == false) alert (res.data) else $ localStorage.token = res.data.token; window.location = "/", function () $ rootScope.error = 'Fehlgeschlagen signup ';); $ scope.me = function () Main.me (function (res) $ scope.myDetails = res;, function () $ rootScope.error =' Details konnten nicht abgerufen werden '; ); $ scope.logout = function () Main.logout (fu nction () window.location = "/", function () alert ("Abmeldung fehlgeschlagen!"); ); ; $ scope.token = $ localStorage.token; ])
Im obigen Code steht der HomeCtrl
Controller ist definiert und einige erforderliche Module werden wie injiziert $ rootScope
und $ scope
. Abhängigkeitsinjektion ist eine der stärksten Eigenschaften von AngularJS. $ scope
ist die Brückenvariable zwischen Controllern und Ansichten in AngularJS, die Sie verwenden können Prüfung
in view, wenn Sie es in einem angegebenen Controller definiert haben $ scope.test =…
In diesem Controller sind einige Hilfsfunktionen definiert, wie zum Beispiel:
Einloggen
um eine Anmeldeschaltfläche auf dem Anmeldeformular einzurichtenAnmelden
für das Anmeldeformularhandlingmir
zum Zuweisen der Me-Schaltfläche im LayoutIm Hauptlayout in der Hauptmenüliste sehen Sie die Daten-Controller
Attribut mit einem Wert HomeCtrl
. Das bedeutet, dass dieses Menü dom
Element kann den Gültigkeitsbereich mit teilen HomeCtrl
. Wenn Sie auf die Anmeldeschaltfläche im Formular klicken, wird die Anmeldefunktion in der Controller-Datei ausgeführt, und in dieser Funktion wird der Anmeldedienst von verwendet Main
Dienst, der bereits in diesen Controller injiziert wurde.
Die Hauptstruktur ist Ansicht -> Controller -> Dienst
. Dieser Dienst führt einfache Ajax-Anforderungen an das Backend aus, um bestimmte Daten zu erhalten.
'streng verwenden'; angle.module ('angleRestfulAuth') .factory ('Main', ['$ http', '$ localStorage'), Funktion ($ http, $ localStorage) var baseUrl = "your_service_url"; Funktion changeUser (user) angle. extend (currentUser, user); Funktion urlBase64Decode (str) var Ausgabe = str.replace ('-', '+'). replace ('_', '/'); switch (output.length% 4) case 0: break; case 2: output + = '=='; break; case 3: output + = '='; break; default: throw 'Illegal base64url string!'; return window.atob (output); function getUserFromToken () var token = $ localStorage.token; var user = ; if (typeof-Token! == 'undefined') var encoded = token.split ('.') [1]; user = JSON. parse (urlBase64Decode (codiert)); return user; var currentUser = getUserFromToken (); return save: function (Daten, Erfolg, Fehler) $ http.post (baseUrl + '/ signin', data) .success ( Erfolg). Fehler (Fehler), Anmelden: Funktion (Daten, Erfolg, Fehler) $ http.post (baseUrl + '/ authenticate', Daten). Erfolg (Erfolg). Fehler (Fehler), me: Funktion ( Erfolg, Fehler) $ htt p.get (baseUrl + '/me').success(success).error(error), logout: function (success) changeUser (); lösche $ localStorage.token; Erfolg(); ; ]);
Im obigen Code können Sie Servicefunktionen sehen, z. B. Anfragen zur Authentifizierung. In controller.js haben Sie möglicherweise bereits erkannt, dass es Funktionen wie gibt Main.me
. Diese Main
Dienst wurde in die Steuerung eingespeist, und in der Steuerung werden die zu diesem Dienst gehörenden Dienste direkt aufgerufen.
Diese Funktionen sind einfach Ajax-Anfragen an unseren Service, die wir gemeinsam eingesetzt haben. Vergessen Sie nicht, die Service-URL einzugeben baseUrl
im obigen Code. Wenn Sie Ihren Service bei Heroku bereitstellen, erhalten Sie eine Service-URL wie appname.herokuapp.com
. Im obigen Code werden Sie einstellen var baseUrl = "appname.herokuapp.com"
.
Im Anmelde- oder Anmeldeteil der Anwendung antwortet das Bearer-Token auf die Anforderung, und dieses Token wird im lokalen Speicher gespeichert. Wann immer Sie eine Anforderung an einen Dienst im Back-End stellen, müssen Sie dieses Token in die Header einfügen. Sie können dies tun, indem Sie AngularJS-Interzeptoren verwenden.
$ httpProvider.interceptors.push (['$ q', '$ location', '$ localStorage'), Funktion ($ q, $ location, $ localStorage) return 'request': function (config) config.headers = config.headers || ; if ($ localStorage.token) config.headers.Authorization = 'Bearer' + $ localStorage.token; return config;, 'responseError': function (response) if (antwort.) status === 401 || response.status === 403) $ location.path ('/ signin'); return $ q.reject (response);;]);
Im obigen Code wird jede Anforderung abgefangen, und ein Berechtigungsheader und ein Wert werden in die Header eingefügt.
Im Frontend-Projekt haben wir einige Teilseiten wie Einloggen
, Anmelden
, Profildetails
, und vb
. Diese Teilseiten beziehen sich auf bestimmte Steuerungen. Sie können diese Beziehung in sehen app.js
:
angle.module ('angleRestfulAuth', ['ngStorage', 'ngRoute'])) .config (['$ routeProvider', '$ httpProvider'), Funktion ($ routeProvider, $ httpProvider) $ routeProvider. templateUrl: 'partials / home.html', Controller: 'HomeCtrl'). when ('/ signin', templateUrl: 'partials / signin.html', Controller: 'HomeCtrl'). when ('/ signup ', templateUrl:' partials / signup.html ', Controller:' HomeCtrl '). when (' / me ', templateUrl:' partials / me.html ', Controller:' HomeCtrl '). ansonsten ( redirectTo: '/');
Wie Sie im obigen Code leicht verstehen können, wenn Sie zu gehen /
, das home.html
Seite wird gerendert. Ein anderes Beispiel: Wenn Sie zu gehen /Anmelden
, signup.html
wird gerendert. Dieser Rendering-Vorgang wird im Browser und nicht auf der Serverseite durchgeführt.
Sie können sehen, wie alles, was wir in diesem Tutorial besprochen haben, in der Praxis funktioniert.
Token-basierte Authentifizierungssysteme helfen Ihnen beim Aufbau eines Authentifizierungs- / Autorisierungssystems, während Sie Client-unabhängige Dienste entwickeln. Durch die Verwendung dieser Technologie konzentrieren Sie sich nur auf Ihre Dienste (oder APIs)..
Der Authentifizierungs- / Autorisierungsteil wird vom tokenbasierten Authentifizierungssystem als Schicht vor Ihren Diensten behandelt. Sie können von jedem Client aus auf Dienste zugreifen und diese verwenden, z. B. Webbrowser, Android, iOS oder einen Desktop-Client.
Und wenn Sie nach vorgefertigten Lösungen suchen, schauen Sie sich die Authentifizierungsskripte und Apps von Envato Market an.