Integrieren des Facebook-Logins in die AngularJS-App mit Satellizer

Veröffentlicht: 2022-03-11

Mit der Einführung funktionsreicher Front-End-Frameworks wie AngularJS wird immer mehr Logik im Front-End implementiert, z. B. Datenmanipulation/-validierung, Authentifizierung und mehr. Satellizer, ein benutzerfreundliches Token-basiertes Authentifizierungsmodul für AngularJS, vereinfacht den Prozess der Implementierung des Authentifizierungsmechanismus in AngularJS. Die Bibliothek bietet integrierte Unterstützung für Google, Facebook, LinkedIn, Twitter, Instagram, GitHub, Bitbucket, Yahoo, Twitch , und Microsoft (Windows Live)-Konten.

In diesem Artikel werden wir eine sehr einfache Webanwendung ähnlich der hier erstellen, mit der Sie sich anmelden und die Informationen des aktuellen Benutzers anzeigen können.

Authentifizierung vs. Autorisierung

Dies sind 2 beängstigende Wörter, denen Sie oft begegnen, wenn Ihre App beginnt, ein Benutzersystem zu integrieren. Laut Wikipedia:

Authentifizierung ist der Akt der Bestätigung der Wahrheit eines Attributs eines einzelnen Datenstücks (eines Datums), das von einer Entität als wahr beansprucht wird.

Autorisierung ist die Funktion, Zugriffsrechte auf Ressourcen festzulegen, die sich auf Informationssicherheit und Computersicherheit im Allgemeinen und auf Zugriffskontrolle im Besonderen beziehen.

Lassen Sie uns in Laiensprache ein Beispiel einer Blog-Website nehmen, an der einige Leute arbeiten. Die Blogger schreiben Artikel und der Manager validiert den Inhalt. Jede Person kann sich beim System authentifizieren (einloggen), aber ihre Rechte (Autorisierung) sind unterschiedlich, sodass der Blogger den Inhalt nicht validieren kann, während der Manager dies kann.

Warum Satellizer

Sie können Ihr eigenes Authentifizierungssystem in AngularJS erstellen, indem Sie einigen Tutorials wie diesem sehr detaillierten folgen: JSON Web Token Tutorial: An Example in Laravel and AngularJS. Ich schlage vor, diesen Artikel zu lesen, da er JWT (JSON Web Token) sehr gut erklärt und eine einfache Möglichkeit zeigt, die Authentifizierung in AngularJS zu implementieren, indem direkt der lokale Speicher und HTTP-Interceptoren verwendet werden.

Warum also Satellizer? Der Hauptgrund ist, dass es eine Handvoll Anmeldungen für soziale Netzwerke wie Facebook, Twitter usw. unterstützt. Heutzutage ist die Eingabe von Benutzername und Passwort ziemlich umständlich, insbesondere für Websites, die auf Mobilgeräten verwendet werden, und Benutzer erwarten, dass sie Ihre Website mit wenig Behinderung nutzen können durch die Verwendung von Social Logins. Da die Integration des SDK jedes sozialen Netzwerks und das Verfolgen ihrer Dokumentation ziemlich repetitiv ist, wäre es schön, diese sozialen Logins mit minimalem Aufwand zu unterstützen.

Außerdem ist Satellizer ein aktives Projekt auf Github. Aktiv ist hier der Schlüssel, da sich diese SDKs ziemlich häufig ändern und Sie ihre Dokumentation nicht ab und zu lesen möchten (jeder, der mit Facebook SDK arbeitet, weiß, wie nervig es ist).

AngularJS-App mit Facebook-Login

Hier beginnen die Dinge interessant zu werden.

Wir werden eine Web-App erstellen, die über einen regulären Anmelde-/Registrierungsmechanismus (dh mit Benutzername, Passwort) verfügt und auch soziale Anmeldungen unterstützt. Diese Webapp ist sehr einfach, da sie nur 3 Seiten hat:

  • Startseite: Jeder kann sie sehen
  • Anmeldeseite: zur Eingabe von Benutzername/Passwort
  • Geheime Seite: die nur eingeloggte Benutzer sehen können

