はじめに
こんにちは。未経験からエンジニア転職を目指しプログラミングスクールRUNTEQにて学習しているokadaと申します。
さて、早速ですが、ソーシャルログイン機能をご存知でしょうか?これは、ユーザーがGoogleやLINEなどの既存のソーシャルメディアアカウントを使用し、ウェブサイトやアプリに簡単にログインできる機能のことです。この機能を導入することで、ユーザーの会員登録やログインの手間が大幅に削減でき、非常に便利です。
今回は、Sorceryを用いたRailsアプリケーションでのGoogle認証の追加方法について記載していきたいと思います。アプリ開発中の方や、これから開発を考えている方の参考になれば嬉しいです。
環境
- Rails 7.0.5
- Ruby 3.2.2
- Sorcery 0.16.5
前提条件として、SorceryのSimple Password Authentication(メールアドレス、パスワードを用いた認証)はすでに実装された状態であるものとします。
1. Google APIの設定
まずはGoogle APIのコンソールにて設定を行っていきます。
この手順については以下の記事でとても分かりやすく説明されておりますので割愛させていただきます。
【Rails7】Googleログインを公式ドキュメントに沿って実装する
2. credentials.ymlにclient ID, client secretを追加
APIの設定が完了したら、生成されたclient ID, client secretをcredentials.ymlに追加します。
ターミナルで下記のコマンドを実行し、credentials.ymlの編集画面を開きます。
EDITOR="vim" bin/rails credentials:edit
インサートモードにし、client ID, client secretを記載します。
google:
google_client_id: 取得したclient_id
google_client_secret: 取得したclient_secret
※ :(コロン)の後ろには半角スペースが必要です。半角スペースがないとエラーが発生する可能性があります。
編集が終了したら上書き保存をします。
3. Sorcery externalモジュールの導入
次に、Sorceryのサブモジュールをインストールします。
ターミナルで下記のコマンドを実行します。
rails g sorcery:install external --only-submodules
4. authenticationsテーブル、Authenticationモデルの作成
externalモジュールをインストールするとauthenticationsテーブルのmigrationファイルが自動生成されます。
migrationを実行し、authenticationsテーブルを作成します。
rails db:migrate
さらに、Authenticationモデルを作成します。
migrationファイルは必要ないため、migration=falseオプションをつけコマンドを実行します。
rails g model Authentication --migration=false
Authenticationモデルが作成できたらUserモデルとAuthenticationモデルの関連づけを行います。
それぞれのモデルに以下のようにAssociationを追加します。
class User < ActiveRecord::Base
has_many :authentications, :dependent => :destroy
accepts_nested_attributes_for :authentications
end
class Authentication < ActiveRecord::Base
belongs_to :user
end
5. sorcery.rbファイルの設定
sorcery.rbに設定を追加していきます。
# 70行目あたり
#externalモジュールの読み込み
Rails.application.config.sorcery.submodules = [:external]
Rails.application.config.sorcery.configure do |config|
#利用する外部サービスのプロバイダーを指定
config.external_providers = %i[google]
# 160行目あたり
#credentials.ymlから情報を取得
config.google.key = Rails.application.credentials.dig(:google, :google_client_id)
config.google.secret = Rails.application.credentials.dig(:google, :google_client_secret)
#API設定で承認済みのリダイレクトURIとして登録したurlを設定
config.google.callback_url = 'http://localhost:3000/oauth/callback?provider=google'
#外部サービスから取得したユーザー情報をUserモデルの指定した属性にマッピング
config.google.user_info_mapping = {:email => "email", :username => "name"}
end
config.user_config do |user|
#外部サービスとの認証情報を保存するモデルを指定
user.authentications_class = Authentication
6. OauthsControllerの作成
認証の処理を扱うためのControllerを作成します。
下記のようにoauthとcallbackアクションを追加します。
rails g controller Oauths oauth callback
oauthアクションとcallbackアクションを記述していきます。
ここでは一例を挙げさせていただきます。
class OauthsController < ApplicationController
skip_before_action :require_login
def oauth
#指定されたプロバイダの認証ページにユーザーをリダイレクトさせる
login_at(auth_params[:provider])
end
def callback
provider = auth_params[:provider]
# 既存のユーザーをプロバイダ情報を元に検索し、存在すればログイン
if (@user = login_from(provider))
redirect_to root_path, notice:"#{provider.titleize}アカウントでログインしました"
else
begin
# ユーザーが存在しない場合はプロバイダ情報を元に新規ユーザーを作成し、ログイン
signup_and_login(provider)
redirect_to root_path, notice:"#{provider.titleize}アカウントでログインしました"
rescue
redirect_to root_path, alert:"#{provider.titleize}アカウントでのログインに失敗しました"
end
end
end
private
def auth_params
params.permit(:code, :provider)
end
def signup_and_login(provider)
@user = create_from(provider)
reset_session
auto_login(@user)
end
end
ここで使用されているlogin_at(provider)
,login_from(provider)
,create_from(provider)
,auto_login(@user)
はSorceryであらかじめ用意されているメソッドです。
https://github.com/Sorcery/sorcery#external
7. routing設定
oauthアクションとcallbackアクションのroutingを設定します
post "oauth/callback" => "oauths#callback"
get "oauth/callback" => "oauths#callback"
get "oauth/:provider" => "oauths#oauth", :as => :auth_at_provider
8. リンクの設置
最後にリンクを設置します。
引数としてsorceryのauth_at_provider_path(provider)
メソッドを使用することで外部モジュールのURLに遷移させることができます。
<%= link_to 'Login with Google', auth_at_provider_path(provider: :google) %>
リンクをクリックし、無事ログインできれば成功です。
補足:本番環境のcallback_url適用
先ほどはsorcery.rbに直接callback_urlを記述しましたが、実際は開発環境と本番環境でそれぞれ異なるurlにリダイレクトさせる必要があります。
以下にgem 'config'を使用した方法を記載します。
-
Gemfile
にgem 'config'
を追加し、bundle install
を実行してインストール -
config/settings/
ディレクトリ下にdevelopment.yml
とproduction.yml
を作成 - それぞれのファイルに開発環境、本番環境のcallback_urlを記載
sorcery:
google_callback_url: 'http://localhost:3000/oauth/callback?provider=google'
sorcery:
google_callback_url: 'https://your_app_url/oauth/callback?provider=google'
- sorcery.rbの記述を変更
config.google.callback_url = Settings.sorcery[:google_callback_url]
おわりに
いかがでしたでしょうか。この記事が少しでも役立てたら嬉しいです。
また、実務未経験のため間違っている部分や不足があるかもしれません。もし気づいた点等ございましたら、コメントにてご指摘いただけますと幸いです。
参考にしたサイト・記事
Sorcery公式Wiki
GoogleAPI公式サイト
https://zenn.dev/yoiyoicho/articles/c44a80e4bb4515
https://qiita.com/tarakish/items/8e61106fa2473a9d97e8
https://blog.aiandrox.com/posts/tech/2020/03/29/