LoginSignup
27

More than 3 years have passed since last update.

Rails5.1でGithubログインを実装する

Last updated at Posted at 2018-10-01

0. はじめに

お初にお目にかかります!!
toramaruJPです(`・ω・´)

昨日オリジナルアプリを作成しました!!
日頃からQiitaさんにはお世話になっているので、少しでも貢献できたらと思い、オリジナルアプリに導入したGithubログイン実装方法を記載したいと思います。
改善点等あった際には、ご指摘して下さると嬉しいです(´꒳`)

1. 実装概要

(1)Github連携の準備をしよう!(Github上)
(2)Github連携の準備をしよう!(実装上)
(3)Deviseを用いて、Githubログインを実装しよう!

2. 実装詳細

(1)Github連携の準備をしよう!(Github上)

スクリーンショット 2018-10-01 18.14.28.png
まず、上記画像の右上の"Settings"タブを押します。
スクリーンショット 2018-10-01 18.14.55.png
次に、左下の"Developer settings"タブを押します。
スクリーンショット 2018-10-01 18.09.32.png
そうすると、上記画像のような画面になるので、右上の"New OAuth APP"を押します。
スクリーンショット 2018-10-01 18.22.13.png
Localで動かす場合には、画像のように
・"Application name"には"アプリケーション名-development"
・"Homepage URL"には"http://localhost:3000/"
・"Authorization callback URL"には"http://localhost:3000/users/auth/github/callback"
と記載します。

最後に、"Register application"ボタンを押すと、完了です。
そうすると、"Client ID"と"Client Secret"が作成されます。
後ほど使うので、メモしておきましょう。
※ "Client ID"と"Client Secret"は、作成されたアプリケーション名をクリックした先の詳細に記載されてあるので、そこで確認できます。

(2)Github連携の準備をしよう!(実装上)

(a) アプリを立ち上げよう!

開発で使用するバージョンは以下の通りです。

Rails v5.1.6
ruby v2.3.1

下記コマンドで現在のバージョンを確認できます。

$ ruby -v
$ rails -v

rails newコマンドを使用してアプリの立ち上げを行います。

$ rails _5.1.6_ new oauth -d postgresql

下記のコマンド実行後、"http://localhost:3000/"
にアクセスをして、サーバーが立ち上がるか確認しましょう。

$ rails s

(b) OAuth認証に必要なGemをインストールしよう!

下記をGemfileに追記し、"bundle install"を行なってください。

Gemfile
省略

gem 'devise'
gem 'omniauth'
gem 'omniauth-github'

省略
$ bundle install

各ReadMe
・devise - https://github.com/plataformatec/devise
・omniauth - https://github.com/omniauth/omniauth
・omniauth-github - https://github.com/omniauth/omniauth-github

(c) Deviseの設定をしよう!

以下のコマンドを打ち、deviseに必要な設定ファイルを作成します。

$ rails g devise:install

これで、準備が整いました。

(3)Deviseを用いて、Githubログインを実装しよう!

(a) ユーザーテーブルを作成しよう!

$ rails g devise user

作成されたマイグレーションファイルを下記のように編集しましょう。

class DeviseCreateUsers < ActiveRecord::Migration[5.1]
  def change
    create_table :users do |t|
      ## Database authenticatable
      t.string :name,               null: false, default: ""
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""
      t.string :provider, null: false, default: ""
      t.string :uid, 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.inet     :current_sign_in_ip
      # t.inet     :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, :name,                 unique: true
    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    add_index :users, [:uid, :provider], unique: true
    # add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end
end

マイグレーションファイルを編集できたら
下記コマンドを実行してテーブルの作成を行います。

$ rails db:migrate

(b) users/registration_controllerを作成して、deviseのコントローラーを継承しよう!

下記のコマンドを実行します。

$ rails g controller users::registrations

作成されたファイルを、以下のように編集してください。

app/controllers/users/registrations_controller
class Users::RegistrationsController < Devise::RegistrationsController
  def build_resource(hash={})
    hash[:uid] = User.create_unique_string
    super
  end
end

※ 上記"build_resource(hash={})"メソッドは、継承元の同メソッドをオーバーライドしています。具体的には、uidにランダムな値を代入しています。
下記において、継承元の同メソッドが確認できます。
https://github.com/plataformatec/devise/blob/bcdd54cc5ebd3413eeb3d17e3b634e8ace0d09f3/app/controllers/devise/registrations_controller.rb

(c) create_unique_stringメソッドを作成しよう!。

