Rails4+devise+omniauth-githubで認証

devise でセッション認証管理して Github の OAuth プロバイダを使用するために omniauth-github を使用する。
アプリケーションキーやシークレットキーなどの定数については今回は rails_config を使用して管理することにする。

準備

以下を Gemfile に追加して bundle install しておく。

gem 'devise'
gem 'omniauth'
gem 'omniauth-github'
gem 'rails_config'

githubの認証アプリ登録を行う

githubの右上の Account settings から Applicaitons > Developer applications を選択して作成する。
Authorization callback URL はとりあえず開発中は http://localhost:3000/users/auth/github/callback としておく。(公開時に正式なものに更新する)

rails_config で設定値を用意する

以下のコマンドを実行して、取り急ぎ、開発環境用の config/setting.local.yml を更新しておく。

$ rails g rails_config:install

config/settings.local.yml

OmniAuth:
  github:
    consumer_key: xxxxxxxxxxxxxxx
    consumer_secret: abcdefghijk01234567890

devise用のUserモデルとビューを作成

$ bin/rails g devise:install
$ bin/rails g devise user
$ bin/rails g migration AddOmniToUser name:string uid:string
$ bin/rake db:migrate
$ bin/rails g devise:views

Userモデルのomniauth用設定

app/models/user.rb

class User < ActiveRecord::Base
  devise :trackable, :database_authenticatable, :omniauthable, :omniauth_providers => [:github]

  def self.find_for_oauth(auth)
    provider = auth["provider"]
    u = User.where(:provider => provider, :uid => auth.uid)
    case provider.to_sym
    when :github
      u.first_or_initialize(:name => auth.extra.raw_info.name, :email => auth.info.email)
    end
  end
end

omniauth用設定

config/initializers/omniauth.rb (新規作成する)

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :github, Settings.OmniAuth.github.consumer_key, Settings.OmniAuth.github.consumer_secret
end

routes設定

devise_for :usersの部分を更新する。

config/routes.rb

  devise_for :users, :controllers => {
    omniauth_callbacks: "users/omniauth_callbacks"
  }

ビュー修正

ログインさせたいビューに対して以下の感じで追加する。

<% if user_signed_in? %>
  Sign in as <strong><%= current_user.name %></strong>
  |
  <%= link_to "Sign out", destroy_user_session_path, :method => :delete %>
<% else %>
  <%= link_to "Sign in with GitHub", user_omniauth_authorize_path(:github) %>
<% end %>

また、コントローラで before_action :authenticate_user! を使用した場合、
app/views/devise/shared/_links.erb でエラーが表示されるので以下のように修正が必要だった。

<%- if devise_mapping.omniauthable? %>
  <%- resource_class.omniauth_providers.each do |provider| %>
    <%= link_to "Sign in with #{provider.to_s.titleize}", user_omniauth_authorize_path(provider) %><br />
  <% end -%>
<% end -%>