at posts/single.html

Rails で OpenID を使う (OpenID::SuccessRequest#redirect_url を読もう編)

引き続き、ユーザに OpenID のアカウント (URL) を入力してもらい、OpenIDの認証サーバに誘導するところの処理について。

request = consumer.begin(openid_url)
url = request.redirect_url(trust_root, return_to)
redirect_to(url)

昨日の日記では、鍵交換などの認証のための事前準備 (OpenID::Consumer#begin) のところを読んだ。 今日は認証サーバへのリダイレクトを生成する redirect_url メソッドについて調べよう。 昨日見たとおり、 request は SuccessRequest クラスのインスタンスになってる(GenericConsumer#begin メソッドの中で SuccessRequest クラスののインスタンスを生成している)。

    def begin(service)
      nonce = self.create_nonce
      assoc = self.get_association(service.server_url)
      return SuccessRequest.new(assoc, nonce, service)
    end

SuccessRequest クラスも consumer.rb で定義されているっぽい。 定義されているメソッドの一覧を表示してみた。

$ grep -E '^\s*(class|def|module)' consumer.rb
  class OpenIDStatus
    def initialize(status)
  class SuccessRequest < OpenIDStatus
    def initialize(assoc, nonce, service)
    def redirect_url(trust_root, return_to, immediate=false)
    def return_to(return_to)
    def add_extension_arg(namespace, key, value)
    def add_arg(key, value)
    def uses_extension?(extension_url)

SuccessRequest#redirect_url

redirect_url の引数は trust_root, return_to, immediate の3つ。

OpenID server (permit)

  • trust_root … 認証サーバがコンシューマを識別するための URL 。認証サーバが「許可しますか?」の画面を出すかどうかは、 trust_root を見ているんじゃないかな(未確認)。 realm みたいなものかと思っていたら、やっぱり 2.0 では openid.realm というパラメータに変更されてた。
  • return_to … 認証サーバでのログイン後に戻ってくる URL 。 trust_root で指定した URL を含んでいないと NG になるはず(未確認)。
  • immediate … immediate mode を使うかどうか。とりあえずは気にしないことにする。

メソッドの中身は意外とシンプルだった。 認証サーバに渡すパラメータをハッシュとして生成して、 OpenID::Util.append_args でパラメータを追加し、最後に to_s 文字列に変換しているだけ。

    def redirect_url(trust_root, return_to, immediate=false)
      # add the nonce into the return_to url
      return_to = OpenID::Util.append_args(return_to, @return_to_args)

      redir_args = {
        "openid.identity" => @server_id,
        "openid.return_to" => return_to,
        "openid.trust_root" => trust_root,
        "openid.mode" => immediate ? 'checkid_immediate' : 'checkid_setup'
      }

      redir_args["openid.assoc_handle"] = @assoc.handle if @assoc
      redir_args.update(@extra_args)

      return OpenID::Util.append_args(server_url, redir_args).to_s
    end

redirect_url メソッドではインスタンス変数がいくつか使われている。 このうち、 @server_id と @return_to_args と @extra_args は initialize メソッドで初期化されてる。

    def initialize(assoc, nonce, service)
      super(SUCCESS)
      @service = service
      @server_id = service.server_id
      @server_url = service.server_url
      @identity_url = service.consumer_id
      @extra_args = {}
      @return_to_args = {'nonce' => nonce}
    end
  • @server_id … 認証サーバのID。 Consumer#begin で取得している。
  • @return_to_args … nonce を含むハッシュ値。 nonce も Consumer#begin で生成している。
  • @extra_args … OpenID の拡張として含む値。拡張を追加するには、 OpenID::SuccessRequest#add_extension_arg を呼び出せばいいみたい。
    def add_extension_arg(namespace, key, value)
      @extra_args['openid.'+namespace+'.'+key] = value
    end

まとめ

今日は短めだった。

  • SuccessRequest#redirect_url … ハッシュに OpenID のパラメータを格納し、最後に文字列 (URL) へと変換する。
  • ちょっとインスタンス変数を多用気味かも。
  • SuccessRequest#add_extension_arg … OpenID を拡張する際に呼び出す(未確認)。

関連する日記