いますぐ使えるOpenID

第4回 Railsで作るOpenID対応アプリケーション実践(前編)

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

OpenID Authenticationプラグインによるユーザ認証

ログイン処理

OpenID Authenticationプラグインを使ったログインの流れを見ていきます。まずはログイン画面からです。ここはOpenIDアカウント(User-Supplied Identifier)を入力するフォームが存在するだけです。

view/sessions/new.html.erb

<% form_tag(session_url) do %>
  <label for="openid_url">OpenIDアカウント名を入力してください:</label>
  <%= text_field_tag "openid_url" %>
  <%= submit_tag 'Sign in', :disable_with => "Signing in…" %>
<% end %>

OpenIDの仕様では,アカウントを入力するフィールドに「openid_url」という名前を付けることが推奨されています。この名前を付けることで,Webブラウザのオートコンプリート機能によって他のサイトで入力した値を自動補完できるためです。フォームに入力したアカウント名はSessionsコントローラのcreateアクションへと送られます。createアクションのソースコードを以下に示します。

controller/sessions_controller.rb

  def create
    # OpenID でユーザを認証する (begin, completeの両方に対応)
    authenticate_with_open_id do |result, identity_url|
      if result.successful?
        if @current_user = User.find_by_identity_url(identity_url)
          # 認証成功でユーザが登録済みの場合はログイン成功 (A)
          successful_login
        else
          # 認証成功でユーザが未登録の場合はユーザ登録画面へ遷移 (B)
          session[:identity_url] = identity_url
          redirect_to(new_user_path)
        end
      else
        # 認証失敗の場合はエラーメッセージを表示 (C)
        failed_login result.message
      end
    end
  end

authenticate_with_open_idは,OpenID Authenticationプラグインが提供するメソッドです。連載の第2回で紹介したruby-openid付属のサンプルでは,OPへOpenIDリクエストを送信するbeginメソッドと,OPからのOpenIDレスポンスを受信するcompleteメソッドに分かれていました。しかし,authenticate_with_open_idメソッドはこれらの処理を隠蔽してくれます。そのため,認証処理をシンプルに記述できています。

まず,OPへのOpenIDリクエストは,authenticate_with_open_idメソッドが自動的に生成します。そのため,createアクション側でOPへのリダイレクト処理を書く必要はありません。

次に,OPからのOpenIDレスポンスを受信すると,authenticate_with_open_idの内側に記述したブロックが実行されます。ブロック内部では処理結果を格納したresult変数と,ユーザのOpenIDアカウント (User Claimed Identifier) を格納したidentity_url変数が利用できます。createアクションでは,result.successful? を使って,認証処理が成功したかどうかを確認し,成功の場合はidentity_url からアカウント名を取得します。

このように,OpenID Authenticationプラグインを使えば,認証処理をシンプルに記述できています。createアクションでの処理をまとめると,以下のようになります。

認証成功の場合
  • データベースにユーザが登録されていればセッションを生成してログイン成功(A)
  • データベースにユーザが未登録であればユーザ登録画面へ(B)
認証失敗の場合
  • ログイン画面にエラーメッセージを表示(C)

パスワード認証の場合と異なり,OpenIDではOPでのユーザ認証とRPでのユーザ登録の確認の二段階となります。また,ユーザが未登録の場合にユーザ登録画面に遷移するのも特徴的です。

ユーザ登録処理

前述の通り,OpenIDで最初にログインする時には,RP側にはそのユーザ情報は存在しません。ブログのコメントのように,その場限りの認証であればRPでユーザ情報を持つ必要がありません。しかし,通常のサービスであればRPにもユーザ情報が必要となります。

図3 ユーザ登録画面

図3 ユーザ登録画面

今回のサンプルではつぶやきの画面に表示するニックネームが必要なので,ニックネームを入力してもらい,ユーザ情報をデータベースに登録します。すでに認証済みのユーザを登録するので,メールアドレスの到達確認やCAPTCHAの入力は不要としています。パスワードの登録も必要ありません。

もちろん,アプリケーションの種類によっては,ユーザのメールアドレスが必須の場合もあります。そのときは,通常のユーザ登録のようにメールアドレスの到達確認機能も必要になるかもしれません。また,SREGに対応しているOPであれば,SREGを使ってOPに登録されているメールアドレス情報を取得することもできるでしょう。

ユーザ登録画面から呼ばれるUsersコントローラのcreateメソッドを以下に示します。ユーザ情報のうち,identity_urlを先ほど保存したセッション情報から設定しているのが特徴的です。

controller/users_controller.rb

  def create
    @user = User.new(params[:user])
    # identity_url 属性にセッションで保存した値を代入
    @user.identity_url = session[:identity_url]
    if @user.save
      # ユーザ登録に成功したら home 画面へ移動
      redirect_to(user_home_path)
    else
      render :action => "new" }
    end
  end

ユーザ登録が終わると,ホーム画面へと遷移します。また,次回のログインからは,すでにユーザが登録されているので,認証成功時にホーム画面へと遷移します。

まとめ

今回はOpenID Authenticationプラグインを使って,ログインおよびユーザ認証の機能を作成しました。パスワード認証の場合と異なり,OpenID認証では先にOpenIDを使ってユーザを認証します。認証後にユーザ登録の有無によって,ログイン成功とするかユーザ登録画面を表示するかを制御します。

念のために書いておきますが,ユーザ登録フォームに利用者が直接OpenIDアカウントを入力させてはいけません。OpenID認証を実施して,ユーザのOpenIDアカウントが正当であることが確認できてから,ユーザ情報にOpenIDアカウント名を自動で設定するようにしてください。

次回は今回のサンプルアプリケーションを拡張し,パスワード認証とOpenID認証が共存できるようにします。

著者プロフィール

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

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