aboutsummaryrefslogtreecommitdiff
path: root/files/it/archive/mozilla/persona/quick_setup/index.html
blob: 076e004ca191227f7b4a166467594fef78594002 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
---
title: Setup veloce
slug: Archive/Mozilla/Persona/Quick_Setup
translation_of: Archive/Mozilla/Persona/Quick_Setup
---
<p>Aggiungere il sistema di login Persona al tuo sito richiede solo cinque passaggi:</p>

<ol>
 <li>Includere la libreria JavaScript di Persona nelle tue pagine.</li>
 <li>Aggiungere i bottoni di “login” e “logout”.</li>
 <li>Watch for login and logout actions.</li>
 <li>Verificare le credenziali dell'utente.</li>
 <li>Rivedere le best practices.</li>
</ol>

<p>Dovresti riuscire a implementarlo e farlo funzionare in un solo pomeriggio, ma innanzitutto: se hai intenzione di usare Persona sul tuo sito, <em>per piacere</em> prendi un momento per sottoscrivere la mailing list <a href="https://mail.mozilla.org/listinfo/persona-notices">Persona notices</a>. Genera un traffico estremamente basso, viene solo usata per annunciare cambiamenti o questioni di sicurezza che potrebbero avere un impatto negativo sul tuo sito.</p>

<h2 id="Step_1_Includi_la_libreria_di_Persona">Step 1: Includi la libreria di Persona</h2>

<p>Persona é progettato per essere indipendente dal browser e funzionare bene su <a href="https://developer.mozilla.org/docs/persona/Browser_compatibility">tutti i maggiori browser per desktop e mobile</a>.</p>

<p>Ci aspettiamo che in futuro i browser supporteranno nativamente Persona, ma nel frattempo forniamo una libreria JavaScript che implementa completamente l'interfaccia utente e la parte client-side del protocollo. Includendo questa libreria, i tuoi utenti saranno in grado di registrarsi con Persona anche se il loro browser non lo supporta nativamente.</p>

<p>Questa libreria è caricata nella tua pagina, Persona funziona necessita di ({{ domxref("navigator.id.watch()", "watch()") }}, {{ domxref("navigator.id.request()", "request()") }}, and {{ domxref("navigator.id.logout()", "logout()") }}) sarà disponibile al mondo navigator.id object.</p>

<p>Includere la libreria JavaScript di Persona, tu puoi mettere questo script tag in fondo al <code>body</code> della pagina:</p>

<pre class="brush: html;">&lt;script src="https://login.persona.org/include.js"&gt;&lt;/script&gt;
</pre>

<p><strong>Devi</strong> includere questo script in ogni pagina dove gli utenti utilizzeranno Persona {{ domxref("navigator.id") }}. Ciò perchè Persona è ancora in svilippo, tu non dovresti auto accogliere il file <code>include.js</code></p>

<h2 id="Step_2_Aggiungere_il_bottone_di_login_e_di_logout">Step 2: Aggiungere il bottone di login e di logout</h2>

<p>Because Persona is designed as a DOM API, you must call functions when a user clicks a login or logout button on your site. To open the Persona dialog and prompt the user to log in, you should invoke {{ domxref("navigator.id.request()") }}. For logout, invoke {{ domxref("navigator.id.logout()") }}. Note, the call to {{ domxref("navigator.id.logout()", "logout()") }} <em>must</em> be made in the click handler of the logout button.</p>

<p>For example:</p>

<pre class="brush: js;">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(); };
}
</pre>

<p>What should those buttons look like? Check out our <a href="https://developer.mozilla.org/docs/persona/branding">Branding Resources</a> page for premade images and CSS-based buttons!</p>

<h2 id="Step_3_Watch_for_login_and_logout_actions">Step 3: Watch for login and logout actions</h2>

<p>For Persona to function, you need to tell it what to do when a user logs in or out. This is done by calling the {{ domxref("navigator.id.watch()") }} function and supplying three parameters:</p>

<ol>
 <li>
  <p>The email address of the user currently logged into your site from this computer, or <code>null</code> if no one is logged in. For example, you might examine the browser's cookies to determine who is signed in.</p>
 </li>
 <li>
  <p>A function to invoke when an <code>onlogin</code> action is triggered. This function is passed a single parameter, an “identity assertion,” which must be verified.</p>
 </li>
 <li>
  <p>A function to invoke when an <code>onlogout</code> action is triggered. This function is not passed any parameters.</p>
 </li>
</ol>

<div class="note style-wrap">
<p><strong>Note:</strong> You must always include both <code>onlogin</code> and <code>onlogout</code> when you call {{ domxref("navigator.id.watch()") }}.</p>
</div>

<p>For example, if you currently think Bob is logged into your site, you might do this:</p>

<pre class="brush: js;">var currentUser = 'bob@example.com';