Für das Backend verwenden wir Python und Flask. Python und das Framework Flask sind ziemlich ausdrucksstark, daher hoffe ich, dass die Portierung des Codes auf andere Sprachen/Frameworks nicht sehr schwierig sein wird. Wir werden natürlich AngularJS als Frontend verwenden. Und für die sozialen Logins werden wir nur mit Facebook integrieren, da es derzeit das beliebteste soziale Netzwerk ist.

Lasst uns beginnen!

Schritt Nr. 1: Bootstrap-Projekt

So werden wir unseren Code strukturieren:

 - app.py - static/ - index.html - app.js - bower.json - partials/ - login.tpl.html - home.tpl.html - secret.tpl.html

Der gesamte Back-End-Code befindet sich in app.py . Der Front-End-Code wird im Ordner static/ abgelegt. Standardmäßig stellt Flask automatisch den Inhalt des Ordners static/ bereit. Alle Teilansichten befinden sich in static/partials/ und werden vom ui.router-Modul verarbeitet.

Um mit der Codierung des Backends zu beginnen, benötigen wir Python 2.7.* und installieren die erforderlichen Bibliotheken mit pip. Sie können natürlich virtualenv verwenden, um eine Python-Umgebung zu isolieren. Unten ist die Liste der erforderlichen Python-Module, die in der requirements.txt eingefügt werden müssen:

 Flask==0.10.1 PyJWT==1.4.0 Flask-SQLAlchemy==1.0 requests==2.7.0

So installieren Sie alle diese Abhängigkeiten:

 pip install -r requirements.txt

In app.py haben wir einen anfänglichen Code zum Bootstrap von Flask (import-Anweisungen werden der Kürze halber weggelassen):

 app = Flask(__name__) @app.route('/') def index(): return flask.redirect('/static/index.html') if __name__ == '__main__': app.run(debug=True)

Als nächstes initieren wir Bower und installieren AngularJS und ui.router:

 bower init # here you will need to answer some question. when in doubt, just hit enter :) bower install angular angular-ui-router --save # install and save these dependencies into bower.json

Sobald diese Bibliotheken installiert sind, müssen wir AngularJS und ui-router in index.html einfügen und Routings für 3 Seiten erstellen: Home, Login und Secret.

 <body ng-app="DemoApp"> <a ui-sref="home">Home</a> <a ui-sref="login">Login</a> <a ui-sref="secret">Secret</a> <div ui-view></div> <script src="bower_components/angular/angular.min.js"></script> <script src="bower_components/angular-ui-router/release/angular-ui-router.min.js"></script> <script src="main.js"></script> </body>

Unten ist der Code, den wir in main.js benötigen, um das Routing zu konfigurieren:

 var app = angular.module('DemoApp', ['ui.router']); app.config(function ($stateProvider, $urlRouterProvider) { $stateProvider .state('home', { url: '/home', templateUrl: 'partials/home.tpl.html' }) .state('secret', { url: '/secret', templateUrl: 'partials/secret.tpl.html', }) .state('login', { url: '/login', templateUrl: 'partials/login.tpl.html' }); $urlRouterProvider.otherwise('/home'); });

Wenn Sie zu diesem Zeitpunkt den Server python app.py ausführen , sollten Sie diese grundlegende Schnittstelle unter http://localhost:5000 haben

Grundlegende Anmeldeschnittstelle

Die Links Home, Login und Secret sollten an dieser Stelle funktionieren und den Inhalt der entsprechenden Templates anzeigen.

Herzlichen Glückwunsch, Sie haben gerade das Skelett aufgebaut! Wenn Sie auf einen Fehler stoßen, überprüfen Sie bitte den Code auf GitHub

Schritt Nr. 2: Anmelden und registrieren

Am Ende dieses Schritts haben Sie eine Webapp, die Sie mit E-Mail und Passwort registrieren/anmelden können.

