何かやってみるブログ

興味をもったことに関して書いています。技術系の記事が多いです。

GiHub OAuthでのログイン・登録機能をRailsで実装する(超初心者向け)

今回は、GitHubのOAuthを試してみたときのメモです。

実装環境

それではGitHubのOAuthを実装していきましょう。

(i) Deviseと関連gemのインストール

gem 'devise'
gem 'omniauth'
gem 'omniauth-github'
bundle してインストールします。

(ii) Deviseの設定とUserモデルを作成

メールの受信には letter_opner_webというgemを使っていきます。READMEを参考に設定します。

参考記事

github.com

github.com

DeviseのREADME.mdを参考にDeviseの初期設定をして、Userモデルを作成します。

$rails g devise User

今回は、メールアドレスで登録したユーザーには登録したアカウント有効化メールを送りたいのでConfirmableのコメントを有効化します。 migrationファイルはこんな感じです。

class DeviseCreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # t.integer  :sign_in_count, default: 0, null: false
      # t.datetime :current_sign_in_at
      # t.datetime :last_sign_in_at
      # t.string   :current_sign_in_ip
      # t.string   :last_sign_in_ip

      ## Confirmable
      t.string   :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at
      t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

(iii) このリンクに飛んで、APIの設定をしていきます。

f:id:s-takaya1027:20191109073858p:plain

Application nameにはアプリケーション名、今回はローカルで試したいのでHomepage URLには「http://localhost:3000.com」、Deviseとその他もろもろを使っていきたいので、Callbackに「http://localhost:3000/users/auth/github/callback」とします。

[注意] Client IDとClient Secretは外部にもれないようにしましょう。

(iv) Deviseのwikiを参考にログイン・登録を実装

参考記事 OmniAuth: Overview · plataformatec/devise Wiki · GitHub

上記のDeviseのwikiにサンプルコードがあったので、これを参考に実装していきます。

group :development, :test do
  gem 'dotenv-rails'
end

bundle してインストールします。

  • .envファイルを作成して、Client IDとClient Secretの環境変数を設定していきます。
CLIENT_ID=◯◯◯◯◯◯◯
CLIENT_SECRET=◯◯◯◯◯◯◯

gitで管理している場合はgitignoreを設定して外部にClient IDとClient Secretが漏れないようにしましょう.

  • providerとuidを格納するためのカラムをusersテーブルに追加します。
$rails g migration AddOmniauthToUsers provider:string uid:string
$rails db:migrate
  • 参考記事を元にDeviseにGitHubの設定をしていきます。
 config.omniauth :github, ENV['CLIENT_ID'], ENV['CLIENT_SECRET'],scope: "user,repo,gist"

scopeにユーザーからとってきたい情報を指定することができます。今回はomniauth-githubのREADME通りにuserとrepoとgistを指定します。 その他にもscopeに指定できるみたいですね。

developer.github.com

次にuserモデルにマウントの処理を書きます。

 devise :omniauthable, omniauth_providers: %i[github]

そしてログインリンクを設置していきます。

<%= link_to "GitHubでログイン/登録する", user_github_omniauth_authorize_path %>

このリンクからコールバック(同意画面的なやつ) に進むことが出来ます。

  • ログイン登録機能の実装

DeviseにOmniauthCallbacksControllerがあるので、これを継承したコントローラーを作成してログイン・登録機能を実装します。

devise/omniauth_callbacks_controller.rb at master · plataformatec/devise · GitHub

$rails g controller users::omniauth_callbacks 

デフォルトではApplicationControllerを継承していますが、omniauth_callbacks_controllerに書き換えましょう!! そして記事を参考に実装します。

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def github 
     @user = User.from_omniauth(request.env['omniauth.auth']) #ここの処理をuserモデルで実装

     if @user.present?
      sign_in_and_redirect @user, event: :authentication>
      set_flash_message(:notice, :success, kind: "Github") if is_navigational_format?
    else
      session["devise.github_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end
  
  def failure
    redirect_to root_path
  end

end

githubアクションで、ユーザーが存在すればログインしてrootページにリダイレクトする処理を書いています。 3行目のfrom_omniauthというクラスメソッドでユーザーのアカウントがなければアカウントを作成し、あればスルーする という処理を書きます。コードは以下の通りです。

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,:confirmable ,:omniauthable, omniauth_providers: %i[github]

  # ここでユーザーのアカウントがなければアカウントを作成し、あればスルーする
  def self.from_omniauth(auth)
     where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
       user.email = auth.info.email 
       user.password = Devise.friendly_token[0,20]
       user.skip_confirmation!
     end
  end

end

以上でGitHubの登録・ログイン機能が実装できました