Facebook認証機能の実装(3)
Userモデルの修正
追加したルーティングを確認する前に、UserモデルにOmniAuthを有効化する記述を以下の通り追加します。
class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable, omniauth_providers: [:twitter, :facebook] # 追加 end
このように指定するとdeviseでOmniAuthの機能を使うことができるようになります。この時点でルーティングを確認することができます。以下のコマンドを実行して、追加したルーティングに該当するomniauth_callbacksとregistrationsに対応するコントローラーがdeviseからusersに変わっていることを確認しておきましょう。
bin/rails routes
次に、コールバック用コントローラーで呼び出すfind_or_create_for_oauthメソッドとユーザー登録用コントローラーから呼び出すnew_with_sessionメソッドを定義します。
class User < ApplicationRecord …(中略)… class << self def find_or_create_for_oauth(auth) find_or_create_by!(email: auth.info.email) do |user| user.provider = auth.provider user.uid = auth.uid user.name = auth.info.name user.email = auth.info.email password = Devise.friendly_token[0..5] logger.debug password user.password = password end end def new_with_session(params, session) if user_attributes = session['devise.user_attributes'] new(user_attributes) { |user| user.attributes = params } else super end end end end
find_or_create_for_oauthメソッドは、OAuth認証後に得られたユーザーのメールアドレスを元にユーザー情報の取得または登録を行っています。auth.info.emailなどとすると外部サービスで登録されているメールアドレスを取得することができます。
パスワードもあわせて登録しないとバリデーションエラーが発生してしまうため、ここではdeviseが提供するfriendly_tokenメソッドを使って6文字のパスワードを生成してセットしています。このパスワードは後でユーザー情報の編集時に使用するため、logger.debugでパスワードをログ出力するようにしています。アプリケーションログにパスワードが出力されてしまうので、実際の運用ではユーザーにメール送信するなどの対応が必要となる点に注意しましょう。
new_with_sessionメソッドは、deviseのRegistrationsControllerから呼び出されます。ここでは、セッションに格納されたユーザー情報を補完する処理を追加しています。
SSLでの動作定義
前述の通り、FacebookアプリはSSL接続が必須となっているので、ローカルで開発しながら動作を確認するにあたってもSSLでアクセスできるようにする必要があります。
まず、pumaサーバーをSSLでアクセス可能にするための前準備として、SSL証明書を自前で作成します。ここでは、ローカル環境に限ってアクセスできればよいので以下のコマンドで証明書を作成します。
なお、2つ目のコマンド実行時に国名などを聞かれるので、最初の国名のみJAと入力して、その後は何も入力せず[Enter]キーのみ押下すれば問題ありません。
# RSA暗号方式で秘密鍵を作成 openssl genrsa 2048 > tmp/server.key # 秘密鍵からCSRを作成 openssl req -new -key tmp/server.key > tmp/server.csr # 秘密鍵からSSL自己証明書を作成 openssl x509 -days 3650 -req -signkey tmp/server.key < tmp/server.csr > tmp/server.crt
次に、pumaサーバー用の設定ファイルの末尾に以下の通り追記します。このように記述することでポート9292でSSL接続することができるようになります。
if ENV.fetch('RAILS_ENV') { 'development' } == 'development' ssl_bind '0.0.0.0', '9292', { key: 'tmp/server.key', cert: 'tmp/server.crt' } end
config/puma.rbの設定を反映させてpumaサーバーを起動するには以下のコマンドを実行します。
bin/bundle exec puma -C config/puma.rb
上記コマンドを実行してpumaサーバーが立ち上がった際に以下のようなログが出力されていれば「https://127.0.0.1:9292」でトップページにアクセスすることができるようになります。
* Listening on ssl://0.0.0.0:9292?cert=tmp/server.crt&key=tmp/server.key&verify_mode=none
Facebook認証の動作確認
pumaサーバーが正常に立ち上がったら、「https://127.0.0.1:9292」にアクセスすると以下のような画面が表示されます。
ページ下部のリンクに[Sign in with Twitter][Sign in with Facebook]リンクが増えていることが確認できます。Facebookにログイン済みの状態で[Sign in with Facebook]リンクをクリックすると、以下のようなFacebookのOAuth認証画面が表示されます。
[~としてログイン]ボタンをクリックするとRailsアプリのトップページにリダイレクトしてユーザー登録が完了します。表示されているメールアドレスがFacebookに登録されているものと一致していることに注目してください。
まとめ
ここまで、OmniAuthが提供する機能の概要を確認すると共に、実際にdeviseと連携してRailsアプリにFacebookと連携する機能の実装と動作確認を行いました。また、dotenv-railsを導入して環境変数を.envに定義して使えることも確認しました。
次回は、引き続きTwitter連携の機能を実装するとともにユーザー情報を編集できるようにしていきます。