Ruby
Rails
OmniAuth
omniauth-google-oauth
omniauth-google-oauth2

Omniauth-google-auth2 だけで、DB に保存せず認証する

More than 1 year has passed since last update.

要件的に、「ユーザーデータを保存はしないけど Google 認証だけはしたい」という条件があって、巷では Devise を使った例しか見つからなかったので記事にしてみます。

環境: Ruby 2.3.1, Rails 4.2.6 / 5.0.1 1


事前準備

Google で client_id, client_secret を発行しておく。また、リダイレクト先の許可設定もしておく。リダイレクト先は /auth/xxxx/callback の形にしておくと、のちに困らないはず。今回は xxxx のところを

google_oauth にして、 /auth/google_oauth/callback としてみます(*1)


コーディング


Gem 追加


Gemfile

gem "omniauth-google-oauth2"


を Gemfile に追記して、 bundle install をする


ベースとなる Controller の実装

名前はなんでもいいのですが、ここでは LoginedApplicationController というのを用意して、ログイン状態で使う Controller は全てこれを継承するみたいな想定で作ります。

class LoginedApplicationController < ApplicationController

before_action :authenticate

def authenticate
# session がなかったら
# Google に redirect する
# url は、 /auth/google_oauth (Google にリダイレクト先を登録したときの google_oauth 。 *1 参照) にすると、 OmniAuth が飛ばしてくれる
end
end


callback 先となる部分を用意する

名前はなんでもいいのですが、ここでは例として CallbacksController という名前にします (*2)。

メソッド名もなんでもいいのですが、ここでは omniauth_google という名前にしています (*3)。


app/controllers/callbacks_controller.rb

class CallbacksController < ApplicationController # *2

#
# 当たり前ですが LoginedApplicationController を継承してしまうと無限ループしちゃうので、
# Callback 用メソッドが呼ばれた時には authenticate メソッドが実行されないようにする
#
# この例では親クラスを分けることによってそれを実装している。
# before_action に if 文を噛ませるなどの対応でも OK

def omniauth_google # *3
# session にセットして、アプリケーションの画面に redirect する
end
end



config/routes.rb

  # callback を、さっき作った callback 先メソッドに流せるように書く

# match のあとに書くのは *1、 actionとして書くのは *2 と *3
match "/auth/google_oauth/callback" => "callbacks#omniauth_google", :via => [:get]


omniauth の設定をしておく


config/initializer/omniauth.rb

Rails.application.config.middleware.use OmniAuth::Builder do

provider :google_oauth2, ENV['FOOBAR_GOOGLE_CLIENT_ID'], ENV['FOOBAR_GOOGLE_CLIENT_SECRET'],
{name: "google_oauth", approval_prompt: ''}
# name には、Google にリダイレクト先として登録したはずのパスの後半部分 (*1)
end

んで、環境変数として FOOBAR_GOOGLE_CLIENT_IDFOOBAR_GOOGLE_CLIENT_SECRET に適切な値を入れる

これでよし


Advanced


ユーザーを取る

上記で説明した authenticate メソッドで

  def authenticate

if request.env['omniauth.auth'].present? && request.env['omniauth.auth']["info"].present?
session['google_data'] = request.env['omniauth.auth']["info"]

としておいて

 def current_user

authenticate

@current_user ||= session['google_data']
end


Tips / Troubleshooting


CookieOverflowError

Google から返却されたユーザーデータを全部 session に入れると、 CookieOverflowError に遭遇する。外部ストレージを検討するか、 session には必要なものだけを入れる





  1. Rails 4 系でこの実装をしたあとにおもむろに Rails のバージョンもあげてみたけど普通に動いてたので、たぶん大丈夫