Devise and OmniAuth remembering OAuth
Asked Answered
D

4

19

So, I just got setup using Rails 3, Devise and OmniAuth via https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview.

I'm successfully authenticating users via Facebook, but they are not "rememberable" despite being marked with:

devise [...]: rememberable, :omniauthable

I tried calling:

@the_user.remember_me!

...to no avail. No cookie is being stored/set which means the user does not persist across sessions.

Has anybody managed to get a user sourced from FB remembered via cookies? In my mind, this should be happening automatically.

Thanks for any ideas or feedback you guys might have.

Diarmid answered 17/12, 2010 at 23:42 Comment(0)
D
11

I agree that you would expect Devise to set a session before the request goes to FB. I guess this is a missing feature of Devise.

I had the problem myself where I used token_authenticatable. An api client was calling the following url directly:

/users/auth/facebook?auth_token=TnMn7pjfADapMdsafOFIHKgJVgrBEbjKqrubwMXUca0n16m3Hzr7CnrP1s4z

Since I was using token_authenticatable i was assuming this would sign in the user. Unfortunately this doesn't work out of the box. What you have to do to get this working is making sure that the user is logged in before it gets to this path. You can do it in other ways, but the easiest way is to give a different url to the API client (in this case "users/connect/facebook". Here is my addition to the routes file that makes it work (assuming you have a user model with devise and you didn't change defaults):

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

This will make sure the session is correctly created so the user is being recognized when he/she returns from facebook.

Dandruff answered 13/1, 2011 at 11:40 Comment(1)
How dio you "give" the API client another URL? Somewhere in config/initializers/devise.rb ?Shelley
G
20

I'd like to elaborate on the (correct) answer @jeroen-van-dijk gave above which worked for me.

In config/routes.rb, add a new route in the devise_for block:

devise_for :users, :controllers => {
                     :omniauth_callbacks => "user_omniauth_callbacks" } do
  ...
  get '/users/connect/:network', :to => redirect("/users/auth/%{network}"),
                                 :as => 'user_oauth_connect'

end

Then change your "login using facebook" link to use the new route:

<!-- before it linked to user_omniauth_authorize_path -->
<%= link_to "Sign in using Facebook", user_oauth_connect_path(:facebook) %>

In app/controllers/user_omnniauth_callbacks_controller.rb

class UserOmniauthCallbacksController < Devise::OmniauthCallbacksController
  include Devise::Controllers::Rememberable

  def facebook
    @user = User.find(...)
    ...
    remember_me(@user) # set the remember_me cookie
  end
end

This solution works well for me using Rails 3.1 and Devise 1.4.9.

Gerrald answered 2/2, 2012 at 12:0 Comment(3)
I missed the call to remember_me on the controller rather than the model at first. Finally got it working after including the right module.Fetterlock
On Rails 3.2.3 and Devise 2.1.2, adding the "include" line and the "remember_me()" call was enough. I didn't have to change any routing.Flatiron
@Gerrald I tried all the solutions, but they do not work for me and I am opening a new question at the following post. Could you please help me? Thanks Fabrizio #42281122Wreckful
D
11

I agree that you would expect Devise to set a session before the request goes to FB. I guess this is a missing feature of Devise.

I had the problem myself where I used token_authenticatable. An api client was calling the following url directly:

/users/auth/facebook?auth_token=TnMn7pjfADapMdsafOFIHKgJVgrBEbjKqrubwMXUca0n16m3Hzr7CnrP1s4z

Since I was using token_authenticatable i was assuming this would sign in the user. Unfortunately this doesn't work out of the box. What you have to do to get this working is making sure that the user is logged in before it gets to this path. You can do it in other ways, but the easiest way is to give a different url to the API client (in this case "users/connect/facebook". Here is my addition to the routes file that makes it work (assuming you have a user model with devise and you didn't change defaults):

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

This will make sure the session is correctly created so the user is being recognized when he/she returns from facebook.

Dandruff answered 13/1, 2011 at 11:40 Comment(1)
How dio you "give" the API client another URL? Somewhere in config/initializers/devise.rb ?Shelley
J
11

It is fixed by devise contributors: You should just add

user.remember_me = true
# then add your signing in code 
sign_in(:user, user)

ref: https://github.com/plataformatec/devise/issues/776#issuecomment-807152

Jonquil answered 9/12, 2012 at 9:54 Comment(1)
this should be the right answer, I've searched it for whole day, you should set this before sign_in_and_redirectEckart
F
0

fyi - if you want to also use the extend_remember_period feature in devise - you need to force this on the user object in the callback controller

added one line to @mustafaturan's answer

user.remember_me = true
user.extend_remember_period = true

# then add your signing in code 
sign_in(:user, user)
Flagpole answered 7/5, 2014 at 16:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.