Omuniauthを使ってRailsアプリにソーシャルサインオンの機能を追加してみました。

facebook編

まずはgemのインストール

モデルの変更

プロバイダのキーとプロバイダ内のユーザIDをユーザテーブルに追加

config/initializers/devise.rbに以下の設定を追加

ビューにfacebookログインのリンクを追加

controllers/users/omniauth_callbacks_controller.rbを作成

config/routes.rbを修正

仕組み

user_facebook_omniauth_authorize_pathではinitializersで設定したfacebookのAPP IDとSECRETからAuthorize URLを生成し、コールバックが返ってきたら作成したcallbackのコントローラで認可後の処理をします。

request.env[“omniauth.auth”]にはプロバイダやユーザ情報が入っているので、それらの情報を使ってActiveRecordのwhere(provider: auth.provider, uid: auth.uid)で検索し、既にプロビジョニングされているユーザであればログイン、そうでなければユーザの新規作成をしています。

コールバック直後にユーザを自動作成するのではなく、ユーザ入力や確認画面等をはさみたい場合は、モデルをcreateせずにrequest.env[“omniauth.auth”]をsessionで持ち回って登録画面に遷移させればOK。sessionで”devise.”のプレフィックスが付いたものはdeviseでログインしたときに自動的に削除されるためセキュアかつ効率的です。

これで、”facebookアカウントでログイン”リンクをクリックすると、facebookの認証/認可画面を介してアプリケーションのユーザが自動的に作成 or ログインできます。

Twitter、Githubの対応サンプル

以下のGemをインストール

initializerに追加

以下のリンクを追加

callbackはtwitter, githubというメソッドを追加して上述のfacebookメソッドのように実装すればOKです。

ただし、request.env[‘omniauth.auth’]の値はプロバイダによって変わってくるので、プロビジョニングの部分等は各プロバイダを考慮した上で実装する必要があります。

補足

リファレンスではUserモデルのdeviseのモジュール定義でomniauth_providersを定義しています。

実はinitializersでomniauthメソッドで定義したソーシャルプロバイダを全て利用する場合は、omniauth_providersの定義が無くても動きます。

devise+omniauthでは利用するソーシャルプロバイダのキー(”twitter”とか”facebook”とか)を配列で管理しており、プロバイダのキーを使って認証、コールバック用のURLやコントローラへのマッピングを生成しています。その配列に対するアクセサがomniauth_providersメソッドになります。

deviseメソッドによって可変長の引数に対応したモジュール(lib/devise/modelsディレクトリ直下のモジュール)のモジュール+モジュール内のmodule ClassMethodsがinclude、extendされます

omniauthableモジュールのClassMethods内ではDevise::Models.configメソッドが呼び出され、available_configsに[:omniauth_providers]がセットされるとともに、omniauth_providersのアクセサが定義されます。Getterはインスタンス変数が定義されていればインスタンス変数を返し、そうでなければSuperClassのGetter、それもなければDeviseのクラスメソッドを返します。

Deviseのクラスメソッドはinitializers内のomniauthメソッドで定義したプロバイダのキーの配列を返します。

omniauth_providersのプロパティを定義すると、Setterが呼び出され、インスタンス変数が定義された状態になります。インスタンス変数が定義されている場合、Getterはそのインスタンス変数を返すようになるので、この時点でDeviseのクラスメソッドomniauth_providersは呼び出されなくなります。

たとえばinitializersでfacebook、twitterに対して定義していてもomniauth_providersのプロパティでfacebookしか設定していない場合はプロパティの設定が優先されるため、twitterをソーシャルサインオンに利用できなくなり、twitter用の認証、コールバックURLは記述するとエラーになります。

参考URL