お役立ち

RailsでSNSログイン機能の実装/サンプルコード(Twitter、Facebook、Googleなど)

  • このエントリーをはてなブックマークに追加

この記事で解決すること

SNSログインボタンの完成図

  • SNSログイン認証を追加したい
  • すでに自前の認証機能がある場合は干渉しないように追加したい
  • Omniauthのシンプルなサンプルコードが知りたい(Deviceを使わない実装)
  • Twitter、Facebook、Googleの認証の具体例
  • ちゃんとしたデザインのSNSログインボタンの設置(上記の画像)

SNSログイン・連携はOmniauthを使うと簡単!

Omniauthとは?

OmniauthはさまざまなSNS認証機能を標準化するライブラリです。
簡単に説明するとSNSごとの細かな認証の違いを吸収し、SNSが変わっても認証機能を同じように実装できるミドルウェアよりのライブラリです。

対応しているSNS

私の知る限りほとんどすべてのSNSに対してOmniauthライブラリが開発されています。
omniauth-twitter、omniauth-facebook、ominiauth-google-oauth2、omniauth-mixi…

しかもOminiauth+Deviceで標準化されているため使い方を覚えるとSNSが変わってもすぐに連携機能が実装できます。

準備

APIアクセスキーの取得

SNSの認証APIを利用する場合、~key、~secretと2つの情報が必要です。
下記のリンクから設定を行いましょう。
Googleの場合、Google+ APIの追加も必要にです。

Twitter、Facebook、Googleの場合

Gemのインストール

Gemfileを次のように記述、今回はTwitterとFacebookの認証機能を追加

gem 'omniauth'
gem 'omniauth-twitter'
gem 'omniauth-facebook'
gem 'omniauth-google-oauth2'

bundleインストールを実行

bundle install

環境変数の設定

先ほど入手した2つの情報を記述します。
これは後で説明するomniauth.rbにべた下記しても動きますがセキュリティの観点上良くないです。

今回はconfig/secrets.ymlに記述します。

次のように先ほどの入手した情報を入力します。
鍵、秘密情報は””で囲みましょう。そうしないとint型で読み込まれて認証に失敗することがあります。
ここではgoogle-oauth2ではなくgoogle_oauth2です。ハイフン”-“がアンダーバー”_”になってます。

shared:
twitter:
key:  #ここにConsumer Key (API Key)を記述
secret: #ここにConsumer Secret (API Secret)を記述
facebook:
key: #ここにアプリIDを記述
secret: #ここに app secret を記述
google_oauth2:
key: #ここにクライアント IDを記述
secret: #ここにクライアント シークレットを記述

omniauthにSNSを登録

config/initializes/omniauth.rb
にomniauthにSNSを登録するコードを記述します。

Rails.application.config.middleware.use OmniAuth::Builder do
provider :twitter, Rails.application.secrets[:twitter][:key], Rails.application.secrets[:twitter][:secret]
provider :facebook, Rails.application.secrets[:facebook][:key], Rails.application.secrets[:facebook][:secret]
provider :google_oauth2, Rails.application.secrets[:google_oauth2][:key], Rails.application.secrets[:google_oauth2][:secret]
end

Omniauthでログイン機能~モデルの作成~

authorizationモデルの生成

Omniauthを利用する場合、provider(SNS名)、uid(ユーザーID)というカラムをモデルに保存する必要があります。
ユーザーモデルに付け加える方法もありますが複数のSNSの認証を付けた場合、
ユーザテーブルがごちゃごちゃするので、
authorizationモデルを新しく作ってユーザーモデルと紐つける付けるのが
ベストという結論になりました。下記の記事を参考にしました。

Separating Authentication and Identity with OmniAuth

モデルの生成

rails g model authorization provider:string uid:string user_id:integer

モデルにバリデーションの追加

重複して認証しないようにインデックスを追加するマイグレーションファイルを作成

rails g migration AddIndexToAuthorizationsProviderUid

作成されたファイルのchange関数を次のように記述しましょう。

def change
add_index :authorizations, [:provider, :uid], unique: true
end

UserモデルとAuthorizationモデルを下記のようにバリデーションを追加します。

