160
163

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SpeeeAdvent Calendar 2015

Day 15

爆速ッ!! gem omniauth-google-oauth2 で認証させる

Last updated at Posted at 2015-12-15

Railsでユーザ認証させる

鉄板のDevise + Omniauthの組み合わせですが、意外とomniauth-google-oauth2に関する記事は少なそうだったので、備忘録+写真で解説してみます。

Let's Try!

まずはGoogle Developers Consoleで登録

https://console.developers.google.com/project
スクリーンショット 2015-12-15 20.18.35.png

プロジェクトを作成をクリックし、

スクリーンショット 2015-12-15 20.22.03.png

よしなにプロジェクトを作成します。

使用するAPIの設定

今回はあくまで「ユーザ認証」を行いたいため、不要なAPIの利用は解除していきます。
スクリーンショット 2015-12-15 20.22.28.png

サイドバーから、API Manager > 概要 を選択し、

スクリーンショット 2015-12-15 20.22.36.png

Enable APIs (7) タブを選択、

スクリーンショット 2015-12-15 20.22.41.png

Google+ APIを除いて無効にしておきます。(ムダなAPIは無効に!)

認証情報と同意画面の設定

スクリーンショット 2015-12-15 20.27.42.png 再びサイドメニューから、今度は認証情報を選び、 スクリーンショット 2015-12-15 20.29.15.png

OAuth 同意画面タブへ移動します。
ココで同意画面を作っておこないと、認証情報追加時にケラれます

スクリーンショット 2015-12-15 20.34.56.png

新しい認証情報を追加する際は、"OAuth クライアントID"を選択。

スクリーンショット 2015-12-15 20.36.38.png

アプリケーションの種類は、ウェブアプリケーション。名前を入力します。
承認済みのリダイレクトURIに、http://localhost:3000/users/auth/google/callbackと入力しておいてください。

スクリーンショット 2015-12-15 20.46.23.png

クライアントID、クライアントシークレットが発行されるので、どこかに控えておいてくださいね。

Railsプロジェクト作成

$ rails new openidtest

テスト用のRailsプロジェクトを作成します。

Gemfileに追加

Gemfile
...
gem 'devise'
gem 'omniauth'
gem 'omniauth-google-oauth2'
...
openidのroot上で
$ bundle install

Deviseの設定

# Deviseの初期化
$ rails g devise:install

すると、以下のメッセージが出てきます。どうしてもうまくいかねぇ...というとき、このメッセージに立ち返ってみるといいですね。

Running via Spring preloader in process 23652
      create  config/initializers/devise.rb
      create  config/locales/devise.en.yml
===============================================================================

Some setup you must do manually if you haven't yet:

  1. Ensure you have defined default url options in your environments files. Here
     is an example of default_url_options appropriate for a development environment
     in config/environments/development.rb:

       config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }

     In production, :host should be set to the actual host of your application.

  2. Ensure you have defined root_url to *something* in your config/routes.rb.
     For example:

       root to: "home#index"

  3. Ensure you have flash messages in app/views/layouts/application.html.erb.
     For example:

       <p class="notice"><%= notice %></p>
       <p class="alert"><%= alert %></p>

  4. If you are deploying on Heroku with Rails 3.2 only, you may want to set:

       config.assets.initialize_on_precompile = false

     On config/application.rb forcing your application to not access the DB
     or load models when precompiling your assets.

  5. You can copy Devise views (for customization) to your app by running:

       rails g devise:views

===============================================================================

ユーザ認証情報を保持するテーブルを作る

作業は続きます。

# ユーザ認証用のテーブル作成
$ rails g devise user

これで、ユーザ認証に関する情報を保持するテーブルが生成されます。
新たに追加されたmigrationファイルに、ユーザ情報を保持しておくカラムを追加しておきましょう。

ユーザ情報をいちいちGoogleに問い合わせるのはナンセンスなので、
アプリケーションで必要になりそうなデータは、例えば初回ログイン時などにデータを取得して保存しておくなどが良いですね。

migrationファイル
class DeviseCreateUsers < ActiveRecord::Migration
  def change
    create_table(:users) do |t|
...
      t.string :users, :provider
      t.string :users, :uid
      t.string :users, :token
      t.string :users, :meta
...
    end
  end
end
# migrationファイルに基づいてテーブルを作る
$ rake db:migrate

土台は出来ましたね。

Model修正

app/models/user.rb
class User < ActiveRecord::Base
  devise :trackable, :omniauthable, omniauth_providers: %i(google)

  protected
  def self.find_for_google(auth)
    user = User.find_by(email: auth.info.email)

    unless user
      user = User.create(name:     auth.info.name,
                         provider: auth.provider,
                         uid:      auth.uid,
                         token:    auth.credentials.token,
                         password: Devise.friendly_token[0, 20],
                         meta:     auth.to_yaml)
    end
    user
  end
end

:trackable, :omniauthableだけでOKです。deviseに新たに機能を持たせたいときは、そのとき新たに追記する方がスマートだと思います。今回は、とりあえずログインすることが目的なので、これでよい!

また、def self.find_for_google(auth)は、コールバックを受けた時にユーザが既にアプリケーションの中で認知されているかどうかを判断するメソッドです。後で使います。

config修正

config/initializers/devise.rb
Devise.setup do |config|
  require 'devise/orm/active_record'
  config.omniauth :google_oauth2,
                  ENV['GOOGLE_APP_ID'], # 環境変数に先ほど控えたクライアントIDを入れておく
                  ENV['GOOGLE_APP_SECRET'], # 環境変数に先ほど控えたシークレットを入れておく
                  name: :google,
                  scope: %w(email) 
end

It's Simple!!
scopeについて、デフォルト(ここに記述しない状態)だとemailとprofileになります。ユーザ認証のための必須ではないため、emailだけにしちゃいましょう

ログインボタンを設置するページ作る

$ rails g controller home index
app/controllers/views/home.html.erb
<%= link_to 'Signin with Google', user_omniauth_authorize_path(:google) %>

ビューの準備完了しました。

routes.rbの書き換え

config/routes.rb
Rails.application.routes.draw do
  get 'home/index'
  
  # devise_for :users <- コメントアウトするか消しちゃいます
  devise_for :users, controllers: {
      omniauth_callbacks: "users/omniauth_callbacks"
  }
...

omniauth_callbacks_controller.rbを作成

app/controllers/usersディレクトリを作成して、omniauth_callbacks_controller.rbというコントローラーを作成します。

omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def google
    @user = User.find_for_google(request.env['omniauth.auth'])

    if @user.persisted?
      flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: 'Google'
      sign_in_and_redirect @user, event: :authentication
    else
      session['devise.google_data'] = request.env['omniauth.auth']
      redirect_to new_user_registration_url
    end
  end
end

サーバ起動

$ rails s

で、サーバを起動し、
http://localhost:3000/home/index にアクセスすると...

スクリーンショット 2015-12-15 21.34.34.png

の文字が...!早速押してみましょう!

スクリーンショット 2015-12-15 21.35.30.png

どきどき...

スクリーンショット 2015-12-15 21.36.24.png

キタ!

スクリーンショット 2015-12-15 22.08.58.png

来ましたー!routes.rbでログイン後に遷移する先を記述していないのでrootに行ってますね。ログイン後、viewなどでcurrent_user.emailなどを表示させてみれば、ログインしているユーザのemailアドレスが表示されるかと思います。
動かん!などのコメント、お待ちしております!

160
163
5

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
160
163

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?