49
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

個人開発エンジニア応援 - 個人開発の成果や知見を共有しよう!-

【Rails】Sorceryを使用したGoogle認証機能の追加

Last updated at Posted at 2023-10-16

はじめに

こんにちは。未経験からエンジニア転職を目指しプログラミングスクール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を追加します。

app/models/user.rb
class User < ActiveRecord::Base
 has_many :authentications, :dependent => :destroy
 accepts_nested_attributes_for :authentications
end
app/models/authentication.rb
class Authentication < ActiveRecord::Base
 belongs_to :user
end

5. sorcery.rbファイルの設定

sorcery.rbに設定を追加していきます。

config/initializers/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アクションを記述していきます。
ここでは一例を挙げさせていただきます。

oauths_controller.rb
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を設定します

config/routes.rb
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'を使用した方法を記載します。

  • Gemfilegem 'config'を追加し、bundle installを実行してインストール
  • config/settings/ディレクトリ下にdevelopment.ymlproduction.ymlを作成
  • それぞれのファイルに開発環境、本番環境のcallback_urlを記載
config/settings/development.yml
sorcery:
    google_callback_url: 'http://localhost:3000/oauth/callback?provider=google'
config/settings/production.yml
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/

49
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
49
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?