はっさんブログ

技術的なまとめ・話題になっているもの・やっていきを配信する

30分でinstagram-omniauth + Devise でログイン機能を実装してみる

Gemfileに追加

#Gemfile
gem 'instagram-omniauth'

userモデルにdeviseのomniauthableモジュールを追加

# models/user.rb

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable, :confirmable, :omniauthable #=> 追加
end

Omniauthに必要なカラムを追加

$ rails g migration AddColumnsToUsers uid:string provider:string
$ rails db:migrate

Instagram developerに登録してCLIENT KEY、CLIENT SECRETを発行する

https://www.instagram.com/developer/

callback urlは以下のように

http://localhost:3000/users/auth/instagram/callback

以下画面の「MANAGE」でKEY、SECRETを確認できます。 f:id:usgitan:20170915000136p:plain

initializers/devise.rbにomniauthの設定をする

direnv 等に環境変数を登録して使用する。

# initializers/devise.rb

Devise.setup do |config|
  config.omniauth :instagram, ENV['INSTAGRAM_CLIENT_ID'], ENV['INSTAGRAM_CLIENT_SECRET']
end

Userモデルにoauth用のメソッドを追加

# models/user.rb

def self.find_for_oauth(auth)
  User.find_or_create_by(uid: auth.uid, provider: auth.provider) do |user|
      user.email    = User.tmp_email(auth)
      user.password = Devise.friendly_token[0, 20]
  end
end

private

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

OmniauthCallback用のControllerを作成する

# app/controllers/users/omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController

  def instagram
    callback_from :instagram
  end

  private

  def callback_from(provider)
    @user = User.find_for_oauth(request.env['omniauth.auth'])

    if @user.persisted?
      flash[:notice] = "#{provider}でのログインが完了しました。"
      sign_in_and_redirect @user, event: :authentication
    else
      flash[:notice] = "ログインに失敗しました。"
      redirect_to new_user_registration_url
    end
  end
end

ルーティングを追加

# config/routes.rb

devise_for :users, controllers: {
    passwords:          'users/passwords',
    registrations:      'users/registrations',
    confirmations:      'users/confirmations',
    omniauth_callbacks: 'users/omniauth_callbacks' #=> 追加
  }

ルーティング確認 (クリックしてみてね) f:id:usgitan:20170915000655p:plain

任務完了

Deviseで生成したViewに以下のコードがあるので、以上でログイン画面からInstagramログインができます。

# app/views/users/shared/_links.html.slim

- if devise_mapping.omniauthable?
  - resource_class.omniauth_providers.each do |provider|
    = link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider)
    br