やりたいこと
- いろんなところに Sign in/ Sign up ボタンある
- Sign in/ Sign up後に元いたページとか適切な場所に戻ってこれる
- 当たり前だけど各ページに認証関連のコードは書きたくない。Controller 1個に集約したい
概要
パラメータ名を state にすると、認証後まで持って帰って来てくれる。
ので、stateに必要な情報を入れておいて戻ってきたら redirect などなどすれば良い。
実際のところ
sessions コントローラでやります。ルーティングは、Omniauthのいつもの感じ。
match "/auth/:provider/callback" => "sessions#user_sign_in_up", :via => [:get, :post]
get 'sessions/sign_out' => 'sessions#user_sign_out'
Viewに設置するボタンは、今回、Sign in / Sign up を別ボタンにしました。
Sign in でアカウント未登録ならハネるし、Sign up でアカウント登録済でもハネます。
= button_to 'Sign in', '/auth/google', { method: :get, class: 'btn btn-info', params: { state: { action: 'sign_in', return_to: '/', } } }
= button_to 'Sign up', '/auth/google', { method: :get, class: 'btn btn-info', params: { state: { action: 'sign_up', return_to: '/targets/new', } } }
stateの中に、action(Sign in なのか、Sign up なのか)と、return_to(戻り先)を入れて送っておきます。
まだ実装していませんが、Sign up 前にもなにかサービス利用が出来て、そのデータをとっておきたい場合も、stateの中に保持することになるかと。
パラメーターでデータを持ち回るのは色んな意味でダメなので、適切なテーブルに保存しておいてidだけ渡す感じになると思います。
パラメータは、request.env["omniauth.params"]でとれます。
stateの中身は、action=sign_in とかのテキストになってるのでパースします。
あとは仕様通りに。今回は、セキュリティを意識して、認証失敗の時は追加情報を出さない感じに作ってます。
class SessionsController < ApplicationController
def user_sign_in_up
auth = request.env["omniauth.auth"]
state = Rack::Utils.parse_nested_query request.env["omniauth.params"]['state']
button_action = state['action']
return_to= state['return_to']
if current_user
notice_or_alert={ alert: "Already sigend in." }
else
case button_action
when 'sign_in'
user = User.find_by(provider: auth["provider"], uid: auth["uid"])
when 'sign_up'
user = User.create_with_omniauth(auth)
else
notice_or_alert={ alert: "Sign in / Sign up failed." }
end
if user && user.active
session[:access_token]= user.access_token
notice_or_alert={ notice: "Signed in." }
else
notice_or_alert={ alert: "Sign in / Sign up failed." }
end
end
redirect_to return_to || root_url, notice_or_alert
end
def user_sign_out
session[:access_token] = nil
redirect_to root_url
end
end
参考にさせて頂いたサイト
Thanks a lot!
http://stackoverflow.com/questions/9890985/passing-parameters-through-omniauth
http://bang.hateblo.jp/entry/2012/10/09/002003