#はじめに
実装する度に検索するのも面倒なので、この際にまとめます。
理解すべきところはそれについて言及しています。
追記
こちらも参考になります。
Devise+OmniAuthでユーザ認証を実装する手順
#対象読者
自分のサービスにソーシャルログインを追加したい人
#omniauthとは
Webアプリケーションのログイン認証を、複数のプロバイダを通して行うことができるgemです。
新規登録の際によくある、Twitter・Facebookでログインはこれを使って実装できます。
#事前準備
Userモデルを作成します。
カラム名は使用したいデータに合わせて変更してください。
rails g model user provider:string uid:string nickname:string image_url:string
rails g model user name:string provider:string uid:text oauth_token:string
Gemfile
にgem omniauth
, gem omniauth-twitter
を追加。
gem 'omniauth'
gem 'omniauth-twitter'
omniauth.rb
を作成し、以下を記述。
Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET']
end
middlewareとは?自分で作れるの?と思って調べました
Webサーバーがフレームワークとデータのやりとりをする場所です。
自作すると色々できておもしろそう。
Twitter Application Managementでキーを発行します。
そしてdirenvで.envrc
を作成し、管理します。
direnv edit .
export TWITTER_KEY="xxxxxxxxxxxxxxxxx"
export TWITTER_SECRET="xxxxxxxxxxxxxxxxxxxxxx"
さて、モデルから作成していきます。
class User < ActiveRecord::Base
def self.find_or_create_from_auth(auth)
provider = auth[:provider]
uid = auth[:uid]
nickname = auth[:info][:nickname]
image_url = auth[:info][:image]
self.find_or_create_by(provider: provider, uid: uid) do |user|
user.nickname = nickname
user.image_url = image_url
end
end
end
find_or_create_from_auth
はDBにユーザーがいれば持ってきて、なければ作るという処理です。
次にsessionsコントローラーを作成し、以下を記述します。
class SessionsController < ApplicationController
def create
user = User.find_or_create_from_auth(request.env['omniauth.auth'])
session[:user_id] = user.id
redirect_to root_path
end
def destroy
reset_session
redirect_to root_path
end
end
次に、application_controller.rb
にヘルパーメソッドを記述していきます。
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :current_user, :logged_in?
private
def current_user
return unless session[:user_id]
@current_user ||= User.find(session[:user_id])
end
def logged_in?
!!session[:user_id]
end
def authenticate
return if logged_in?
redirect_to root_path, alert: 'ログインしてください'
end
end
helper_method :メソッド名
で指定すると、そのメソッドがViewでも扱えるようになります。
ユーザーの識別やログインしているかどうかを返すメソッドを指定するとViewがすっきりします。
logged_in?
の!!
は返り値がnil
の場合、nil
ではなくfalse
を返すようにしています。
メソッド名が真偽値であるため、false
で帰ったほうがより良いと思います。
次に、route.rb
にログイン・ログアウトのルーティングを設定します。
Rails.application.routes.draw do
get 'auth/:provider/callback', to: 'sessions#create'
get '/logout', to: 'sessions#destroy'
root 'homes#top'
end
最後に、Viewにログイン・ログアウト用のリンクを記述し、終了です。
- if logged_in?
= link_to 'ログアウト', logout_path
- else
= link_to 'Twitterでログイン', 'auth/twitter'
401が発生する場合は、twitter developerの方でアクセストークンを発行し直したり、
.envrc
に不必要な空白がはいってないか確認してください。(僕はこれでした)
#facebook-omniauth
[試してないけど参考にされたい]
(http://www.workabroad.jp/posts/2099)
instagram-omniauth
[30分でinstagram-omniauth + Devise でログイン機能を実装してみる]
(http://www.hassansan.me/entry/2017/09/15/000826)
#github-omniauth
Github developer settings
上記のリンクでアプリケーションを登録します。
Homepage Urlにはhttp://localhost:3000
Authorization callback URLにはhttp://localhost:3000/auth/github/callback
と入力しましょう。
実際の運用では、本番環境用のURLを新規に作ることをオススメします。
gem 'omniauth'
gem 'omniauth-github'
Rails.application.config.middleware.use OmniAuth::Builder do
provider :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET'], scope: "user,repo"
end
データ取得のscope指定はサービスに合わせて設定します。
def self.create_with_omniauth(auth)
create! do |user|
user.provider = auth['provider']
user.uid = auth['uid']
user.name = auth['info']['nickname']
user.oauth_token = auth['credentials']['token']
end
end
class SessionsController < ApplicationController
def callback
auth = request.env['omniauth.auth']
user = User.find_by(provider: auth['provider'], uid: auth['uid']) || User.create_with_omniauth(auth)
session[:user_id] = user.id
redirect_to root_path
end
def destroy
reset_session
redirect_to root_path
end
end
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :current_user, :logged_in?
private
def current_user
return unless session[:user_id]
@current_user ||= User.find(session[:user_id])
end
def logged_in?
!!session[:user_id]
end
def authenticate
return if logged_in?
redirect_to root_path, alert: 'ログインしてください'
end
end
Rails.application.routes.draw do
get 'auth/:provider/callback', to: 'sessions#callback'
get '/logout', to: 'sessions#destroy'
root 'homes#top'
end
- if logged_in?
= link_to 'Sign out', '/signout'
- else
= link_to 'Githubアカウントでログイン', '/auth/github'
最後に
ログインはちょちょいと乗り越えて、サービスの核を作りこみましょう!