openid with rails

58
Ruby on Railsで作る OpenID対応サイト Identity Conference #3 MATSUOKA Kohei < [email protected] > 1

Upload: kohei-matsuoka

Post on 25-May-2015

4.112 views

Category:

Technology


3 download

TRANSCRIPT

Ruby on Railsで作るOpenID対応サイトIdentity Conference #3MATSUOKA Kohei <[email protected]>

1

今日のテーマ

RailsでOpenID対応サイト (RP) を作るには?

Railsをつかって駆け足でRPを作成します

セキュリティやSREGでの属性取得も少々

そろそろマイミク認証について一言いっておくか

2

背景

2007年以降、OpenID発行サイトが充実

はてな、livedoor、Yahoo! Japan、そしてmixi

でも、対応サイトが少ない

Railsを使ってRPサイトを作ってみよう

3

作成するアプリ簡単なチャット

OpenIDでログイン

mixiのニックネームを取得

マイミク認証

Mac OS X + NetBeans 6.1で開発

5

NetBeans

統合開発環境

JRuby, CRuby, Rails

サーバの起動停止

コード補完

なかなか便利

ライブラリのインストール

7

OpenIDを利用するために必要なライブラリとプラグインを導入します

アプリの構成

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

Railsプラグインの導入プロジェクトを右クリックして、「Railsプラグイン」を選択

10

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

5分でできる(ry

13

サンプルの認証機能以外を作成します。よくあるRailsチュートリアルと同じです。

チャットのひな形を作成

script/generate scaffold message title:string

rake db:migrate

script/server -> Railsサーバ (mongrel) が起動

14

チャットのひな形を作成

画面をチャット風に修正

15

認証機能の組み込み

16

RESTful Authenticationプラグインを使ってアプリに認証機能を組み込みます

RESTful Authentication

認証のためのひながたを作成できる

./script/generate authenticated user sessions

17

自動生成されるファイル

18

種別 名称 役割

モデル User ユーザ情報を保存

コントローラUsersController ユーザ登録

SessionsController ログイン、ログアウト

ビューusers/new ユーザ登録画面

sessions/new ログイン画面

画面遷移

チャット/messages

ユーザ登録/users/new

ログイン/sessions/new

19

認証と認可

チャットの書き込みにはログインが必要

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認証への対応

22

OpenID Authenticationプラグインを使ってパスワード認証からOpenID認証へ変更します

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

画面遷移

26

ログイン処理

チャット

ログイン

ユーザ登録

※ ログイン→ユーザ登録となる

ログイン処理の修正パスワード認証を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

ログイン画面の修正

OpenIDのアカウント名を入力

お好みで「○○でログイン」ボタンを追加

ユーザ登録画面の修正

ニックネームのみ入力してもらう

identity_urlはセッションCookieから取得する

セッションCookieを持たないユーザを拒否

30

セキュリティ

31

RPの基本的なセキュリティ対策であるSSL対応(サーバ証明書の検証)について

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はほとんど無意味

cf. オレオレ証明書

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では入っている証明書リストが異なる

証明書リストに追加(1)

「信頼できる経路」を使ってルート証明書を取得

今回はfirefoxを使う

mixi.jpに接続

CA (AddTrust) の証明書を選択し、「書き出す」

38

証明書リストに追加(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

SREGで属性情報を取得

41

SREG拡張でmixiユーザのニックネームを取得します

mixiのニックネームを取得

ユーザ登録時のニックネームの初期値に利用

メールアドレスが取得できると便利なのに…

42

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

マイミク認証

44

mixi独自のマイミク認証を使ってみましょう

マイミク認証とは?

自分が誰かのマイミクであることを認証

普通の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

マイミク認証の考察

49

マイミク認証&コミュニティ認証の落とし穴・注意点を提起します

マイミク認証のおさらいマイミク認証

コミュニティ認証

RPからは普通のOpenIDアカウントと同じにみえる

まちゅさんのマイミクhttps://id.mixi.jp/1741395/friends/

ニコニコ動画コミュニティの参加者https://id.mixi.jp/community/1651291/

50

コミュニティIDでユーザ登録してみる

https://id.mixi.jp/community/1651291/

51

登録できた…

52

これって、みんなで使える共通アカウントが作れる?

そんなことはありません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

参考

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を記録

おしまい

58