#準備
※twitterとfacebookを例にする。基本的に同じパタンなので、googleなど他のSNSも簡単に適用できる。
※deviseは使わない
※私の既存user modelとsession controllerはRailsチュートリアルで書いたものと同じです
##developerアカウント作成、自分のAPPを追加
###Facebook
facebook developer (即時作成できる)
右上のメニューの中から追加したAPPを選択
Settings-Basic
からAPP IDとAPP SECRETを取得し、他のAPP情報も入力(ユーザ承認画面で表示される)
PRODUCTSのところでFacebook Loginを追加し、Settings
からValid OAuth Redirect URIs(https://domain_name/auth/facebook/callback) を入力
※セキュリティの関係で、facebookは今httpsのurlしか承認しないので、localhostは使えないです。実行してみたいならherokuにappをデプロイすることがおすすめです。※
###Twitter
twitter developer (審査するには少し時間かかる)
右上のメニューの中から追加したAPPを選択
Keys and tokens
からConsumer API keys (API key+API secret key)を取得
App details
からCallback URL(http://localhost:3000/auth/twitter/callback 他複数追加可)を入力、他のAPP情報も入力(ユーザ承認画面で表示される)
##gem追加
gem 'omniauth'
gem 'omniauth-twitter'
gem 'omniauth-facebook'
##環境設定
./config/initializers/omniauth.rb
というファイルを作成
Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, ENV['TWITTER_ID'], ENV['TWITTER_SECRET']
provider :facebook, ENV['FACEBOOK_ID'], ENV['FACEBOOK_SECRET']
end
追加可能なオプションのパラメータは
omniauth-facebook (github)
omniauth-twitter (github)
で確認できる。
例えばこんな感じ:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, ENV['TWITTER_ID'], ENV['TWITTER_SECRET'],
{ :image_size => 'original', :authorize_params => { :lang => 'ja' } }
provider :facebook, ENV['FACEBOOK_ID'], ENV['FACEBOOK_SECRET'],
{ display: 'page', image_size: 'normal' }
end
ENV['XXX']
は環境変数です。XXXは自分で命名できます。
###localhostで設定したい場合
(特にwindowsユーザはこの方法が一番便利かなと思う)
./config/local_env.yml
というファイルを作成 (facebookはlocalhost実行不可なので省略)
TWITTER_ID: '自分のAPP_ID'
TWITTER_SECRET: '自分のAPP_SECRET'
./.gitignore
というファイルに下記のコードを追加(自分のkeyをgithubなどで公開しないように)
/config/local_env.yml
###herokuで設定したい場合
$ heroku config:set TWITTER_ID=自分のAPP_ID
$ heroku config:set TWITTER_SECRET=自分のAPP_SECRET
$ heroku config:set FACEBOOK_ID=自分のAPP_ID
$ heroku config:set FACEBOOK_SECRET=自分のAPP_SECRET
#各ファイルを更新
##ルーティング
get 'auth/:provider/callback', to: 'sessions#create'
これが各developerアカウントのAPP設定で入力したredirect/callback URLになります
##ユーザモデル
#auth hashからユーザ情報を取得
#データベースにユーザが存在するならユーザ取得して情報更新する;存在しないなら新しいユーザを作成する
def self.find_or_create_from_auth(auth)
provider = auth[:provider]
uid = auth[:uid]
name = auth[:info][:name]
image = auth[:info][:image]
#必要に応じて情報追加してください
#ユーザはSNSで登録情報を変更するかもしれので、毎回データベースの情報も更新する
self.find_or_create_by(provider: provider, uid: uid) do |user|
user.username = name
user.image_path = image
end
end
$ rails g migration add_columns_to_users
class AddColumnsToUsers < ActiveRecord::Migration[5.0]
def change
add_column :users, :uid, :string
add_column :users, :provider, :string
end
end
$ rails db:migrate
##セッションコントローラ
def create
auth = request.env['omniauth.auth']
if auth.present?
user = User.find_or_create_from_auth(request.env['omniauth.auth'])
session[:user_id] = user.id
redirect_back_or user
else #既存パタン
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
log_in user
params[:session][:remember_me] == '1' ? remember(user) : forget(user)
redirect_back_or user
else
flash.now[:danger] = 'メールアドレスとパスワードの組み合わせは有効ではありません'
render 'new'
end
end
end
##ユーザモデルのバリエーション
これだけじゃまだ動けない!
なぜなら、user modelでは色々なバリデーションがあるので、
self.find_or_create_by(provider: provider, uid: uid)
という行でエラー発生。
※私のappではSNSアカウントでログインするならemailとpasswordがいらないので、バリデーションを以下のように修正した:
validates :username, presence: true, unless: :uid? #他省略
validates :email, presence: true, unless: :uid?
has_secure_password validations: false
validates :password, presence: true, unless: :uid?
unless: :uid?
というのは、
uidデータがあればusername, email, passwordデータなしでもUser.create()
使えるようになります
##ビュー
###普通のテキストリンクでテストする場合
ログイン画面に追加
<%= link_to "Twitterアカウントでログイン", "/auth/twitter" %>
<%= link_to "Facebookアカウントでログイン", "/auth/facebook" %>
gem 'bootstrap-social-rails'
gem 'font-awesome-rails'
@import "bootstrap-social";
@import "font-awesome";
<p>
<%= link_to '/auth/twitter', class: "btn btn-social btn-twitter" do %>
<span class="fa fa-twitter"></span> Twitterアカウントでログイン
<% end %>
</p>
<p>
<%= link_to '/auth/facebook', class: "btn btn-social btn-facebook" do %>
<span class="fa fa-facebook"></span> Facebookアカウントでログイン
<% end %>
</p>
<p>
<%= link_to '/auth/google_auth2', class: "btn btn-social btn-google" do %>
<span class="fa fa-google"></span> Googleアカウントでログイン
<% end %>
</p>