navigator.id.watch({
  loggedInUser: currentUser,
  onlogin: function(assertion) {
    // A user has logged in! Here you need to:
    // 1. Send the assertion to your backend for verification and to create a session.
    // 2. Update your UI.
    $.ajax({ /* &lt;-- 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) { 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); }
    });
  }
});
</pre>

<p>In this example, both <code>onlogin</code> and <code>onlogout</code> are implemented by making an asynchronous <code>POST</code> 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.</p>

<p>You can, of course, use AJAX to implement this without reloading or redirecting, but that’s beyond the scope of this tutorial.</p>

<p>Here is another example, this time not using jQuery.</p>

<pre class="brush: js;">function simpleXhrSentinel(xhr) {
    return function() {
        if (xhr.readyState == 4) {
            if (xhr.status == 200)
                // reload page to reflect new login state
                window.location.reload();
            else
                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 http://www.openjs.com/articles/ajax_xmlhttp_using_post.php
    var param = "assert="+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 } );
</pre>

<p>You <strong>must</strong> call <code>navigator.id.watch()</code> on every page with a login or logout button. To support Persona enhancements like automatic login and global logout for your users, you <strong>should</strong> call this function on every page of your site.</p>

<p>Persona will compare the email address you've passed into <code>loggedInUser</code> 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 <code>onlogin</code> or <code>onlogout</code> on page load.</p>

<p> </p>

<h2 id="Step_4_Verify_the_user’s_credentials">Step 4: Verify the user’s credentials</h2>

<p>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 <code>onlogin</code> callback will be invoked with an assertion from that user. Before you can log them in, you must verify that the assertion is valid.</p>

<p>It’s <em>extremely important</em> 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 <code>$.ajax()</code> helper to <code>POST</code> it to <code>/auth/login</code>.</p>

<p>Once your server has an assertion, how do you verify it? The easiest way is to use a helper service provided by Mozilla. Simply <code>POST</code> the assertion to <code>https://verifier.login.persona.org/verify</code> with two parameters:</p>

<ol>
 <li><code>assertion</code>: The identity assertion provided by the user.</li>
 <li><code>audience</code>: 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.</li>
</ol>

<p>For example, if you’re <code>example.com</code>, you can use the command line to test an assertion with:</p>

<pre class="brush: bash;">$ curl -d "assertion=&lt;ASSERTION&gt;&amp;audience=https://example.com:443" "https://verifier.login.persona.org/verify"
</pre>

<p>If it’s valid, you’ll get a JSON response like this:</p>

<pre class="brush: js;">{
  "status": "okay",
  "email": "bob@eyedee.me",
  "audience": "https://example.com:443",
  "expires": 1308859352261,
  "issuer": "eyedee.me"
}
</pre>

<p>You can learn more about the verification service by reading <a href="https://developer.mozilla.org/en-US/docs/BrowserID/Remote_Verification_API">The Verification Service API</a>. An example <code>/api/login</code> implementation, using <a href="http://python.org/">Python</a>, the <a href="http://flask.pocoo.org/">Flask</a> web framework, and the <a href="http://python-requests.org">Requests</a> HTTP library might look like this:</p>

<pre class="brush: python;">@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 resp.content

    # Oops, something failed. Abort.
    abort(500)
</pre>

<p>For an example on how to use Persona in a C# ASP.Net MVC3 application, <a href="https://github.com/sergiotapia/ASP.Net-MVC3-Persona-Demo" title="https://github.com/sergiotapia/ASP.Net-MVC3-Persona-Demo">visit this application demo</a> or see the Controller code below:</p>

<p> </p>

<pre class="brush:java;">public class AuthController : Controller
{
    [HttpPost]
    public ActionResult Login(string assertion)
    {
        if (assertion == null)
        {
            // The 'assertion' key of the API wasn't POSTED. Redirect,
            // or whatever you'd like, to try again.
            return RedirectToAction("Index", "Home");
        }

        using (var web = new WebClient())
        {
            // Build the data we're going to POST.
            var data = new NameValueCollection();
            data["assertion"] = assertion;
            data["audience"] = "https://example.com:443"; // Use your website's URL here.


            // POST the data to the Persona provider (in this case Mozilla)
            var response = web.UploadValues("https://verifier.login.persona.org/verify", "POST", data);
            var buffer = Encoding.Convert(Encoding.GetEncoding("iso-8859-1"), Encoding.UTF8, response);


            // Convert the response to JSON.
            var tempString = Encoding.UTF8.GetString(buffer, 0, response.Length);
            var reader = new JsonReader();
            dynamic output = reader.Read(tempString);

            if (output.status == "okay")
            {
                string email = output.email; // Since this is dynamic, convert it to string.
                FormsAuthentication.SetAuthCookie(email, true);
                return RedirectToAction("Index", "Home");
            }

            // Could not log in, do something else.
            return RedirectToAction("Index", "Home");
        }
    }
}</pre>

<p>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 <code>loggedInEmail</code> parameter to {{ domxref("navigator.id.watch()") }}.</p>

<p>Logout is simple: you just need to remove the user’s session cookie.</p>

<h2 id="Step_5_Review_best_practices">Step 5: Review best practices</h2>

<p>Once everything works and you’ve successfully logged into and out of your site, you should take a moment to review <a href="https://developer.mozilla.org/docs/BrowserID/Security_Considerations">best practices</a> for using Persona safely and securely.</p>

<p>If you're making a production-ready site, you may want to write integration tests that simulate logging a user in and out of your site using Persona. To facilitate this action in Selenium, consider using the <a href="https://github.com/mozilla/bidpom" title="https://github.com/mozilla/bidpom">bidpom</a> library. The sites <a href="https://mockmyid.com/" title="https://mockmyid.com/">mockmyid.com</a> and <a href="http://personatestuser.org" title="http://personatestuser.org">personatestuser.org</a> may also be helpful.</p>

<p>Lastly, don’t forget to sign up for the <a href="https://mail.mozilla.org/listinfo/persona-notices">Persona notices</a> 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.</p>

<p> </p>