Der erste Schritt besteht darin, das Backend zu konfigurieren. Wir benötigen ein Benutzermodell und eine Möglichkeit, das JWT-Token für einen bestimmten Benutzer zu generieren. Das unten gezeigte Benutzermodell ist wirklich vereinfacht und führt nicht einmal grundlegende Prüfungen durch, z. B. ob das Feld E- Mail ein „@“ enthält oder ob das Feld Passwort mindestens 6 Zeichen enthält usw.

 class User(db.Model): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(100), nullable=False) password = db.Column(db.String(100)) def token(self): payload = { 'sub': self.id, 'iat': datetime.utcnow(), 'exp': datetime.utcnow() + timedelta(days=14) } token = jwt.encode(payload, app.config['TOKEN_SECRET']) return token.decode('unicode_escape')

Wir verwenden das jwt-Modul in Python, um den Nutzlastteil in JWT zu generieren. Der iat- und exp-Teil entsprechen dem Zeitstempel, zu dem das Token erstellt wurde und abgelaufen ist. In diesem Code läuft das Token in 2 Wochen ab.

Nachdem der Modellbenutzer erstellt wurde, können wir die Endpunkte „Anmeldung“ und „Registrierung“ hinzufügen. Der Code für beide ist ziemlich ähnlich, also zeige ich hier nur den Teil „Registrieren“. Bitte beachten Sie, dass Satellizer standardmäßig die Endpunkte /auth/login und /auth/signup für „login“ bzw. „register“ aufruft.

 @app.route('/auth/signup', methods=['POST']) def signup(): data = request.json email = data["email"] password = data["password"] user = User(email=email, password=password) db.session.add(user) db.session.commit() return jsonify(token=user.token())

Lassen Sie uns zuerst den Endpunkt mit curl überprüfen:

 curl localhost:5000/auth/signup -H "Content-Type: application/json" -X POST -d '{"email":"[email protected]","password":"xyz"}'

Das Ergebnis sollte so aussehen:

 { "token": "very long string…." }

Nun, da der Back-End-Teil fertig ist, greifen wir das Front-End an! Zuerst müssen wir Satellizer installieren und als Abhängigkeit in main.js hinzufügen:

 bower install satellizer --save

Satellizer als Abhängigkeit hinzufügen:

 var app = angular.module('DemoApp', ['ui.router', 'satellizer']);

