OAuthについて
OAuthについて
OAuthとは、第三者となるアプリケーションに対して安全にアクセス権限を提供するためのプロトコルのことです。OAuthを利用すると、例えばTwitterやFacebookなどのSNSからログインすることが可能となります。
本記事ではgemのOmniAuth
を利用してGitHub認証をBookアプリに実装します。
本記事の前提
内容に入る前に、まずアプリ作成の流れなどを振り返ります。
- 『Railsの教科書』内で紹介されていたBookアプリを作成
- 日本語に対応するためにgem
i18n
を実装 - ページネーション機能をgem
kaminari
で実装 - ログイン・ログアウト機能をgem
devise
とdevise-i18n
で実装 - GitHubによるログイン機能をgem
OmniAuth
で実装 ←今日はここです! - ActiveStorageによるプロフィール画像のアップロード機能実装
deviseを利用することで、メール認証など一旦ユーザー認証の機能は追加済みです。
DBにはBookとUserのテーブルが存在しており、モデルの作成後、Userテーブルにカラムの追加はしておりません。
OmniAuth導入にあたっての補足
基本的にこちらの記事を参考にして進めました。 こちらの内容通りに進めれば問題なく実装できるかと思います。
大枠として、プロセスは以下のようなイメージです。
- GitHub連携の準備のため、GitHub上で"Client ID"と"Client Secret"の取得
OmniAuth
のインストール- DBテーブルへのカラムの追加
- app/models/user.rbへのメソッド追加
dotenv-rails
をインストールし、.env
ファイルを作成して"Client ID"と"Client Secret"を記述- コールバック処理のコントローラを作成する
- config/routes.rbとconfig/initializers/devise.rbの修正
- viewsファイルの修正
一部補足事項がありますのでこちらの記事で紹介いたします。
3. DBテーブルへのカラムの追加
deviseとomniauthを同時にインストールする場合などは、記事通りに実行すれば問題ありません。 私は既ににdeviseのインストールと実装を済ませていたので、必要なカラムを追加してマイグレーションファイルを確認する必要がありました。
OmniAuth利用に必要なカラムは以下の2つ。
uid
とprovider
(この場合はGitHubですね!)
uid
とprovider
についてはDBのデータを検索するメソッドで必要になるため、テーブルに存在していない場合追加してあげましょう。
# uidとproviderの追加 $ rails g migration AddUidToUser uid:integer provider:string
また、必須ではないのでがログイン画面でユーザー名を表示したい場合などに必要なusernameもしくはnameを登録する場合があります。これはoAuthというよりdeviseのトピックになりますね。
deviseを利用すると、認証に必要なデータとしてデフォルトでemailとパスワードが利用できますが、それ以外のカラム(代表的なのがusernameです)をDBに追加して認証に利用する場合、前回の記事でも紹介したstrong parametersの仕組みを考慮する必要があります。
# usernameの追加 $ rails g migration AddUserameToUser username:string:uniq #ユニークにするために:uniqを使用 $ rails db:migrate
application_controller.rbのbeforeフィルターに別途処理を記述しましょう。以下の記述を忘れるとstrong parametersによりエラーが発生します。
# application_controller.rb class ApplicationController < ActionController::Base before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.permit(:sign_up, keys: [:username]) end end
また、usernameを追加した場合viewsについてもカスタマイズする必要があります。
4. app/models/user.rbへのメソッド追加
Modelに様々なメソッドを追加するのですが、特に以下の処理は重要です。
uidとproviderによりDBを検索して、値が存在しない場合は、新規でユーザーインスタンスを作成するというメソッドですね。
# app/models/user.rb def self.find_for_github_oauth(auth, signed_in_resource=nil) user = User.find_by(provider: auth.provider, uid: auth.uid) unless user user = User.create(provider: auth.provider, uid: auth.uid, username: auth.info.name, email: User.dummy_email(auth), password: Devise.friendly_token[0, 20] ) end user.skip_confirmation! user.save user 省略
こちらのメソッドは下記のコールバックの処理で使用されます。ユーザーが存在する場合としない場合とで条件分岐させてログイン認証の処理を分けていますね。
引数のauth
として渡されるのがrequest.env['omniauth.auth']
です。
# app/controllers/users/omniauth_callbacks_controller.rb class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController def github @user = User.find_for_github_oauth(request.env["omniauth.auth"], current_user) if @user.persisted? sign_in_and_redirect @user, :event => :authentication set_flash_message(:notice, :success, :kind => "Github") if is_navigational_format?
request.env['omniauth.auth']というリクエストパラメータには、OmniAuthによってHashのデータ構造に似たOmniAuth::AuthHashというクラスのオブジェクトが格納されています。oAuthによるこれらのデータを取得して、検索を行うのですね。
5. dotenv-rails
をインストールし、.env
ファイルを作成して"Client ID"と"Client Secret"を記述
.envのファイルに環境変数としてGitHubのAPI keyを登録します。環境変数として認識させるためにdotenv-rails
のインストールをお忘れずに。
.envを.gitignoreに置くことでGitHub上へのファイルのコミットを防ぎます。
以上となります。
OmniAuth実装上の注意点
-------deviseでメール認証を実装された方に向けた内容になります-------
実はGitHubの認証が上手くいっても、メール認証の設定によりログインができない場合があるのです。
こちらの記事のコメント欄にも同様の事象を経験されている方がいらっしゃいます。
メール認証のアラートが飛ぶ場合は、GitHub認証時にメール認証を省略するための記述が別途必要なのです。
それが、obj.skip_confirmation!
です。
# app/models/user.rb user = User.create(:username => data.name, 省略 ) user.skip_confirmation! #user.saveの前に処理を記述 user.save
上記の記述をすることで、GitHubによるログインを実行した後にメール認証のアラートが飛ぶことはないはずです。
また処理を分けているので、メール認証も引き続き実行可能です。
ログイン後の画面
GitHub認証後の遷移
メール認証後の遷移
参考文献
最後に
いかがでしたでしょうか。個人的には、OmniAuthの導入そのものより、username追加時のdeviseの処理などが難しく感じました。
次回はActiveStorageについてです!