概要
原著者の許諾を得て翻訳・公開いたします。
- 英語記事: Ruby on Rails - OmniAuth authorization - sign in with LinkedIn feature.
- 原文公開日: 2018/02/25
- 著者: Paweł Dąbrowsk
Rails tips: DeviseとOmniAuth認証でLinkedIn機能にサインインする(翻訳)
本記事ではRuby 2.5 + Rails 5.1.4を用います。執筆時点ではいずれも最新です。まずはGemfile
にDevise gemを追加しましょう。
gem 'devise'
続いてbundle install
を実行してPCにgemをインストールしなければなりません。しかしインストールはこれだけでは終わりません。以下のコマンドを実行して、Deviseのイニシャライザファイルと翻訳ファイルを生成しなければなりません。
rails generate devise:install
モデルの生成
これでモデルを生成できるようになりました。認証データを持つモデル名はUser
とするのが普通なので、この名前にします。
rails generate devise user
上のコマンドでDeviseがモデルのクラスとマイグレーションとカラのテストを生成してくれます。User
モデルの内容は次のようになっています。
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
アプリではLinkedInの認証のみを許可したいので、不要なコードを削除します。
class User < ApplicationRecord
devise :trackable, :omniauthable
end
マイグレーションの内容は次のようになっているはずです。
# frozen_string_literal: true
class DeviseCreateRecruiters < ActiveRecord::Migration[5.1]
def change
create_table :users do |t|
t.string :email, null: false, default: ""
## 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
# LinkedIn
t.string :provider
t.string :uid, unique: true
t.timestamps null: false
end
add_index :users, :email, unique: true
end
end
ここではメールとパスワードによる認証は使いたくありませんが、後で使えるようにアプリにはユーザーのメールを保存しておきたいと思います。データベースにテーブルを作成するために以下のマイグレーションを実行しなければなりません。
bundle exec rake db:migrate
不要なカラムが残っていることに気づいた場合は、マイグレーションをロールバックしてファイルを修正し、再度マイグレーションを実行できます。
bundle exec rake db:rollback STEP=1
OmniAuthストラテジーによるLinkedIn認証では、provider
カラムとuid
カラムを使います。
LinkedInの設定
認証にはomniauth-linkedin gemを使いますので、最初にインストールしておきましょう。Gemfile
に以下の行を追加してbundle install
を実行します。
gem 'omniauth-linkedin'
今度はアプリでconsumer_key
とconsumer_secret
キーが必要になります。アプリにこれらがない場合はこちらの記事を参考に作成しておいてください。
config/initializers/devise.rb
にあるDevise gemイニシャライザを開いて、credenntialを追加します。
config.omniauth :linkedin, "consumer_key", "consumer_secret"
これで、User
モデルを更新して認証プロバイダとしてLinkedIn
を使うよう指定できるようになります。
class User < ApplicationRecord
devise :trackable, :omniauthable, omniauth_providers: %i[linkedin]
end
ルーティング
config/routes.rbにdevise_for :users
エントリがあれば、Deviseによって自動的に以下の2つのパスが追加されます。
user_omniauth_authorize_path(provider)
user_omniauth_callback_path(provider)
これで、LinkedIn認証を開始するためのリンクを追加できます。
<%= link_to "Sign in with LinkedIn", user_linkedin_omniauth_authorize_path %>
このリンクをクリックするとLinkedIn認証ページにリダイレクトされます。今度は、コントローラでリクエストを受けて、指定のユーザーをアプリ側で認証する準備をしなければなりません。
認証コントローラ
認証アクションを扱うために、別のコントローラを作成することにします。このコントローラの名前はAuthorizationsController
にしました。LinkedInリクエストを処理するために、linkedin
メソッドとfailure
メソッドの追加が必要です。1番目のメソッドはレスポンスが成功した場合を扱い、2番目は失敗の場合を扱います。
class AuthorizationsController < Devise::OmniauthCallbacksController
def linkedin
end
def failure
redirect_to root_path
end
end
上のコードが機能するには、ルーティングファイルを更新して、LinkedIn認証に使うコントローラがどれであるかをDeviseに伝えなければなりません。
devise_for :users, controllers: { omniauth_callbacks: 'authorizations' }
それでは、ユーザーの作成と検索を担当するコードを実装しましょう。
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
end
end
コントローラを更新して、認証が完全に動作するようにしましょう。
class AuthorizationsController < Devise::OmniauthCallbacksController
def linkedin
@user = User.from_omniauth(request.env["omniauth.auth"])
sign_in_and_redirect @user, event: :authentication
end
def failure
redirect_to root_path
end
end
これでおしまいです。LinkedInネットワーク経由でユーザーを認証できる非常にシンプルな基本アプリを作りました。保存されるのはメールだけです。名前や画像といった他のデータを集めることもできます。可能性は無限なので、何をするかはあなた次第です。
ユーザーが認証されれば、コントローラやビューでcurrent_user
を介してアクセスできるようになります。
お知らせ: RSpec & TDDの電子書籍を無料でダウンロード
もっと稼ぎたい方や会社をさらに発展させたい方へ: テスティングのスキルの重要性にお気づきでしょうか?テストを正しく書き始めることが、唯一のファーストステップです。無料でダウンロードいただける私の書籍『RSpec & Test Driven Developmentの無料ebook』をどうぞお役立てください。