OPとして動作するSKIPのコードを読む
OPとして動作するために必要な実装は、RPを実現するのに比べて非常に複雑です。認証情報を管理するだけでなく、多くの処理が必要となります。
今回は、正常系の流れの中でも、SKIP独自の部分を中心に見ていくことで全体像をつかみましょう。
SKIPのOP部分は、masqueradeというRailsで作られたオープンソースのOP実装のソースコードを参考に実装しました。このmasqueradeというアプリケーションは、OpenID ver2.0のプロバイダとしての基本機能を備えているもので、そこから必要な部分を切り出しながらSKIPのOP実装は行いました。
関連リンク: | |
masquerade http://github.com/dbloete/masquerade/ |
OPとしての動作の流れは、前節のSKIPをRPで動作させた場合と同じになります。その流れの中の、例えばmixiが行ったOPの部分を、SKIPで作り込んだと考えてください。
任意のRPで認証を求められた際に、OPであるSKIPにリダイレクトされてきますので、自前で管理しているユーザー情報を基に認証処理を行うためのログイン画面の表示を行います。
ユーザーからのログインのアクションを受けて認証処理を行った後は、適切な認証情報をパラメータに付与した上で、元のRPにリダイレクトして戻す、というのが詳しい流れになります。その部分だけをまとめると以下のようになります。
- RPは、OPであるSKIPの認証処理のためのURL(エンドポイントと呼ばれます)にリダイレクトする
- OPであるSKIPで、すでにログイン済みなら後処理(4)へ、ログイン前ならログイン画面(3)へリダイレクトする
- ログイン画面を表示してユーザーからのログインを処理した後、後処理(4)へリダイレクトする
- 認証を要求した元のRPへ、適切な認証情報を付与した上でリダイレクトする
何度かリダイレクトを繰り返しますが、ユーザーからの受け付けはログイン画面でのログイン処理のみとなります。同一Webブラウザ上で、すでにOPでログイン済みの場合、ユーザーはログインが不要になります。この流れで順にソースコードを追っていきましょう。
まず1つ目のRPからのリダイレクト処理ですが、この際にRP側はOPのどのURLにリダイレクトすれば良いか分かりません。
利用者が入力もしくは選択するのは、利用者自身をユニークに識別するOpenID Identifierか、どのOPを使うかということを識別するOP Identifier(例えばhttp://mixi.jp)か、のいずれかだけです。
前者は利用者にひも付くURL、後者はOPにひも付くURLになってはいますが、そのURLがリダイレクト先とは限りません。エンドポイントとなるURLが分かっていない状態からスタートするのです。
OpenID ver2.0からは、エンドポイント情報をXRDSと呼ばれるXMLを使ってOPが提供することになっています。XRDSのXMLデータを取得できるためのURIが必要になりますが、それはOP Identifierにリクエストした場合のHTTPレスポンスヘッダに含まれるX-XRDS-Locationというパラメータで指定されます。
OP側の実装は、これらに対する準備が必要となります。例えば、XRDSのURIを指定している部分のソースコードは以下になります。
25 |
def index |
26行目がXRDSの位置の指定をしている部分です。/server.xrdsというURIを代入して返すようにしています。次に、そのURIにアクセスした場合に実行されるソースコードを見てみましょう。
35 |
def index |
servers_controller.rbのindexメソッドの拡張子がxrdsの場合の処理は47〜49行目です。単純にビューに処理を渡しているだけです。対応するビューapp/views/server/index.xrds.builderの中でXRDS形式のXMLを生成して返すようになっており、そのXRDSの中で最初のRPからOPへのリダイレクト先となるエンドポイントのURIが提示されています。
SKIPの場合は、/serverになります。つまり、上記のservers_controller.rbのindexメソッドということになります。このindexメソッドが、拡張子によって2つの意味合いの違う処理を実装しているため複雑になっていますが、RPからOPへリダイレクトされた時に最初に実行されるのは、このindexメソッドということになります。
正しい認証リクエストの場合は、40行目のhandle_checkid_requestが実行されます。そのメソッドを見てみましょう。
89 |
def handle_checkid_request |
このhandle_checkid_requestメソッドでは、ログイン状態に応じてリダイレクト先を判別します。すでに同一Webブラウザでログインが済んでいる場合は、すぐに後処理のURLにリダイレクトしています(92行目)。ログインがまだの場合は、ログイン画面にリダイレクトしています(97行目)。ログイン画面へリダイレクトする際には、ログイン後の戻り先のURLに後処理のURLを指定しています。
ログイン画面とその処理は非常にシンプルなので割愛して、ログイン後の処理のメソッドを見てみましょう。
61 |
def proceed |
proceedメソッドでは、63行目から67行目でホワイトリストとして登録されているRPに対しては情報を付加してリダイレクトを行っています。ホワイトリストに登録されていないRPの場合は、73、74行目のように許可されていないというメッセージを表示し、SKIPのマイページに遷移するという処理を行ないます。
このホワイトリストによる特定RPへの認証情報を許可する方式がSKIP独自の拡張になっています。ユーザーごとにアプリケーションへの認証情報の引き渡しの許可を確認するようにしてしまうと、社内利用者にとっては操作が煩雑になってしまう点を解決できます。
また、社内管理者の意図しないアプリケーションで、社員用のSKIPをOPとして使われるのを防ぐために、SKIPの管理者だけが認証情報の引き渡しを許可するアプリケーションをホワイトリストという形で管理するようにしました。
これによって、利用者はOpenIDを利用していることを意識させないような擬似的なシングルサインオンを実現することができました。
今回は、比較的新しい技術であるOpenIDをSKIPの中でどのように応用して実装しているかという部分をコードリーディングするという実践的な内容になりました。本記事内で紹介した以外のソースコードも読むことでOpenIDの仕様そのものについての理解も深まることでしょう。
次回は、SKIPの大きな特徴の1つでもある、閲覧権限を含めたコンテンツ全体からのユニバーサル検索を可能にした、全文検索エンジン「HyperEstraier」との連携について解説する予定です。
3/3 |
Index | |
OpenIDを実装したソースコードを読もう | |
Page1 OpenIDでWebの認証を便利に実現 OpenIDについて SKIPバージョン1.1リリースしました! |
|
Page2 RPとして動作するSKIPのコードを読む SKIPにおけるRPの活用シーンと独自の拡張 |
|
Page3 OPとして動作するSKIPのコードを読む |
Railsコードリーディング 〜scaffoldのその先へ〜 |
Ruby/Rails関連記事 |
プログラミングは人生だ まつもと ゆきひろのコーディング天国 ときにプログラミングはスポーツであり、ときにプログラミングは創造である。楽しいプログラミングは人生をより実りあるものにしてくれる |
|
生産性を向上させるRuby向け統合開発環境カタログ Ruby on Rails 2.0も強力サポート 生産性が高いと評判のプログラミング言語「Ruby」。統合開発環境を整えることで、さらに効率的なプログラミングが可能になる |
|
かんたんAjax開発をするためのRailsの基礎知識 Ruby on RailsのRJSでかんたんAjax開発(前編) 実はAjaxアプリケーション開発はあなたが思うよりも簡単です。まずはRuby on Railsの基礎知識から学びましょう |
|
Praggerとnetpbmで作る画像→AA変換ツール Rubyを使って何か面白いものを作ってみよう! 一般的な画像をアスキーアートに変換するツールを作ってみる。さらに出力にバリエーションを持たせてみよう |
|
コードリーディングを始めよう Railsコードリーディング〜scaffoldのその先へ〜(1) 優れたプログラマはコードを書くのと同じくらい、読みこなす。優れたコードを読むことで自身のスキルも上達するのだ |
|
- プログラムの実行はどのようにして行われるのか、Linuxカーネルのコードから探る (2017/7/20)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。最終回は、Linuxカーネルの中では、プログラムの起動時にはどのような処理が行われているのかを探る - エンジニアならC言語プログラムの終わりに呼び出されるexit()の中身分かってますよね? (2017/7/13)
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。今回は、プログラムの終わりに呼び出されるexit()の中身を探る - VBAにおけるFileDialog操作の基本&ドライブの空き容量、ファイルのサイズやタイムスタンプの取得方法 (2017/7/10)
指定したドライブの空き容量、ファイルのタイムスタンプや属性を取得する方法、FileDialog/エクスプローラー操作の基本を紹介します - さらば残業! 面倒くさいエクセル業務を楽にする「Excel VBA」とは (2017/7/6)
日頃発生する“面倒くさい業務”。簡単なプログラミングで効率化できる可能性がある。本稿では、業務で使うことが多い「Microsoft Excel」で使えるVBAを紹介する。※ショートカットキー、アクセスキーの解説あり
|
|