This article needs a technical review. How you can help.
Persona is no longer actively developed by Mozilla. Mozilla has committed to operational and security support of the persona.org services until November 30th, 2016.
On November 30th, 2016, Mozilla will shut down the persona.org services. Persona.org and related domains will be taken offline.
If you run a website that relies on Persona, you need to implement an alternative login solution for your users before this date.
For more information, see this guide to migrating your site away from Persona:
https://wiki.mozilla.org/Identity/Persona_Shutdown_Guidelines_for_Reliers
Summary
When a user tries to log into a website, their browser generates a data structure called an assertion, which is essentially a cryptographically signed email address. The browser sends this assertion to the website, which must verify that the assertion is valid before logging the user in.
Assertions can be verified locally, or with an API hosted at https://verifier.login.persona.org/verify
. This page describes how to use the API.
Method
HTTP POST request to https://verifier.login.persona.org/verify
.
Parameters
assertion
- The assertion supplied by the user. Available as the first parameter passed to the
onlogin
function innavigator.id.watch()
. audience
- The protocol, domain name, and port of your site. For example, "
https://example.com:443
".
Return values
The call returns a JSON structure containing a status
element, which may be either "okay" or "failure". Depending on the value of status
, the structure contains additional elements listed below.
"okay"
The assertion is valid.
In this case the JSON structure contains the following additional elements:
"email " |
The address contained in the assertion, for the intended person being logged in. |
"audience " |
The audience value contained in the assertion. Expected to be your own website URL. |
"expires " |
The date the assertion expires, expressed as the primitive value of a Date object: that is, the number of milliseconds since midnight 01 January, 1970 UTC. |
"issuer " |
The hostname of the identity provider that issued the assertion. |
"failure"
The assertion is invalid. In this case, the JSON structure contains one additional element:
"reason" |
A string explaining why verification failed. |
Examples
node.js
This example uses a node.js server using express.js
var express = require("express"), app = express.createServer(), https = require("https"), querystring = require("querystring"); /* ... */ // The audience must match what your browser's address bar shows, // including protocol, hostname, and port var audience = "https://localhost:8888"; app.post("/authenticate", function(req, res) { var vreq = https.request({ host: "verifier.login.persona.org", path: "/verify", method: "POST" }, function(vres) { var body = ""; vres.on('data', function(chunk) { body+=chunk; } ) .on('end', function() { try { var verifierResp = JSON.parse(body); var valid = verifierResp && verifierResp.status === "okay"; var email = valid ? verifierResp.email : null; req.session.email = email; if (valid) { console.log("assertion verified successfully for email:", email); res.json(email); } else { console.log("failed to verify assertion:", verifierResp.reason); res.send(verifierResp.reason, 403); } } catch(e) { console.log("non-JSON response from verifier"); // bogus response from verifier! res.send("bogus response from verifier!", 403); } }); }); vreq.setHeader('Content-Type', 'application/x-www-form-urlencoded'); var data = querystring.stringify({ assertion: req.body.assertion, audience: audience }); vreq.setHeader('Content-Length', data.length); vreq.write(data); vreq.end(); console.log("verifying assertion!"); });
via Lloyd Hilaiel
PHP
$url = 'https://verifier.login.persona.org/verify'; $assert = filter_input( INPUT_POST, 'assertion', FILTER_UNSAFE_RAW, FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH ); //Use the $_POST superglobal array for PHP < 5.2 and write your own filter $params = 'assertion=' . urlencode($assert) . '&audience=' . urlencode('https://localhost:8888'); $ch = curl_init(); $options = array( CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => TRUE, CURLOPT_POST => 2, //CURLOPT_SSL_VERIFYPEER => true, //This currently blocks connection to 'https://verifier.login.persona.org/verify' CURLOPT_SSL_VERIFYPEER => 0, CURLOPT_SSL_VERIFYHOST => 2, CURLOPT_POSTFIELDS => $params ); curl_setopt_array($ch, $options); $result = curl_exec($ch); curl_close($ch); echo $result;
Java
@Override protected void doPost(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException { final String audience = req.getServerName(); final String assertion = req.getParameter("assertion"); final Verifier verifier = new Verifier(); final BrowserIDResponse personaResponse = verifier.verify(assertion,audience); final Status status = personaResponse.getStatus(); if (status == Status.OK) { /* Authentication with Persona was successful */ String email = personaResponse.getEmail(); log.info("{} has sucessfully signed in", email); HttpSession session = req.getSession(true); session.setAttribute("email", email); } else { /* Authentication with Persona failed */ log.info("Sign in failed..."); } }
Via Javier
Note: If you send the assertion and audience parameters as a JSON-object, they must not be URL-encoded. If they are sent as regular HTTP POST parameters, as in the example above, they must be URL-encoded.