いますぐ使えるOpenID

第2回 OpenIDライブラリに付属しているRPサーバを動かしてみる

この記事を読むのに必要な時間:およそ 3 分

OP への認証リクエストの送信

ここからはサンプルを動かしながら,ruby-openidライブラリの簡単な使い方について説明します。

Railsを動かす環境が無い方は,ruby-openidライブラリのサイトで同じサンプルが公開されていますので,こちらにアクセスしてみるのがよいでしょう。サイトの一番下にある,⁠Live Demos」「2.x.x trunk demo relying party」からRPのサンプルへアクセスできます。

ログイン画面の表示(index.rhtml)

ログイン画面のソースコードはapp/views/consumer/index.rhtmlに記述されています。 以下にソースコードの一部を抜粋します。

69  <form method="get" accept-charset="UTF-8"
70      action='<%= url_for :action => 'start' %>'>
71  Identifier:
72  <input type="text" class="openid" name="openid_identifier" />  
73  <input type="submit" value="Verify" /><br />

Identifierと書かれた入力フィールドがOpenIDのアカウント名(User-Supplied URL)を入力する箇所です。

OPへのリダイレクト(ConsumerController#start)

Identifierに自分のOpenIDを入力してVerifyボタンを押すと,Consumerアクションのstartメソッドが呼ばれます。Consumerアクションはapp/controllers/consumer_controller.rbです。 この中のstartメソッドから重要な箇所だけを説明します。

まず,ユーザが入力したOpenIDのURLを引数に beginメソッドを呼び出して,OpenIDの認証要求を生成してもらいます。 consumerはruby-openidが提供するOpenID::Consumerクラスのオブジェクトです。 OpenID::Consumerは引数として渡されたURLからOpenIDのOPを見つけ出します。 戻り値のoidreqは認証要求を扱うためのOpenID::Requestクラスのオブジェクトです。

    # ユーザが入力したopenid_identifierを元にOpenIDリクエストを作成
17  oidreq = consumer.begin(params[:openid_identifier])  

oidreqのredirect_urlメソッドを呼び出して認証サーバ(OP)のログイン画面URLを取得し,そのURLへ利用者をリダイレクトします。

    # 利用者をOPのログイン画面(OP EndPoint)へと誘導する
47  redirect_to oidreq.redirect_url(realm, return_to, params[:immediate])  

なお,redirect_urlメソッドの引数として渡しているreturn_toとrealmパラメータは,直前で下記のように生成しています。

    # 認証サーバ(OP)からの戻り先URL(completeアクションのURL)
43  return_to = url_for :action => 'complete', :only_path => false  
    # このサーバを識別するためのrealm
44  realm = url_for :action => 'index', :only_path => false

これで,ユーザはOPのログイン画面へと転送されます。

OPでのログイン

OPのログイン画面で,IDとパスワードを入力してログインします。 先ほどのはてなやYahoo!の例と同じですので,説明は割愛します。

OPからの認証結果の受け取り (ConsumerController#complete)

OPからの認証結果は,リクエストで指定したreturn_toへと戻ってきます。 今回はcompleteアクションを指定したので,completeメソッドが呼ばれます。 以下にソースコードを抜粋します。

55  current_url = url_for(:action => 'complete', :only_path => false)  
56  parameters = params.reject{|k,v|request.path_parameters[k]}
    # 戻り値を解析し,OpenID::Responseクラスのオブジェクトを作成
57  oidresp = consumer.complete(parameters, current_url)

completeメソッドの戻り値のoidrespは,OpenID::Responseクラスのオブジェクトです。 OPでのログインに成功したかどうかは,oidresp.statusで確認できます。 statusは下記4つの値をとります。

  • OpenID::Consumer::FAILURE…メッセージの検証に失敗した
  • OpenID::Consumer::SUCCESS…ログインに成功した
  • OpenID::Consumer::SETUP_NEEDED…セットアップが必要
  • OpenID::Consumer::CANCEL…ユーザがログインを拒否した

ログインに成功していれば(statusがSUCCESSであれば⁠⁠,OpenID::Responseオブジェクトのdisplay_identifierからユーザのOpenIDアカウントを取得できます。 サンプルでは,画面に表示するために文字列として格納していますが,実際のアプリケーションでは,取得したOpenIDアカウント名をセッションに格納する処理が入ることになるでしょう。

    # OpenIDレスポンスのステータスを確認 
57  case oidresp.status
    # ログイン成功なら,display_identifierからOpenIDのアカウント名を取得
65  when OpenID::Consumer::SUCCESS
66    flash[:success] = ("Verification of #{oidresp.display_identifier}"¥  
67                       " succeeded.")

最後に,取得したIDを画面に表示しています。

図2

いかがでしたでしょうか。 少し概念が難しく感じるかもしれませんが,この程度のサンプルであれば意外と簡単に作れることが分かったのではないでしょうか。 はてなやYahoo!のような多くのユーザを抱えるサイトがOpenIDのOPサービスを提供し,OpenIDを使うためのライブラリが充実している今,OpenIDは意外と身近なものになっているのかもしれません。

次回は,OpenIDライブラリを使いながら,利用者が入力したOpenIDアカウント名からOPの認証画面のURLを見つけるdiscoveryの仕組みや,OpenIDの拡張領域を使ってOPに登録されている利用者のメールアドレスを取得する方法などを説明します。

著者プロフィール

松岡浩平(まつおかこうへい)

NTTコムウェア株式会社にて,オープンソースを活用した認証システムの開発を担当しています。ここ2年は,情報セキュリティ大学院大学に通学しながら,OpenIDを使った認証システムについて研究していました。