nicoolas25
10/29/2013 - 4:15 PM

Rails 4 + Devise 3 + (google | windows live | facebook) Oauth2

Rails 4 + Devise 3 + (google | windows live | facebook) Oauth2

# app/models/user.rb

class User # < YourORM::Base

  # Don't forget the other devise modules
  devise :omniauthable, omniauth_providers: [:google_oauth2, :windowslive, :facebook]


  OAUTH_INFOS = {
    google_oauth2: {
      email:      'data.info.email',
      first_name: 'data.info.first_name',
      last_name:  'data.info.last_name'
    }.freeze,
    windowslive: {
      email:      'data.extra.raw_info.emails.preferred',
      first_name: 'data.extra.raw_info.first_name',
      last_name:  'data.extra.raw_info.last_name'
    }.freeze,
    facebook: {
      email:      'data.info.email',
      first_name: 'data.info.first_name',
      last_name:  'data.info.last_name'
    }.freeze
  }.freeze

  class << self
    OAUTH_INFOS.each do |provider, infos|
      class_eval %Q"
        def find_for_#{provider}(data, signed_in_resource=nil)
          where(email: #{infos[:email]}).first_or_create do |u|
            u.provider   = '#{provider}'
            u.first_name = #{infos[:first_name]}.presence || 'John'
            u.last_name  = #{infos[:last_name]}.presence  || 'Do'
            u.password   = Devise.friendly_token[0,20]
          end
        end
      "
    end
  end
end
# app/controllers/devise_users/omniauth_callbacks_controller.rb

class DeviseUsers::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  PROVIDER_KIND_NAMES = {
    google_oauth2: 'Google',
    windowslive:   'Windows Live',
    facebook:      'Facebook'
  }.freeze

  User::OAUTH_INFOS.keys.each do |provider|
    kind_name = PROVIDER_KIND_NAMES[provider]
    class_eval %Q"
      def #{provider}
        @user = User.find_for_#{provider}(request.env['omniauth.auth'], current_user)

        if @user.persisted?
          flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: '#{kind_name}'
          sign_in_and_redirect @user, event: :authentication
        else
          flash[:alert] = I18n.t 'devise.omniauth_callbacks.failure', kind: '#{kind_name}', reason: @user.errors.full_messages
          redirect_to new_user_registration_url
        end
      end
    "
  end
end
# config/initializers/devise.rb

Devise.setup do |config|

  # ...

  require 'omniauth-google-oauth2'
  require 'omniauth-windowslive'
  require "omniauth-facebook"

  config.omniauth :google_oauth2, Settings[:google]['app_id'],      Settings[:google]['app_secret'],      { access_type: "offline", approval_prompt: "" }
  config.omniauth :windowslive,   Settings[:windowslive]['app_id'], Settings[:windowslive]['app_secret'], { scope: 'wl.basic,wl.emails' }
  config.omniauth :facebook,      Settings[:facebook]['app_id'],    Settings[:facebook]['app_secret']

  # ...

end
gem 'devise'

gem 'omniauth'

gem 'omniauth-facebook'
gem 'omniauth-google-oauth2'
gem 'omniauth-windowslive'