Die Anmeldung und Anmeldung bei Satellizer ist eigentlich ganz einfach im Vergleich zu allen bisherigen Einstellungen:

 $scope.signUp = function () { $auth .signup({email: $scope.email, password: $scope.password}) .then(function (response) { // set the token received from server $auth.setToken(response); // go to secret page $state.go('secret'); }) .catch(function (response) { console.log("error response", response); }) };

Wenn Sie Schwierigkeiten beim Einrichten des Codes haben, können Sie sich den Code auf GitHub ansehen.

Schritt #3: Aber Secret View ist nicht wirklich geheim, weil jeder es sehen kann!

Ja, das ist richtig! Bis jetzt kann jeder auf die geheime Seite gehen, ohne sich anzumelden.

Es ist an der Zeit, einen Interceptor in AngularJS hinzuzufügen, um sicherzustellen, dass, wenn jemand auf die geheime Seite geht und dieser Benutzer nicht angemeldet ist, er auf die Anmeldeseite umgeleitet wird.

Zuerst sollten wir ein Flag requiredLogin hinzufügen, um die geheime Seite von anderen zu unterscheiden.

 .state('secret', { url: '/secret', templateUrl: 'partials/secret.tpl.html', controller: 'SecretCtrl', data: {requiredLogin: true} })

Der „Daten“-Teil wird im $stateChangeStart-Ereignis verwendet, das jedes Mal ausgelöst wird, wenn sich das Routing ändert:

 app.run(function ($rootScope, $state, $auth) { $rootScope.$on('$stateChangeStart', function (event, toState) { var requiredLogin = false; // check if this state need login if (toState.data && toState.data.requiredLogin) requiredLogin = true; // if yes and if this user is not logged in, redirect him to login page if (requiredLogin && !$auth.isAuthenticated()) { event.preventDefault(); $state.go('login'); } }); });

Jetzt kann der Benutzer nicht direkt auf die geheime Seite gehen, ohne sich anzumelden. Hurra!

Den Code dieses Schrittes finden Sie wie gewohnt hier.

Schritt Nr. 4: Es ist Zeit für etwas wirklich Geheimes!

In diesem Moment gibt es auf der geheimen Seite nichts wirklich Geheimnisvolles. Lassen Sie uns dort etwas Persönliches unterbringen.

Dieser Schritt beginnt mit der Erstellung eines Endpunkts im Back-End, auf den nur ein authentifizierter Benutzer zugreifen kann, der beispielsweise über ein gültiges Token verfügt. Der Endpunkt /user unten gibt die user_id und die E- Mail -Adresse des Benutzers zurück, der dem Token entspricht.

 @app.route('/user') def user_info(): # the token is put in the Authorization header if not request.headers.get('Authorization'): return jsonify(error='Authorization header missing'), 401 # this header looks like this: “Authorization: Bearer {token}” token = request.headers.get('Authorization').split()[1] try: payload = jwt.decode(token, app.config['TOKEN_SECRET']) except DecodeError: return jsonify(error='Invalid token'), 401 except ExpiredSignature: return jsonify(error='Expired token'), 401 else: user_id = payload['sub'] user = User.query.filter_by(id=user_id).first() if user is None: return jsonify(error='Should not happen ...'), 500 return jsonify(id=user.id, email=user.email), 200 return jsonify(error="never reach here..."), 500

Auch hier verwenden wir das Modul jwt , um das im Header „Authorization“ enthaltene JWT-Token zu entschlüsseln und den Fall zu behandeln, dass das Token abgelaufen oder ungültig ist.

Lassen Sie uns diesen Endpunkt mit curl testen. Zuerst müssen wir ein gültiges Token erhalten:

 curl localhost:5000/auth/signup -H "Content-Type: application/json" -X POST -d '{"email":"[email protected]","password":"xyz"}'

Dann mit diesem Token:

 curl localhost:5000/user -H "Authorization: Bearer {put the token here}"

Was dieses Ergebnis ergibt:

 { "email": "[email protected]", "id": 1 }

Jetzt müssen wir diesen Endpunkt in den Secret Controller aufnehmen. Dies ist ganz einfach, da wir den Endpunkt nur mit dem regulären $http-Modul aufrufen müssen. Der Token wird von Satellizer automatisch in den Header eingefügt, sodass wir uns nicht um alle Details kümmern müssen, um den Token zu speichern und ihn dann in den richtigen Header einzufügen.

 getUserInfo(); function getUserInfo() { $http.get('/user') .then(function (response) { $scope.user = response.data; }) .catch(function (response) { console.log("getUserInfo error", response); }) }

Endlich haben wir etwas wirklich Persönliches auf der geheimen Seite!

Die geheime Seite, die eine Benutzer-E-Mail und -ID anzeigt.

Der Code dieses Schritts befindet sich auf GitHub.

Schritt #5: Facebook-Login mit Satellizer

Das Schöne an Satellizer ist, wie eingangs erwähnt, dass es die Integration von Social Login viel einfacher macht. Am Ende dieses Schritts können sich Benutzer mit ihrem Facebook-Konto anmelden!

Facebook-OAuth-Authentifizierung.

Als erstes müssen Sie eine Anwendung auf der Facebook-Entwicklerseite erstellen, um eine Anwendungs -ID und einen Geheimcode zu erhalten. Bitte folgen Sie developer.facebook.com/docs/apps/register, um ein Facebook-Entwicklerkonto zu erstellen, falls Sie noch keines haben, und erstellen Sie eine Website-App. Danach haben Sie die Anwendungs-ID und das Anwendungsgeheimnis wie im folgenden Screenshot.

Abrufen des Anwendungsgeheimnisses.

Sobald sich der Benutzer für eine Verbindung mit Facebook entscheidet, sendet Satellizer einen Autorisierungscode an den Endpunkt /auth/facebook . Mit diesem Autorisierungscode kann das Back-End ein Zugriffstoken vom Facebook- /oauth- Endpunkt abrufen, das es dem Aufruf der Facebook-Graph-API ermöglicht, Benutzerinformationen wie Standort, user_friends, Benutzer-E-Mail usw. abzurufen.

Wir müssen auch nachverfolgen, ob ein Benutzerkonto bei Facebook oder durch regelmäßige Anmeldung erstellt wird. Dazu fügen wir facebook_id zu unserem Benutzermodell hinzu.

 facebook_id = db.Column(db.String(100))

Das Facebook-Geheimnis wird über die env-Variablen FACEBOOK_SECRET konfiguriert, die wir zu app.config hinzufügen.

 app.config['FACEBOOK_SECRET'] = os.environ.get('FACEBOOK_SECRET')

Um also app.py zu starten, sollten Sie diese env-Variable festlegen:

 FACEBOOK_SECRET={your secret} python app.py

Hier ist die Methode, die Facebook-Anmeldungen handhabt. Standardmäßig ruft Satellizer den Endpunkt /auth/facebook auf.

 @app.route('/auth/facebook', methods=['POST']) def auth_facebook(): access_token_url = 'https://graph.facebook.com/v2.3/oauth/access_token' graph_api_url = 'https://graph.facebook.com/v2.5/me?fields=id,email' params = { 'client_id': request.json['clientId'], 'redirect_uri': request.json['redirectUri'], 'client_secret': app.config['FACEBOOK_SECRET'], 'code': request.json['code'] } # Exchange authorization code for access token. r = requests.get(access_token_url, params=params) # use json.loads instead of urlparse.parse_qsl access_token = json.loads(r.text) # Step 2. Retrieve information about the current user. r = requests.get(graph_api_url, params=access_token) profile = json.loads(r.text) # Step 3. Create a new account or return an existing one. user = User.query.filter_by(facebook_id=profile['id']).first() if user: return jsonify(token=user.token()) u = User(facebook_id=profile['id'], email=profile['email']) db.session.add(u) db.session.commit() return jsonify(token=u.token())

Um eine Anfrage an den Facebook-Server zu senden, verwenden wir das praktische Modul Anfragen. Jetzt ist der schwierige Teil am Backend erledigt. Am Frontend ist das Hinzufügen des Facebook-Logins ganz einfach. Zuerst müssen wir Satellizer unsere facebook_id mitteilen, indem wir diesen Code in die Funktion app.config einfügen :

 $authProvider.facebook({ clientId: {your facebook app id}, // by default, the redirect URI is http://localhost:5000 redirectUri: 'http://localhost:5000/static/index.html' });

Um sich über Facebook anzumelden, können wir einfach anrufen:

 $auth.authenticate(“facebook”)

Wie üblich können Sie den Code auf GitHub überprüfen

Zu diesem Zeitpunkt ist die Webapp funktional vollständig. Der Benutzer kann sich mit normaler E-Mail und Passwort oder über Facebook anmelden/registrieren. Einmal angemeldet, kann der Benutzer seine geheime Seite sehen.

Machen Sie eine hübsche Schnittstelle

Die Benutzeroberfläche ist an dieser Stelle nicht sehr hübsch, also fügen wir ein wenig Bootstrap für das Layout und das eckige Toastermodul hinzu, um eine Fehlermeldung gut zu behandeln, z. B. wenn die Anmeldung fehlschlägt.

Den Code für dieses Verschönerungsteil finden Sie hier.

Fazit

Dieser Artikel zeigt eine schrittweise Integration von Satellizer in eine (einfache) AngularJS-Webapp. Mit Satellizer können wir problemlos andere soziale Logins wie Twitter, Linkedin und mehr hinzufügen. Der Code auf dem Frontend ist ziemlich derselbe wie im Artikel. Das Back-End variiert jedoch, da SDKs für soziale Netzwerke unterschiedliche Endpunkte mit unterschiedlichen Protokollen haben. Sie können sich https://github.com/sahat/satellizer/blob/master/examples/server/python/app.py ansehen, das Beispiele für Facebook, Github, Google, Linkedin, Twiter und Bitbucket enthält. Im Zweifelsfall sollten Sie einen Blick in die Dokumentation auf https://github.com/sahat/satellizer werfen.

Verwandte: Ein-Klick-Anmeldung mit Blockchain: Ein MetaMask-Tutorial