Sie benötigen nur 5 Schritte um Persona ihrer Webseite hinzuzufügen:
- Binden Sie die Persona JavaScript Bibliothek in ihre Webseite ein.
- Fügen Sie jeweils einen "Login" und "Logout" Button hinzu.
- Achten Sie auf die Aktionen der Nutzer.
- Überprüfen Sie die Informationen des Nutzers.
- Beachten Sie die Informationen für Sicheres Einbinden.
Sie sollten in der Lage sein, Persona an einem einzigen Nachmittag zu implementieren. Zuvor sollten Sie sich allerdings in den Persona notices Newsletter eintragen. Der Newsletter versendet nur sicherheitsrelevante E-Mails.
Schritt 1: Einbinden der Persona Bibliothek
Persona ist Browser-neutral programmiert und unterstützt alle großen Desktop- und Mobilbrowser.
Wir erwarten für die Zukunft, dass die Browser Persona direkt und ohne externe Bibliothek unterstützten. Solange dies nicht der Fall ist, stellen wir eine JavaScript Bibliothek bereit, die die Benutzeroberfläche und den Client-seitigen Teil des Persona-Protokolls übernimmt. Durch die Einbindung dieser Bibliothek kann sich jeder Nutzer anmelden, egal, ob sein Browser Persona direkt unterstützt, oder nicht.
Sobald die Bibliothek in der Seite geladen ist, sind die Persona Funktionen (watch()
, request()
, und logout()
) im globalen navigator.id
Knoten vorhanden.
Um die Persona JavaScript Bibliothek einzubinden plazieren Sie diesen script
Tag am Ende der HTML-Seite:
<script src="https://login.persona.org/include.js"></script>
Sie müssen dies am Ende jeder Seite einfügen, die navigator.id
benutzen soll. Da sich Persona immer noch in der Entwicklung befindet, sollten Sie die Persona include.js
Datei nicht selber bereitstellen.
Unterdrückung des Kompatibilitätsmodus
Damit Persona auch im Internet Explorer funktioniert, sollten Sie dessen Kompatibilitätsmodus unterdrücken. Dies kann auf zwei Wegen geschehen:
- entweder fügen Sie auf ihrer Seite noch vor dem ersten Skript Element ein :
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
- oder aber Sie liefern diesen HTTP-Kopf mit aus:
X-UA-Compatible: IE=Edge
.
Für weitere Informationen schauen Sie bitte bei IE Compatibility Mode und "IE8 and IE9 Complications" vorbei.
Schritt 2: Hinzufügen der Login und Logout Buttons
Da Persona als Bestandteil der DOM API entwickelt wurde, müssen Sie Funktionen ausführen, sobald ein Nutzer auf einen der beiden Button klickt. Um den Anmelden Dialog auszuführen, sollten sie navigator.id.request()
aufrufen. Für den Logout starten Sie bitte navigator.id.logout()
. Notiz: Der Aufruf von logout()
muss in dem Click-Handler des Logout-Buttons ausgeführt werden.
Als Beispiel:
var signinLink = document.getElementById('signin'); if (signinLink) { signinLink.onclick = function() { navigator.id.request(); }; } var signoutLink = document.getElementById('signout'); if (signoutLink) { signoutLink.onclick = function() { navigator.id.logout(); }; }
Wie sollten diese Buttons aussehen? Betrachte unsere Branding Resources Seite für vorgefertigte Persona-Bilder und CSS-basierte Buttons.
Schritt 3: Warte auf Login und Logout Aktionen
Damit Persona funktioniert, musst du ihm mitteilen, wenn sich ein Nutzer an- bzw. abmeldet. Dies geschieht durch Übergabe dreier Parameter an die Funktion navigator.id.watch()
. Die drei Parameter sind:
-
Die E-Mail Adresse des momentan angemeldeten Nutzers, oder aber, wenn niemand angemeldet ist
null
Beispielsweise kannst du den Cookie auslesen, um herauszufinden, wer angemeldet ist. -
Eine Funktion für den Fall, dass
onlogin
ausgelöst wird. This function is passed a single parameter, an “identity assertion,” which must be verified. -
Eine Funktion, die aufzurufen ist, wenn
onlogout
ausgelöst wird. Dieser Funktion werden keine Parameter mitgegeben.
Beachte: Sie müssen immer beide, onlogin
und onlogout
übergeben, wenn Sie navigator.id.watch()
aufrufen.
Wenn beispielsweise Bob angemeldet ist, müssen Sie folgendes tun:
var currentUser = '[email protected]'; navigator.id.watch({ loggedInUser: currentUser, onlogin: function(assertion) { // Ein Nutzer hat sich angemeldete. Hier müssen Sie: // 1. Send the assertion to your backend for verification and to create a session. // 2. Aktualisiere die Oberfläche $.ajax({ /* <-- This example uses jQuery, but you can use whatever you'd like */ type: 'POST', url: '/auth/login', // This is a URL on your website. data: {assertion: assertion}, success: function(res, status, xhr) { window.location.reload(); }, error: function(xhr, status, err) { navigator.id.logout(); alert("Login failure: " + err); } }); }, onlogout: function() { // A user has logged out! Here you need to: // Tear down the user's session by redirecting the user or making a call to your backend. // Also, make sure loggedInUser will get set to null on the next page load. // (That's a literal JavaScript null. Not false, 0, or undefined. null.) $.ajax({ type: 'POST', url: '/auth/logout', // This is a URL on your website. success: function(res, status, xhr) { window.location.reload(); }, error: function(xhr, status, err) { alert("Logout failure: " + err); } }); } });
In this example, both onlogin
and onlogout
are implemented by making an asynchronous POST
request to your site’s backend. The backend then logs the user in or out, usually by setting or deleting information in a session cookie. Then, if everything checks out, the page reloads to take into account the new login state.
Note that if the identity assertion can't be verified, you should call navigator.id.logout()
: this has the effect of telling Persona that none is currently logged in. If you don't do this, then Persona may immediately call onlogin again with the same assertion, and this can lead to an endless loop of failed logins.
You can, of course, use AJAX to implement this without reloading or redirecting, but that’s beyond the scope of this tutorial.
Here is another example, this time not using jQuery.
function simpleXhrSentinel(xhr) { return function() { if (xhr.readyState == 4) { if (xhr.status == 200){ // reload page to reflect new login state window.location.reload(); } else { navigator.id.logout(); alert("XMLHttpRequest error: " + xhr.status); } } } } function verifyAssertion(assertion) { // Your backend must return HTTP status code 200 to indicate successful // verification of user's email address and it must arrange for the binding // of currentUser to said address when the page is reloaded var xhr = new XMLHttpRequest(); xhr.open("POST", "/xhr/sign-in", true); // see https://www.openjs.com/articles/ajax_xmlhttp_using_post.php var param = "assertion="+assertion; xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.setRequestHeader("Content-length", param.length); xhr.setRequestHeader("Connection", "close"); xhr.send(param); // for verification by your backend xhr.onreadystatechange = simpleXhrSentinel(xhr); } function signoutUser() { // Your backend must return HTTP status code 200 to indicate successful // sign out (usually the resetting of one or more session variables) and // it must arrange for the binding of currentUser to 'null' when the page // is reloaded var xhr = new XMLHttpRequest(); xhr.open("GET", "/xhr/sign-out", true); xhr.send(null); xhr.onreadystatechange = simpleXhrSentinel(xhr); } // Go! navigator.id.watch( { loggedInUser: currentUser, onlogin: verifyAssertion, onlogout: signoutUser } );
You must call navigator.id.watch()
on every page with a login or logout button. To support Persona enhancements like automatic login and global logout for your users, you should call this function on every page of your site.
Persona will compare the email address you've passed into loggedInUser
with its own knowledge of whether a user is currently logged in, and who they are. If these don't match, it may automatically invoke onlogin
or onlogout
on page load.
Step 4: Verify the user’s credentials
Instead of passwords, Persona uses “identity assertions,” which are kind of like single-use, single-site passwords combined with the user’s email address. When a user wants to log in, your onlogin
callback will be invoked with an assertion from that user. Before you can log them in, you must verify that the assertion is valid.
It’s extremely important that you verify the assertion on your server, and not in JavaScript running on the user’s browser, since that would be easy to forge. The example above handed off the assertion to the site’s backend by using jQuery’s $.ajax()
helper to POST
it to /auth/login
.
Once your server has an assertion, how do you verify it? The easiest way is to use a helper service provided by Mozilla. Simply POST
the assertion to https://verifier.login.persona.org/verify
with two parameters:
assertion
: The identity assertion provided by the user.audience
: The hostname and port of your website. You must hardcode this value in your backend; do not derive it from any data supplied by the user.
For example, if you’re example.com
, you can use the command line to test an assertion with:
$ curl -d "assertion=<ASSERTION>&audience=https://example.com:443" "https://verifier.login.persona.org/verify"
If it’s valid, you’ll get a JSON response like this:
{ "status": "okay", "email": "[email protected]", "audience": "https://example.com:443", "expires": 1308859352261, "issuer": "eyedee.me" }
You can learn more about the verification service by reading The Verification Service API. An example /auth/login
implementation, using Python, the Flask web framework, and the Requests HTTP library might look like this:
@app.route('/auth/login', methods=['POST']) def login(): # The request has to have an assertion for us to verify if 'assertion' not in request.form: abort(400) # Send the assertion to Mozilla's verifier service. data = {'assertion': request.form['assertion'], 'audience': 'https://example.com:443'} resp = requests.post('https://verifier.login.persona.org/verify', data=data, verify=True) # Did the verifier respond? if resp.ok: # Parse the response verification_data = json.loads(resp.content) # Check if the assertion was valid if verification_data['status'] == 'okay': # Log the user in by setting a secure session cookie session.update({'email': verification_data['email']}) return 'You are logged in' # Oops, something failed. Abort. abort(500)
For examples of how to use Persona in other languages, have a look at the cookbook.
The session management is probably very similar to your existing login system. The first big change is in verifying the user’s identity by checking an assertion instead of checking a password. The other big change is ensuring that the user’s email address is available for use as the loggedInUser
parameter to navigator.id.watch()
.
Logout is simple: you just need to remove the user’s session cookie.
Step 5: Review best practices
Once everything works and you’ve successfully logged into and out of your site, you should take a moment to review best practices for using Persona safely and securely.
If you're making a production site, have a look at the implementor's guide, where we've collected tips for adding the kind of features often needed in real-world login systems.
Lastly, don’t forget to sign up for the Persona notices mailing list so you’re notified of any security issues or backwards incompatible changes to the Persona API. The list is extremely low traffic: it’s only used to announce changes which may adversely impact your site.