LoginSignup
4
3

More than 5 years have passed since last update.

Omniauthで認証時に、パラメータを持ち帰る

Posted at

やりたいこと

  • いろんなところに Sign in/ Sign up ボタンある
  • Sign in/ Sign up後に元いたページとか適切な場所に戻ってこれる
  • 当たり前だけど各ページに認証関連のコードは書きたくない。Controller 1個に集約したい

概要

パラメータ名を state にすると、認証後まで持って帰って来てくれる。
ので、stateに必要な情報を入れておいて戻ってきたら redirect などなどすれば良い。

実際のところ

sessions コントローラでやります。ルーティングは、Omniauthのいつもの感じ。

ruby:routes.rb (抜粋)
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 でアカウント登録済でもハネます。

hoge.html.haml
= 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 とかのテキストになってるのでパースします。
あとは仕様通りに。今回は、セキュリティを意識して、認証失敗の時は追加情報を出さない感じに作ってます。

sessions_controller.rb
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

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3