Transcript
Ruby on Railsで作るOpenID対応サイトIdentity Conference #3MATSUOKA Kohei <kohei@machu.jp>
1
今日のテーマ
RailsでOpenID対応サイト (RP) を作るには?
Railsをつかって駆け足でRPを作成します
セキュリティやSREGでの属性取得も少々
そろそろマイミク認証について一言いっておくか
2
宣伝
gihyo.jp
いますぐ使えるOpenID
http://gihyo.jp/dev/feature/01/openid
4
アプリの構成
Ruby 1.8.6-p111, Ruby on Rails 2.1
ruby-openidライブラリ
Restful Authenticationプラグイン
OpenID Authenticationプラグイン
8
ruby-openid
sudo gem install ruby-openid
RubyでOpenIDを扱うための基本的なライブラリ
http://openidenabled.com/ruby-openid/
PHP, Pythonにも同様のライブラリあり
9
RESTful Authentication
認証機能の枠組み
RESTfulな設計
OpenID Authプラグインと組み合わせて利用
処理 メソッド パス
ユーザ登録 POST /users
ログイン POST /sessions
ログアウト DELETE /sessions
11
OpenID Authenticationruby_openidライブラリのRails向けラッパー
OpenID Providerとのやりとりを担当
authenticate_with_open_id do |result, identity_url| if result.successful? # 認証成功 else # 認証失敗 end
12
チャットのひな形を作成
script/generate scaffold message title:string
rake db:migrate
script/server -> Railsサーバ (mongrel) が起動
14
自動生成されるファイル
18
種別 名称 役割
モデル User ユーザ情報を保存
コントローラUsersController ユーザ登録
SessionsController ログイン、ログアウト
ビューusers/new ユーザ登録画面
sessions/new ログイン画面
認証と認可
チャットの書き込みにはログインが必要
AuthenticatedSystemをインクルード
フィルタでlogin_requiredメソッドを呼び出す
class ApplicationController < ActionController::Base include AuthenticatedSystem
class MessagesController < ApplicationController before_filter :login_required, :except => [:index, :show]
20
AuthenticatedSystemコントローラにincludeして使用
認証と認可に必要なメソッドを定義
メソッドをオーバーライドすることでカスタマイズ可能
login_requiredauthorized?
認可
access_deniedアクセス拒否時の動作を定義
logged_in?ログインの有無を判定
NG
21
OpenID認証への対応RESTful Authenticationプラグインで作成したひながたを元にOpenID認証に対応します
変更箇所
データベース
ログイン処理(コントローラ)
ログイン画面、ユーザ登録画面(ビュー)
データベースの更新
OpenIDライブラリが使用するテーブルを自動生成
rake open_id_authentication:db:create
open_id_authentication_associations
open_id_authentication_nonces
24
データベースの更新
usersテーブルにidentity_url属性を追加
OpenIDのVerified Identifierを保存するため
rake db:migrateを実行してDBスキーマを更新
25
ログイン処理の修正パスワード認証をOpenID認証へ
Sessionsコントローラのcreateメソッドを修正
OpenID AuthenticationのREADMEを参考
認証成功時に処理を分岐
ユーザ登録済 → セッションCookie発行
ユーザ未登録 → ユーザ登録画面へ
27
ログイン処理の修正 authenticate_with_open_id do |result, identity_url| if result.successful? if @current_user = User.find_by_identity_url(identity_url) successful_login else # identity_url (Verified Identifier) をセッションに保存 session[:identity_url] = identity_url # ユーザ登録画面へリダイレクトする redirect_to new_user_path end else # 認証失敗 flash[:notice] = result.message render :action => 'new' end end
認証成功→ Cookie発行
認証成功(未登録)→ ユーザ登録へ
認証失敗→ ログイン画面へ
※ OPへのリダイレクト処理は記述不要28
http://d.hatena.ne.jp/ZIGOROu/20080805/121793320632
SSL対応の発行サイト“mixi.jp”でログイン → ログに警告が出力
サーバ証明書を発行したCAを信頼していないため
でも警告だけで使えてしまう><
DNS Cache Poisoningされるとアウト
WARNING: making https request to https://mixi.jp/xrds_server.pl without verifying server certificate; no CA path was specified.
33
SSLを”正しく”利用する信頼していないCAへの接続は拒否する
OpenID.fetcher.ca_fileにCAのリストを設定
config/environment.rb あたりに記述
cURLのCAリストを使用したOpenID.fetcher.ca_file = '/usr/share/curl/curl-ca-bundle.crt'
35
SSLを”正しく”利用するOpenID.fetcher.ca_fileを設定
mixi.jpにログイン
警告ではなくエラーで停止
信頼していない証明書は受け入れない
[OPENID] Failed to fetch Yadis URL https://mixi.jp/xrds_server.pl :Error connecting to SSL URL https://mixi.jp/xrds_server.pl:
certificate verify failed36
mixiの場合id.mixi.jpとmixi.jpでルート証明書が異なる
id.mixi.jp … GTE CyberTrust Global Root
mixi.jp … AddTrust External CA Root
Mac OS XのcURLはAddTrustが含まれていない
Netscape Communicator 4.7の証明書リスト
他のOSでは入っている証明書リストが異なる
証明書リストに追加(2)BEGIN CERTIFICATEと書かれたファイル
これがCAの証明書
CAリストの末尾にこのテキストを貼り付ける
-----BEGIN CERTIFICATE-----MIIENjCCAx6gAwIBAgIBATANBgkqhk
<略>
1Z5jJh5VkpTYghdae9C8x49OhgQ=-----END CERTIFICATE-----
警告もエラーも出ずにログインできるようになる!
39
参考ruby で mixi OpenID を呼ぶには
http://d.hatena.ne.jp/n_shuyo/20080911/mixi_openid
php-openid で mixi のコミュニティ認証を使うhttp://www.machu.jp/diary/20080918.html#p01
面倒でもちゃんと設定しましょう
40
mixiのニックネームを取得引数に :optional => :nickname を追加するだけ authenticate_with_open_id(params[:openid_url], :optional => :nickname) do |result, identity_url, registration| if result.successful? if @current_user = User.find_by_identity_url(identity_url) successful_login else # identity_url (Verified Identifier) をセッションに保存 session[:identity_url] = identity_url session[:nickname] = registration['nickname'] # ユーザ登録画面へリダイレクトする redirect_to new_user_path end
43
マイミク認証とは?
自分が誰かのマイミクであることを認証
普通のOpenIDと同じ仕組みで実現!
まちゅさんのマイミクhttps://id.mixi.jp/1741395/friends/
45
マイミク認証の手順identity_urlからmixiのユーザIDを取得
https://id.mixi.jp/1741395/
後ろにfriends/を付与してClaimed Identityを生成
https://id.mixi.jp/1741395/friends/
authenticate_with_openidメソッドでマイミク認証
47
認証処理のコードidentity_urlの生成以外は普通のOpenID認証と同じ
class FriendsController < ApplicationController def show @user = User.find(params[:user_id]) if @user.identity_url =~ %r|^https://id\.mixi\.jp/\d+| identity_url = "#{@user.identity_url}/friends" authenticate_with_open_id(identity_url) do |result, identity_url| unless result.successful? flash[:notice] = "あなたはマイミクではないようです!" redirect_to '/' end end
48
マイミク認証のおさらいマイミク認証
コミュニティ認証
RPからは普通のOpenIDアカウントと同じにみえる
まちゅさんのマイミクhttps://id.mixi.jp/1741395/friends/
ニコニコ動画コミュニティの参加者https://id.mixi.jp/community/1651291/
50
コミュニティIDでユーザ登録してみる
https://id.mixi.jp/community/1651291/
51
そんなことはありませんUser Supplied Identifierhttps://id.mixi.jp/community/1651291/
User Claimed Identifier (openid.claimed_id)
https://id.mixi.jp/community/1651291/1741395
User Verified Identifier (openid.identity)https://id.mixi.jp/1741395
ログイン前
ログイン後 個人のID
Claimed ID or Verified IDサービス Claimed ID Verified ID
mixi認証 https://id.mixi.jp/1741395 https://id.mixi.jp/1741395
コミュニティ認証 https://id.mixi.jp/community/1651291/1741395 https://id.mixi.jp/1741395
マイミク認証 https://id.mixi.jp/29704/friends/1741395 https://id.mixi.jp/1741395
delegate http://www.machu.jp/ https://id.mixi.jp/1741395
55
参考
Relying PartyとIdentityの関連づけについてhttp://d.hatena.ne.jp/ZIGOROu/20080204/1202115281
RPはClaimed IDを紐づけるのが正解との結論
56
結論
間違ってもUser Supplied Identifierは記録しない
OpenID Authenticationプラグインを使うとUser Claimed IDが記録される
コミュニティ認証やマイミク認証のIDでのユーザ登録を拒否したければ、RPで個別対応
ここだけClaimed IDではなくVerified IDを記録
top related