遠端驗證 API

概覽

當使用者嘗試登入至網站時,瀏覽器會產生一名為「斷言」的資料結構,其實質上就是一個加密過的電子郵件位置。瀏覽器傳送這個斷言至網站上,使用者登入前,網站必須驗證斷言的有效性。

斷言可以在本地端或是通過在下列位置的 API 來進行驗證:https://verifier.login.persona.org/verify。這個頁面介紹了如何使用 API 。

方法

HTTP POST 請求至 https://verifier.login.persona.org/verify

參數

assertion
使用者所提供之斷言。作為傳入 navigator.id.watch()onlogin 函數的第一個參數。
audience
您網站的通訊協定、網域名稱、與通訊埠。例如:「https://example.com:443

回傳值

呼叫後會傳統一個包含 status 元素的 JSON 結構,其值可能為「okay」或是「failure」。 依據 status 的值的不同,可能會包含下列表中的額外元素。

"okay"

該斷言有效。

在這種情況下,JSON 結構會包含下列附加元素:

"email" 斷言中包含的登入者的郵件位置。
"audience" Audience 的值包含了斷言。Expected to be your own website URL.
"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"

該斷言無效。這種情況下 JSON 結構將會包含一個附加的元素:

"reason" 一字串解釋驗證為何失敗。

範例

node.js

該範例為使用 express.js 的 Node.js 伺服器。

var express = require("express"),
    app = express.createServer(),
    https = require("https"),
    querystring = require("querystring");
/* ... */

// Audience 必須符合您瀏覽器的位置列上顯示的,
// 包含通訊協定、主機名稱、以及通訊埠。
var audience = "http://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
);
//使用 $_POST 超全域陣列供 PHP < 5.2 並撰寫您自己的篩選其
$params = 'assertion=' . urlencode($assert) . '&audience=' .
           urlencode('http://example.com:80');
$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;

Via Christian Heilmann

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

 

注意: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.

Document Tags and Contributors

最近更新: teoli,