たった 5 つの手順であなたのサイトに Persona のログインシステムを追加できます:
- Persona の JavaScript ライブラリをページに含める。
- ログインボタンとログアウトボタンを追加する。
- ログインとログアウトの操作を監視する。
- ユーザの信用情報を検証する。
- ベストプラクティスを見直す。
Persona は、半日もあればあなたのサイトに追加できます。ただし、重要なものから順番に行ってください: Persona をあなたのサイトで利用しようとするときは、その前に Persona notices メーリングリストを購読してください。メールのやりとりはとても少ないですが、あなたのサイトに悪影響を及ぼす可能性のある変更をアナウンスするために使われます。
ステップ 1: Persona ライブラリを含める
Persona は、ブラウザ中立で設計されており、すべての主要なデスクトップ版とモバイル版のブラウザ で動作します。
私たちは将来、ブラウザ群がPersonaに母国語の支援を提供するだろうと考えていますが、その間、私たちはユーザーインターフェースとクライアント側のプロトコルを全て備えたJavascriptのライブラリを提供します。
このライブラリが一度ページに読み込まれれば、必要な Persona 関数 (watch()
および request()
, logout()
) がグローバルな navigator.id
オブジェクトで利用可能になります。
Persona JavaScript ライブラリをページに含めるには、以下の script
タグをページのヘッダ(page bodyの末尾)に置いてください:
<script src="https://login.persona.org/include.js"></script>
このコードは、navigator.id
関数を使用するすべてのページに 含めなければなりません。なぜならPersona はまだ開発段階であり、include.js
ファイルをあなた自身でホストすべきではないからです。
互換性モードの制限
Personaを破綻させるため、Internet Explorerのユーザーが互換性モードを使用できないことも確認すべきです。以下をしてください。
すべてscript elementsの前に<meta http-equiv="X-UA-Compatible" content="IE=Edge">
をあなたのページに含める。- もしくはあなたのページに以下のHTTP ヘッダを設定する。
X-UA-Compatible: IE=Edge
.
For more information, see the notes in IE Compatibility Mode and "IE8 and IE9 Complications".
ステップ 2: ログインとログアウトのボタンを追加する
Persona は DOM API として設計されているため、ユーザがサイト上のログインまたはログアウトボタンをクリックした時に関数を呼び出さなければなりません。Persona ダイアログを開いてユーザがログインできるようにするには、navigator.id.request()
を呼び出します。ログアウトする時は navigator.id.logout()
を呼び出します。
Note, the call to logout()
must be made in the click handler of the logout button.
コード例:
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(); }; };
これらのボタンの外観については、ブランドリソース ページのボタン画像や CSS ベースのボタンをご利用ください。
ステップ 3: ログインとログアウトの操作を監視する
Persona を機能させるために、ユーザがログインまたはログアウトした時に何を行うかを知らせる必要があります。これは、navigator.id.watch()
関数に 3 個の引数を与えて呼び出すことにより行えます:
- コンピューターから現在あなたのサイトにログインしているユーザーのemailアドレス。ユーザがいない場合は
null
です。例えば、誰がサインインしているのか確かめるためにブラウザのCookieを調べることでしょう。 onlogin
操作のトリガーが引かれた時に呼び出す関数。この関数には、検証された「ID アサーション」の引数を 1 個渡します。onlogout
操作のトリガーが引かれた時に呼び出す関数。この関数には引数を渡しません。
注意: navigator.id.watch()
を呼び出した時は、常に onlogin
と onlogout
の両方を含めなければなりません。
例えば、あなたが"Bob"で現在あなたのサイトにログインしていると考える場合、次のように書きます:
var currentUser = '[email protected]'; navigator.id.watch({ loggedInUser: currentUser, onlogin: function(assertion) { // ユーザがログインしました! ここで必要なことは: // 1. 検証してセッションを作成するため、アサーションをバックエンドに送信する。 // 2. UI を更新する。 $.ajax({ /* <-- この例では jQuery を使いますが、他のものも使えます */ type: 'POST', url: '/auth/login', // これは、あなたの Web サイト上の URL です。 data: {assertion: assertion}, success: function(res, status, xhr) { window.location.reload(); }, error: function(res, status, xhr) { alert("login failure" + res); } }); }, onlogout: function() { // ユーザがログアウトしました! ここで必要なことは: // リダイレクトするかバックエンドの呼び出しを行って、ユーザのセッションを破棄する。 $.ajax({ type: 'POST', url: '/auth/logout', // これは、あなたの Web サイト上の URL です。 success: function(res, status, xhr) { window.location.reload(); }, error: function(res, status, xhr) { alert("logout failure" + res); } }); } });
このコード例では、非同期の POST
リクエストをサイトのバックエンドで行う onlogin
と onlogout
の両方が実装されています。バックエンドでは、セッション Cookie 内の情報を設定または削除することによりユーザのログインまたはログインが記録されます。そして、すべてが正しく一致したら、ページが再読み込みしてアカウントを新しいログイン状態にします。
もちろん、AJAX を用いて再読み込みやリダイレクトなしでこれを実装することもできますが、このチュートリアルでは扱いません。
もしID assertionが証明できなかったとき、navigator.id.logout()
を呼びだすべきことに注意してください。これはPersonaに現在誰もログインしていないことを教える働きがあり、それをしないと、Personaは同じassertionでonloginをまた直ちに呼び出し、それがendless loop of failed loginsにつながるかもしれません。
次の例を示します。今度は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 } );
すべてのページ上のログインボタンまたはログアウトボタンでnavigator.id.watch()を
呼び出さなければなりません。サイトのユーザのための、自動ログインやグローバルログアウトのような Persona の機能をサポートするには、この関数をあなたのサイトのすべてのページ上で 呼び出してください。
ステップ 4: ユーザの信用情報を検証する
Persona は、パスワードの代わりに「ID アサーション」を使います。これは、ユーザのメールアドレスに結び付けられた、一つのサイトで一回だけ使えるパスワードのようなものです。ユーザがログインしようとする時、このユーザからのアサーションと共に onlogin
コールバックが呼びされます。彼らをログインさせる前に、アサーションが正しいか検証しなければなりません。
アサーションを、ユーザのブラウザ上で実行している JavaScript ではなく、あなたのサーバ上で検証することは とても重要 です。ユーザのブラウザ上では簡単に偽造できてしまうからです。上記の例では、jQuery の $.ajax()
ヘルパーを使ってアサーションをサイトのバックエンドに手放し、/auth/login
に POST
しました。
あなたのサーバにアサーションが渡ったら、それをどのように検証したらよいでしょうか? 最も簡単な方法は、Mozilla が提供するヘルパーサービスを使うことです。単純にアサーションを 2 個の引数と共に https://verifier.login.persona.org/verify
に POST
するだけです:
assertion
: ユーザにより提供された ID アサーション。audience
: あなたの Web サイトのホスト名とポート番号。この値はバックエンドに直接記述してください。ユーザから与えられたいかなるデータも、この引数に渡してはいけません。
例えば、example.com
というサイトの場合、コマンドラインで次のようにアサーションをテストできます:
$ curl -d "assertion=<ASSERTION>&audience=https://example.com:443" "https://verifier.login.persona.org/verify"
値が正しければ、次のような JSON レスポンスが返ります:
{ "status": "okay", "email": "[email protected]", "audience": "https://example.com:443", "expires": 1308859352261, "issuer": "eyedee.me" }
検証サービスについては、Verification Service API をお読みください。/auth/login
の実装例と Python を使った Flask Web フレームワーク、Requests HTTP ライブラリは次のようになります:
@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) # 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)
他の言語でPersonaを使う例はcookbook.を参照してください。
セッション管理は、既存のログインシステムとよく似ているでしょう。最初の大きな変更は、パスワードを確認する代わりにアサーションを確認してユーザの ID を検証することです。他の大きな変更は、ユーザのメールアドレスが利用可能であることを、navigator.id.watch()
に loggedInUser
引数を渡して確認することです。
ログアウトは簡単です: 必要なことは、ユーザのセッション Cookie を削除するだけです。
ステップ 5: ベストプラクティスを見直す
すべての動作が確認でき、あなたのサイトへのログインとログアウトが成功したら、Persona を安全に安心して使うための ベストプラクティス を見直してください。
製品レベルのサイトを制作している場合は、Persona を使ったユーザのログインとログアウトをシミュレートするインテグレーションテストを書きたいでしょう。これを Selenium で容易に行うために、bidpom ライブラリの使用を考慮してください。mockmyid.com と personatestuser.org のサイトも役立つでしょう。
最後に、セキュリティの問題や Persona API の後方互換性に関わる変更を知るために、Persona notices メーリングリストにサインアップすることを忘れないでください。このメーリングリストのやりとりはとても少ないですが、あなたのサイトに悪影響を及ぼす可能性のある変更をアナウンスするために使われます。