Reputation: 11537
In a recent project, facebook User
s 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!
Upvotes: 7
Views: 3080
Reputation: 5247
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
Upvotes: 5
Reputation: 40770
You are using devise but you are not using it's own helpers. For instance, you've defined your own current_user method. To be honest, I can't see any obvious mistakes you've made, so it's just a desperate tip.
what kind of a session store do you use locally and what in production?
When you say "facebook user is logged out", this user is still logged in to facebook, but lost his session at yourapp.com ?
Are you sure that user.id
is never nil or that you anywhere else than in .destroy set session[:user_id]= some_nil_variable
?
Upvotes: 0
Reputation: 13433
In my config/initializers/omniauth.rb, I had to add the following:
OmniAuth.config.full_host = "http://yourdomain.com" # Or have an environment specific URL.
Upvotes: 1