class User < ActiveRecord::Base
has_many :authorizations
...
end
class Authorization < ApplicationRecord
belongs_to :user
#:providerと:uidはもちろんのことユーザーとの紐付け(:user_id)も保証
validates_presence_of :user_id, :uid, :provider
#:providerと:uidのペアは一意であることを保証
validates_uniqueness_of :uid, uniqueness: {:scope => :provider}
end

ユーザー生成機能の追加

次にUserモデルにSNS認証が要求されたときにユーザーを生成する機能を実装します。
User.create_from_auth!(auth)という関数を定義して適宜、ユーザー生成の処理を記述しましょう。

class User < ApplicationRecord
...
def User.create_from_auth!(auth)
#authの情報を元にユーザー生成の処理を記述
#auth["credentials"]にアクセストークン、シークレットなどの情報が入ってます。
#auth["info"]["email"]にユーザーのメールアドレスが入ってます。(Twitterはnil)
...
end

Authorizationモデルにユーザー検索機能と新規に認証を追加する機能を追加します。


def Authorization.find_from_auth(auth)
find_by_provider_and_uid(auth['provider'], auth['uid'])
end
def Authorization.create_from_auth(auth, user = nil)
user ||= User.create_from_auth!(auth)
Authorization.create!(:user => user, :uid => auth['uid'], :provider => auth['provider'])
end

セッション管理機能のコントローラー

セッション管理するコントローラーがない場合は生成しておきましょう。

rails g controller sessions

セッション管理のcreateメソッドを下記のように記述します。

class SessionsController < ApplicationController
...
def create
auth = request.env["omniauth.auth"]
if auth.present?
unless @auth = Authorization.find_from_auth(auth)
@auth = Authorization.create_from_auth(auth)
end
user = @auth.user
redirect_back_or user
else
#もしすでに認証機能がある場合ここに自前の認証機能をいれる
#ない場合はこのelseブロックはいらないので削除
end
end
...
end

ルーティングの設定

ルーティングの設定をします。

match '/auth/:provider/callback', to: 'sessions#create', via: [:get, :post]

コールバックURLをSNSの認証サーバーに登録

今、設定したコールバックのURLをSNSの認証サーバーに登録する必要があります。
利用するSNSのOauth認証サイトでコールバックURLを登録するページがあるので
“[アプリのルートURL]/auth/[SNS名]/callback”
を登録しましょう。
登録方法はSNSごとに違うのでここでは割愛します。

Railsサーバーを再起動

Railsのサーバーが起動していたらサーバーを再起動しましょう。
これはconfig/initializes/omniauth.rbを読み込むためです。

ビューにログインボタンの設置

まずはリンクが機能するかのテスト

まずは、ログイン機能がちゃんと実装されているかの簡単なテストをします。

下記のコードを適当なビューに貼り付けてクリックしてみてログインできるか確認しましょう。

<%= link_to 'ログイン', '/auth/[SNS名]' %>

これでログイン機能の実装は終わりです。

次はちゃんとしたログインリンクを作成

ログインボタンのデザインのために次の2つのGemを入れます。

  • bootstrap-social-rails
  • font-awesome-rails

Gemfileに次の2つを記述しましょう

gem 'bootstrap-social-rails'
gem 'font-awesome-rails'

インストールをします。

bundle install

初期設定をします。’app/assets/stylesheets/application.css’に下記のコードを書きます。

*= require bootstrap-social
*= require font-awesome

ボタンを設置したいところに下記のコードを貼り付けるとボタンが設置できます。

<%= link_to '/auth/twitter', class: "btn btn-block btn-social btn-twitter" do %>
<span class="fa fa-twitter"></span> Twitterアカウントでログイン
<% end %>
<%= link_to '/auth/facebook', class: "btn btn-block btn-social btn-facebook" do %>
<span class="fa fa-facebook"></span> Facebookアカウントでログイン
<% end %>
<%= link_to '/auth/google_oauth2', class: "btn btn-block btn-social btn-google" do %>
<span class="fa fa-google"></span> Googleアカウントでログイン
<% end %>
  • このエントリーをはてなブックマークに追加