下記ファイルに、下記メソッドを追記してください。

app/models/user.rb
  def self.create_unique_string
    SecureRandom.uuid
  end

(d) ルーティングを追加しよう!

config/routes.rb
  devise_for :users, controllers: {
    registrations: "users/registrations"
  }

(e) modelを編集しよう!

下記ファイルを、下記のように編集してください。

app/models/user.rb
  devise :database_authenticatable, :registerable,
       :recoverable, :rememberable, :validatable,
       :omniauthable, omniauth_providers: %i(github)

下記ファイルに、下記メソッドを追記してください。

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.new(provider: auth.provider,
                      uid:      auth.uid,
                      name:     auth.info.name,
                      email:    User.dummy_email(auth),
                      password: Devise.friendly_token[0, 20]
      )
    end
    user.save
    user
  end
app/models/user.rb
  def self.dummy_email(auth)
    "#{auth.uid}-#{auth.provider}@example.com"
  end

現時点における該当modelは下記のようになります。

app/models/user.rb
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :omniauthable, :confirmable, omniauth_providers: %i(google facebook github)

  def self.create_unique_string
    SecureRandom.uuid
  end

  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.new(provider: auth.provider,
                      uid:      auth.uid,
                      name:     auth.info.name,
                      email:    User.dummy_email(auth),
                      password: Devise.friendly_token[0, 20]
      )
    end
    user.save
    user
  end

  def self.dummy_email(auth)
    "#{auth.uid}-#{auth.provider}@example.com"
  end

(f) githubで取得したOAuth認証に必要な値("Client ID"と"Client Secret")を読み込む設定をしよう!

下記ファイルに、下記記述を追記してください。

config/initializers/devise.rb
Devise.setup do |config|

  省略

  config.omniauth :github, ENV["GITHUB_ID"], ENV["GITHUB_SECRET"], scope: 'user,public_repo'

  省略

end

(g) .envファイルを作成しよう!

アプリケーションディレクトリ直下に下記ファイルを作成し、下記記述を追加してください。

.env
  GITHUB_ID=メモした"Client ID"
  GITHUB_SECRET=メモした"Client Secret"

セキュリティ上、githubにプッシュさせない為、下記ファイルに下記記述を追記してください。

.gitignore
  .env

.envに記載した環境変数を認識させる為に、"dotenv"というgemをインストールしてください。

Gemfile
  gem 'dotenv-rails'
 $ bundle install

(h) ログインボタンのリンクを設置するViewを作成しよう!

下記コマンドをターミナルで実行する。

 $ rails g controller oauth_test index

作成されたViewファイルにログインボタンのリンクを設置します。

app/views/oauth_test/index.html.erb
 <p><%= notice %><%= alert %></p>
 <% if user_signed_in? %>
   <%= link_to "ログアウト", destroy_user_session_path, method: :delete %>
 <% else %>
   <%= link_to 'githubでサインアップしてね', user_github_omniauth_authorize_path %>
 <% end %>

ルーティングを再設定します。

config/routes.rb
  devise_for :users, controllers: {
    registrations: "users/registrations",
    omniauth_callbacks: "users/omniauth_callbacks"
  }

(i) コールバック処理のコントローラーを作成しよう!

下記ディレクトリに下記ファイルを作成し、下記を記述してください。

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?
    else
      session["devise.github_data"] = request.env["omniauth.auth"]
      redirect_to new_user_registration_url
    end
  end
end

(j) コールバック先のルーティングを設定しよう!

下記ファイルに下記記述を追記します。

config/routes.rb
 root :to => 'oauth_test#index'

(k) フラッシュメッセージを表示させよう!

下記ファイルに下記記述を追記します。

app/views/layouts/application.html.erb

 省略

 <body>
   <% if notice %>
     <p class="alert alert-notice"><%= notice %></p>
   <% end %>
   <% if alert %>
     <p class="alert alert-error"><%= alert %></p>
   <% end %>

   <%= yield %>

省略

以上になります!!!!!!
これで、"githubでサインアップしてね"リンクをクリックすれば、githubログイン認証してくれるはずです!!!!!

できなかったら( ゚д゚)( ゚д゚)
問題点を教えて頂けると嬉しいです(`・ω・´)

3. 最後に

初めて書きましたが、大変ですねこれ( ゚д゚)
書くのとまとめるのが大変( ゚д゚)
いっぱい書いてる人凄いな( ゚д゚)

ただ、自分の為にもなるのでこれからも書き続けます!!
最後まで見て頂いてありがとうございます!!

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
27