3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【rails】OAuthを用いて、GitHub認証ログイン機能を実装する

Posted at

やりたいこと

  • deviseのomniauthableの機能でgithubログインを実装する

  • ログイン,サインアップからgithubログインができるようにする。

  • 挙動

    • サインアップ、ログイン画面より「GitHub認証」のボタンを押下
    • GitHubのログイン画面へ遷移しid,パスを入力しログインボタンを押下
    • github上で認証するためのトークンを発行し、それをWebサイト側で検証
    • 上記が認証されるとトップ画面へ遷移する。

image.png

調査

  • 必要なこと
    • omniauthableの実装に必要なgemをインストールする。
    • GitHubにてOAuthアプリを作成する。
    • 上記で生成されたCLIENT_IDとSECRET_PASSをenvファイルへ記述
    • controllerにて上記認証情報の処理を記述(むずい)
    • モデルのメソッドにて上記paramsをuserテーブルへの保存するためのメソッドを記述
    • User modelに:omniauthable を追加
    • viewの実装を行う

実際にやったこと

ライブラリ関連

  • Gemfileに以下を記述→bundle install
gem 'omniauth'
gem 'omniauth-github'
gem 'omniauth-rails_csrf_protection'
group :development, :test do
  gem 'dotenv-rails'
end

[Rails]deviseとomniauthによるgithubログイン

OAuthのID,パス生成

image.png

【2021年4月現在】GitHubのClient IDとClient secretsを取得する手順 - No day younger than today

#上記にて自分で設定したkeyを設定
GITHUB_ID = '*********'
GITHUB_SECRET = '********'
  • 記述した.envファイルは外部に漏れないように gitignore ファイルに記述
# Ignore env File
/.env
  • /initializers に上記ENVファイルにて設定した環境変数を記述し読み込めるようにする
  # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  config.omniauth :github, ENV['GITHUB_ID'], ENV['GITHUB_SECRET'], scope: 'user,public_repo'

DB関連

  • rails g migration AddOmniauthToUsers にてmigrationファイルを生成
  • →以下記述し、 rails db:migrate
class AddOmniauthToUsers < ActiveRecord::Migration[7.0]
  def change
    add_column :users, :uid, :string
    add_column :users, :provider, :string, null: false, default: ""

    add_index :users, %i[uid provider], unique: true
  end
end
  • app/models/user.rb に, omniauthable モジュールと、validationを記述
# frozen_string_literal: true

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  validates :name, presence: { message: "can't blank" }
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :confirmable, :lockable, :timeoutable, :trackable,:omniauthable, omniauth_providers: %i[github]
                                                            #追加

  validates :birth_day, presence: { message: "can't blank" }
  validates :tel_number, presence: { message: "can't blank" }
  
  #追加
  validates :uid, uniqueness: { scope: :provider }, if: -> { uid.present? }
end

routeの設定

Rails.application.routes.draw do
  〜略
  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks'}
  
end

controllerの設定

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  skip_before_action :verify_authenticity_token, only: :github
  
  def github
    @user = User.from_omniauth(request.env['omniauth.auth'])

    if @user.persisted?
      sign_in_and_redirect @user, event: :authentication
      set_flash_message(:notice, :success, kind: "Github") if is_navigational_format?
    else
      session["divise.github_data"] = request.env["omniauth.auth"].except(:extra)
      redirect_to new_user_registration_url
    end
  end

  def failure
    redirect_to root_path
  end
end

user.rbモデルにメソッド設定

# frozen_string_literal: true

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  validates :name, presence: { message: "can't blank" }
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :confirmable, :lockable, :timeoutable, :trackable,:omniauthable, omniauth_providers: %i[github]
  validates :birth_day, presence: { message: "can't blank" }
  validates :tel_number, presence: { message: "can't blank" }

  validates :uid, uniqueness: { scope: :provider }, if: -> { uid.present? }

  #追記
  def self.form_omniauth(auth)
    where(uid: auth.uid, provider: auth.provider).first_or_create! do |user|
      user.email = auth.info.email
      user.password = Devise.friendly_token[0,20]
      user.name = auth.info.name
      user.birth_day = Date.parse('1993-04-21')
      user.tel_number = '12345678'.to_i
    end
  end
end

  • first_or_createについて

覚えておくと幸せになれるActiveRecord::Relationメソッド6選 - Qiita

viewの設定

  • app/views/shared/_link.html.slim のomniauthボタンのroutingの変更
 #〜省略

- if devise_mapping.omniauthable?
  - resource_class.omniauth_providers.each do |provider|     #変更
    = button_to " #{OmniAuth::Utils.camelize(provider)}で続ける", user_github_omniauth_authorize_path(resource_name, provider), data: { turbo: false } ,class: "btn btn-primary"
  br
  • Githubログイン用のボタンがサインアップ画面とログイン画面に表示される

image.png

image.png

結果

  • 「Githubで続ける」を押下してログインしようと試みるとNot found. Authentication passthru. とエラーが表示されて認証が通らなかった。

image.png

原因究明と解決

  • passthruは聞きなれない単語だが passthrough(=通過する、素通りする)と同じ意味

passthru - Weblio 英和・和英辞典

  • ログを確認すると認証用パラメータは生成されているように見える。

image.png

  • つまり生成された認証paramasが入力→出力へ「内部で何もせず素通り(pass through)」しているということ? 正しくparamsが送られてない?

パススルーとは - IT用語辞典

  • deviseの公式ドキュメントを確認すると、ボタンのmethodにpostを指定するように記述されていた。ただ、button_to場合は必要なく、link_toの場合は method: :post の追記が必要
  • button_to を用いて下記設定したが解消されず。
- if devise_mapping.omniauthable?
  - resource_class.omniauth_providers.each do |provider|
    = button_to " #{OmniAuth::Utils.camelize(provider)}で続ける", user_github_omniauth_authorize_path ,class: "btn btn-primary"
  br

  • config/initializers 直下に omniauth.rb を作成し、以下記述
Rails.application.config.middleware.use OmniAuth::Builder do
  OmniAuth.config.allowed_request_methods = [:post, :get]
end

→これによりpostとgetメソッドが許可されるので、送られてきた認証paramasが素通りせず、受け取られるはず

  • サインアップ画面が表示されたのでid,passを入力すると、、、

image.png

  • 今度はrouting errorが表示された。エラー画面では /auth/github/callback のrouteがないと怒られている。

image.png

  • 改めて config/route を確認すると, omniauth_callbacks: 'users/omniauth_callbacks' と設定しているので、callbackの接続するパスは users/auth/github/callback となるはず。
Rails.application.routes.draw do

  devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth_callbacks'}
end

image.png

  • 今度は認証画面に遷移することができた。Authorizeをクリックすると無事にログインすることができた!!

image.png

参考

3
2
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
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?