Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Omniauth+Facebook lost session

In a recent project, facebook Users can login using their Facebook UID to upload picture submissions based on file uploads or uploads from their personal albums etc.

Everything works quite nice on my local system in the development environment. Login via Facebook, Logout, Upload - all great.

In production though I'm facing a unknown and hard to debug problem. It seems that every once in a while (actually reproducable when uploading a new Submission to the system) the session is lost, the picture is NOT uploaded and the facebook user is logged out (!).

I'm using devise and omniauth. Omniauth is integrated into Devise.

Following is all the code that touches Devise/Omniauth or the User.

app/models/user.rb

class User < ActiveRecord::Base
  devise :omniauthable, :rememberable, :omniauth_providers => [:facebook]

  def self.create_with_omniauth(auth)
    u = User.find_by_uid(auth["uid"])
    return u unless u.nil?

    create! do |user|
      user.provider = auth["provider"]
      user.uid = auth["uid"]
      user.name = auth["user_info"]["name"]
      user.email = auth['user_info']['email']
    end
  end

  def after_signin_path
    '/competition'
  end
end

Database contains all needed fields for :rememberable, I hope.

app/controllers/users/omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
  def facebook
    # You need to implement the method below in your model
    @user = User.create_with_omniauth(env["omniauth.auth"])

    if @user.persisted?
      flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Facebook"
      @user.update_attributes!(:current_auth_token => env["omniauth.auth"]['credentials']['token'], :last_language => I18n.locale.to_s, :updated_at => Time.now, :remember_created_at => Time.now)

      sign_in_and_redirect(:user, @user)    
    else
      redirect_to '/competition'
    end
  end

protected
  def after_omniauth_failure_path_for resource
    '/competition'
  end
end

config/initializers/devise.rb

OmniAuth.config.full_host = "http://#{APP_CONFIG[:domain]}"

Devise.setup do |config|
  config.mailer_sender = "[email protected]"

  require 'devise/orm/active_record'

  config.stretches = 10

  config.encryptor = :bcrypt
  config.timeout_in = 3.days

  config.pepper = "2a4b8b2ed9e12e553a7a542176f2ace1af62c062f3ba203a590b8b6307f33042b394922807a840004a3dcdf1c4e97ae085fe2c29654ddaeab7c60f431a8078abb"

  config.omniauth :facebook, APP_CONFIG[:facebook_app_id], APP_CONFIG[:facebook_app_secret], {
    :scope => "email,user_photos,user_photos,publish_stream,offline_access",
    :client_options => {
      :ssl => {
        :ca_file => "/etc/pki/tls/certs/ca-bundle.crt"
      }
    }
  }
end

There are no auth-related methods in application_controller.rb.

routes.rb:

The interesting part below:

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

  match '/logout_fb' => 'start#logoutfb'

  authenticate :user do
    get '/users/connect/:network', :to => redirect("/users/auth/%{network}")
  end

Somehow I cannot get to understand the authenticate block, which according to another post should be helpful.. ideas on this too?

So many theories: One is that the facebook function in the omniauth_callbacks_controller runs aside of the users' session, and hence sign_in_and_redirect won't work. So I had the idea of redirecting to another page like '/auth?uid=xxx' but this sounds both wrong, insecure and not stable.

Any help or hints are appreciated!

like image 721
Sebastian Roth Avatar asked Apr 28 '11 09:04

Sebastian Roth


1 Answers

A bit of a long shot but try turning off protect_from_forgery - I had some issues with sessions disappearing and it turned out to be the issue discussed here https://github.com/intridea/omniauth/issues/203

like image 184
David Burrows Avatar answered Sep 28 '22 12:09

David Burrows