Rails Devise Token Auth authentification without using email - ruby-on-rails

I am trying to use devise_token_auth gem with API app on Rails 5.0.2.
I installed gem typically as mentioned on https://github.com/lynndylanhurley/devise_token_auth, so added to Gemfile, bundled and installed on User model. The problem is that, I don't want to use authentification (registration and login) with email. I just want to use telephone number instead (of course POST including with password and password_confirmation).
I added column :telephone_number, which will be unique to users table. And procced required steps to achieve this. https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-sign-in-with-something-other-than-their-email-address
So this is what it looks like in code.
devise.rb
Devise.setup do |config|
...
config.authentication_keys = [ :telephone_number ]
config.case_insensitive_keys = [ :telephone_number ]
config.strip_whitespace_keys = [ :telephone_number ]
...
user.rb
class User < ActiveRecord::Base
# Include default devise modules.
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable, :authentication_keys => [:telephone_number]
include DeviseTokenAuth::Concerns::User
def email_required?
false
end
def email_changed?
false
end
application_controller.rb
class ApplicationController < ActionController::API
include DeviseTokenAuth::Concerns::SetUserByToken
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
added_attrs = [:telephone_number, :password, :password_confirmation, :remember_me]
devise_parameter_sanitizer.permit :sign_up, keys: added_attrs
devise_parameter_sanitizer.permit :account_update, keys: added_attrs
end
end
Server is starting properly, no exception is given. But when I test registration with RESTfull services POST on /auth it gives me validation error, that email can't be blank.
{"status":"error","data":{"id":null,"provider":"email","uid":"",
"name":null,"nickname":null,"image":null,"email":null,
"created_at":null,"updated_at":null,"telephone_number":"0123456789"},
"errors":{"email":["can't be blank","is not an email"],
"full_messages":["Email can't be blank","Email is not an email"]}}
EDIT:
Log from Puma
Started POST "/auth?=" for 127.0.0.1 at 2017-04-24 15:17:13 +0200
Processing by DeviseTokenAuth::RegistrationsController#create as */*
Parameters: {"telephone_number"=>"0123456789", "password"=>"[FILTERED]",
"password_confirmation"=>"[FILTERED]", "registration"=>{"telephone_number"=>"0123456789",
"password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}}
Unpermitted parameter: registration
Unpermitted parameter: registration
Unpermitted parameter: registration
(0.3ms) BEGIN
SQL (0.9ms) INSERT INTO "users" ("encrypted_password", "tokens", "created_at",
"updated_at", "telephone_number") VALUES ($1, $2, $3, $4, $5) RETURNING "id"
[["encrypted_password", "$2a$10$PgCIPAGA1VH1erHvJX5Sg.f4IPmSyfSoVM3EVbKtHkbgeUvEGL5NG"],
["tokens", "{}"], ["created_at", 2017-04-24 13:17:13 UTC], ["updated_at", 2017-04-24 13:17:13 UTC],
["telephone_number", "0123456789"]]
(0.2ms) ROLLBACK
Completed 422 Unprocessable Entity in 139ms (Views: 10.5ms | ActiveRecord: 1.3ms)
Reply on POST /auth
{"status":"error","data":{"id":null,"provider":"email","uid":"",
"name":null,"nickname":null,"image":null,"email":null,
"created_at":"2017-04-24T13:17:13.904Z","updated_at":"2017-04-24T13:17:13.904Z",
"telephone_number":"0123456789"},"errors":["An account already exists for ''"]}
It is checking and validating email, which currently is "", so no account could be registered through.
Is there any config property I should add, or override some method ?
Thank you in advance.

Related

Completed 401 Unauthorized - Devise devise_parameter_sanitizer not permitting any values

I am new to Rails and stuck over here..could you please help me to solve this.
console
Started POST "/users/sign_in" for ::1 at 2020-03-25 11:46:10 +0530
Processing by Users::SessionsController#create as HTML
Parameters: {"authenticity_token"=>"seSNKhVVbrFM+XALvQExwMNxI1KY74or3Cy6Y0wYnU7RLjC6uuaM057jKmQ73a0g84qQNnOVREL0RZ6AuarGQA==", "user"=>{"email"=>"yadu#g.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Log in"}
================================
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? ORDER BY "users"."id" ASC LIMIT ? [["email", "yadu#g.com"], ["LIMIT", 1]]
↳ app/controllers/users/sessions_controller.rb:16:in `create'
Completed 401 Unauthorized in 248ms (ActiveRecord: 0.3ms | Allocations: 1519)
Started GET "/users/sign_in" for ::1 at 2020-03-25 11:46:10 +0530
Processing by Users::SessionsController#new as HTML
Rendering devise/sessions/new.html.erb within layouts/application
Rendered devise/shared/_links.html.erb (Duration: 1.0ms | Allocations: 525)
sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
before_action :configure_sign_in_params, only: [:create]
# GET /resource/sign_in
def new
super
end
# POST /resource/sign_in
def create
logger.debug "================================ #{configure_sign_in_params}"
super
end
# DELETE /resource/sign_out
def destroy
super
end
private
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_in_params
devise_parameter_sanitizer.permit(:sign_in) { |u| u.permit( :email, :password ) }
# params.require(:user).permit(:email, :password, :remember_me)
end
end
routes.rb
devise_for :users, controllers: { omniauth_callbacks: 'users/omniauth',sessions: 'users/sessions'}
resources :users
resources :product_categories
config/initializers/devise.rb
# Use this hook to configure devise mailer, warden hooks and so forth.
# Many of these configuration options can be set straight in your model.
Devise.setup do |config|
config.mailer_sender = 'please-change-me-at-config-initializers-devise#example.com'
config.case_insensitive_keys = [:email]
config.strip_whitespace_keys = [:email]
config.stretches = Rails.env.test? ? 1 : 11
config.reconfirmable = true
# Invalidates all the remember me tokens when the user signs out.
config.expire_all_remember_me_on_sign_out = true
config.password_length = 6..128
config.email_regexp = /\A[^#\s]+#[^#\s]+\z/
config.timeout_in = 30.minutes
config.reset_password_within = 6.hours
config.omniauth :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET'], scope: 'public_profile,email'
config.omniauth :github, ENV['GITHUB_APP_ID'], ENV['GITHUB_APP_SECRET'], scope: 'user,public_repo'
config.omniauth :google_oauth2, ENV['GOOGLE_APP_ID'], ENV['GOOGLE_APP_SECRET'], scope: 'userinfo.email,userinfo.profile'
config.omniauth :twitter, ENV['TWITTER_APP_ID'], ENV['TWITTER_APP_SECRET']
end
Issue
I can register a user successfully, but cannot log in using that user. It shows 401 unautherized at the time. It appears that the parameter arrives in the configuration_sign_in_params method, but the return value of the configuration_sign_in_params method is empty.
All these issues are started from when i set login with social accounts ...Before that everything were fine .

No automatic sign_in after modifying devise registration controller

I initially wanted to send my user to a different page after sign_up. This works now, as I created a registrations controller. The problem now is that the user is prompted to login right after sign_up. Of course I want him to be automatically signed_in after sign_up. Any idea how I can fix that? I found this explanation but both answers do not work for me: Rails: Devise login after sign up.
Here is my registrations controller:
class RegistrationsController < Devise::RegistrationsController
before_action :configure_permitted_parameters, if: :devise_controller?
def start_date
#user =current_user
end
protected
def configure_permitted_parameters
update_attrs = [:password, :password_confirmation, :current_password, :start_date]
devise_parameter_sanitizer.permit(:sign_up, keys: [:applications, :job_category, :job_status])
end
def after_sign_up_path_for(resource)
'/profiles/new' # Or :prefix_to_your_route
end
end
here are my application Logs after signup:
Started GET "/users/sign_up?job_category=IT+%26+Development&job_status=Other+Category&vacancy_id=general+application" for ::1 at 2019-08-08 15:32:17 +0200
Processing by RegistrationsController#new as HTML
Parameters: {"job_category"=>"IT & Development", "job_status"=>"Other Category", "vacancy_id"=>"general application"}
Rendering devise/registrations/new.html.erb within layouts/application
Rendered devise/registrations/new.html.erb within layouts/application (1.1ms)
Rendered shared/_navbar.html.erb (1.0ms)
Rendered shared/_flashes.html.erb (0.4ms)
Completed 200 OK in 174ms (Views: 171.7ms | ActiveRecord: 0.0ms)
Started POST "/users" for ::1 at 2019-08-08 15:32:32 +0200
Processing by RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"Rb06/S6dB019mw8I46x0tJytVG7HNeVV23ZbuX/9Ykb9amYwI3bCLlk8AqNjTEGAR0qTy6rlCNZE1U6w8skslA==", "user"=>{"email"=>"testtesttest#test.de", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "applications"=>"\#{general application}", "job_category"=>"IT & Development", "job_status"=>"Other Category", "terms"=>"1"}, "commit"=>"Sign up"}
Can't verify CSRF token authenticity.
Unpermitted parameter: :terms
(0.5ms) BEGIN
User Exists (0.5ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = $1 LIMIT $2 [["email", "testtesttest#test.de"], ["LIMIT", 1]]
SQL (6.9ms) INSERT INTO "users" ("email", "encrypted_password", "created_at", "updated_at", "applications", "job_category", "job_status") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id" [["email", "testtesttest#test.de"], ["encrypted_password", "$2a$11$MlDweUU00bKQsNyA81/Cuu/o9HQSYJHM8FCInvVSaYVspvcs36oMS"], ["created_at", "2019-08-08 13:32:32.764097"], ["updated_at", "2019-08-08 13:32:32.764097"], ["applications", "{{\"general application\"}}"], ["job_category", "IT & Development"], ["job_status", "Other Category"]]
UserMailer#welcome: processed outbound mail in 0.2ms
(8.4ms) COMMIT
Redirected to http://localhost:3000/profiles/new
Completed 302 Found in 316ms (ActiveRecord: 16.2ms)
Started GET "/profiles/new" for ::1 at 2019-08-08 15:32:32 +0200
Processing by ProfilesController#new as HTML
Completed 401 Unauthorized in 3ms (ActiveRecord: 0.0ms)
Started GET "/users/sign_in" for ::1 at 2019-08-08 15:32:32 +0200
Processing by Devise::SessionsController#new as HTML
Rendering devise/sessions/new.html.erb within layouts/application
Rendered devise/shared/_links.html.erb (1.3ms)
Rendered devise/sessions/new.html.erb within layouts/application (11.0ms)
Rendered shared/_navbar.html.erb (1.4ms)
Rendered shared/_flashes.html.erb (0.5ms)
Completed 200 OK in 198ms (Views: 196.5ms | ActiveRecord: 0.0ms)
Change permitted params from:
def configure_permitted_parameters
update_attrs = [:password, :password_confirmation, :current_password, :start_date]
devise_parameter_sanitizer.permit(:sign_up, keys: [:applications, :job_category, :job_status])
end
to:
def configure_permitted_parameters
update_attrs = [:password, :password_confirmation, :current_password, :start_date]
devise_parameter_sanitizer.permit(:sign_up, keys: [ update_attrs, :applications, :job_category, :job_status])
end
And I think in profiles controller has a problem with before_action :authenticate_user! .
In terminal redirect has work.
You have a problem with terms, in your terminal:
Can't verify CSRF token authenticity.
Unpermitted parameter: :terms
Try changing the protect_from_forgery with: :exception to protect_from_forgery with: :exception, prepend: true
Ref: https://github.com/plataformatec/devise#controller-filters-and-helpers
Devise by default signout the session if the request is unverified.
Ref: from devise code(Devise::Controllers::Helpers),
# Overwrite Rails' handle unverified request to sign out all scopes,
# clear run strategies and remove cached variables.
def handle_unverified_request
super # call the default behaviour which resets/nullifies/raises
request.env["devise.skip_storage"] = true
sign_out_all_scopes(false)
end
Try this out if the first one solves the issue, https://github.com/plataformatec/devise/issues/2734 for solving the issue,
Change this:
devise_parameter_sanitizer.permit(:sign_up, keys: [:applications, :job_category, :job_status]
To this:
devise_parameter_sanitizer.permit(:sign_up, keys: [:applications, :job_category, :job_status, :terms]

Devise: custom fields not saved after signing up Rails 4

I have installed devise gem in my app for registration. I have same issue like this question
I have generated Doctor model by
rails generate devise Doctor
And here is doctor.rb
class Doctor < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
end
I also generated controller by rails generate devise:controllers doctors
class Doctors::RegistrationsController < Devise::RegistrationsController
before_filter :sign_up_params, only: [:create]
before_filter :account_update_params, only: [:update]
#
# # GET /resource/sign_up
# def new
# super
# end
##
## # POST /resource
# def create
# super
# end
##
## # GET /resource/edit
# def edit
# super
# end
##
## # PUT /resource
# def update
# super
# end
##
## # DELETE /resource
# def destroy
# super
# end
protected
def sign_up_params
params.require(:doctor).permit(:first_name, :last_name, :email, :password, :password_confirmation, :gender, :contact_no, :about_me, :certification, :exp_summary, :username)
end
#
def account_update_params
params.require(:doctor).permit(:first_name, :last_name, :email, :password, :password_confirmation, :current_password , :gender, :contact_no, :about_me, :certification, :exp_summary, :username)
end
# protected
# You can put the params you want to permit in the empty array.
#def configure_sign_up_params
# devise_parameter_sanitizer.for(:sign_up) << :first_name, :last_name, :gender, :contact_no, :about_me, :certification, :exp_summary, :username
#end
# You can put the params you want to permit in the empty array.
#def configure_account_update_params
# devise_parameter_sanitizer.for(:account_update) << :first_name, :last_name, :gender, :contact_no, :about_me, :certification, :exp_summary, :username
#end
# The path used after sign up.
# def after_sign_up_path_for(resource)
# super(resource)
# end
# The path used after sign up for inactive accounts.
# def after_inactive_sign_up_path_for(resource)
# super(resource)
# end
end
I have written in routes.rb file devise_for :doctor, :controllers => { sessions: "doctors/sessions"}.
Here is my logs from terminal after submitting Sign_up form
Started POST "/doctor" for 127.0.0.1 at 2014-12-04 16:52:20 +0530
Processing by Devise::RegistrationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"8Dd5u5Qq+kLyAI+RaEuoSyjsxteHw4VBndQC+W5yjy0=", "doctor"=>{"username"=>"Test5", "first_name"=>"John", "last_name"=>"Smith", "contact_no"=>"8787878787", "gender"=>"true", "email"=>"john#smith.com", "about_me"=>"Test", "certification"=>"Test", "exp_summary"=>"Test", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up"}
Unpermitted parameters: username, first_name, last_name, contact_no, gender, about_me, certification, exp_summary
(0.2ms) BEGIN
Doctor Exists (0.3ms) SELECT 1 AS one FROM `doctors` WHERE `doctors`.`email` = BINARY 'john#smith.com' LIMIT 1
SQL (0.2ms) INSERT INTO `doctors` (`created_at`, `email`, `encrypted_password`, `updated_at`) VALUES ('2014-12-04 11:22:20', 'john#smith.com', '$2a$10$as.WAOu05ET7RUtnsdTC2ucqotK5Ls2Z6iKWI.wW3gSuIwohYfoTW', '2014-12-04 11:22:20')
(116.8ms) COMMIT
(0.1ms) BEGIN
SQL (0.3ms) UPDATE `doctors` SET `current_sign_in_at` = '2014-12-04 11:22:20', `current_sign_in_ip` = '127.0.0.1', `last_sign_in_at` = '2014-12-04 11:22:20', `last_sign_in_ip` = '127.0.0.1', `sign_in_count` = 1, `updated_at` = '2014-12-04 11:22:20' WHERE `doctors`.`id` = 7
(56.6ms) COMMIT
Redirected to http://localhost:3000/
Completed 302 Found in 254ms (ActiveRecord: 174.5ms)
Started GET "/" for 127.0.0.1 at 2014-12-04 16:52:20 +0530
Processing by HomeController#index as HTML
Doctor Load (0.3ms) SELECT `doctors`.* FROM `doctors` WHERE `doctors`.`id` = 7 ORDER BY `doctors`.`id` ASC LIMIT 1
Rendered home/index.html.erb within layouts/application (0.0ms)
Completed 200 OK in 32ms (Views: 30.5ms | ActiveRecord: 0.3ms)
Started GET "/assets/application.css?body=1" for 127.0.0.1 at 2014-12-04 16:52:20 +0530
Started GET "/assets/home.css?body=1" for 127.0.0.1 at 2014-12-04 16:52:20 +0530
Started GET "/assets/jquery.js?body=1" for 127.0.0.1 at 2014-12-04 16:52:20 +0530
Started GET "/assets/jquery_ujs.js?body=1" for 127.0.0.1 at 2014-12-04 16:52:20 +0530
Started GET "/assets/turbolinks.js?body=1" for 127.0.0.1 at 2014-12-04 16:52:20 +0530
Started GET "/assets/application.js?body=1" for 127.0.0.1 at 2014-12-04 16:52:20 +0530
Started GET "/assets/home.js?body=1" for 127.0.0.1 at 2014-12-04 16:52:20 +0530
Why my custom fields are not saved? Where I do mistake?
Update
Controller Structure:
controllers
-> doctors
-> confirmations_controller.rb
-> omniauth_callbacks_controller.rb
-> passwords_controller.rb
-> registrations_controller.rb
-> sessions_controller.rb
-> unlocks_controller.rb
-> application_controller.rb
-> home_controller.rb
EDITED:
Okay! You were trying to override the devise controllers which is not required in your case. Follow these simple steps:
rails g model Doctor
Create your fields except email and password. Devise will take care of that.
rails g devise:install
rails g devise Doctor
In your ApplicationController:
before_action :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:username, :address, :phone, :email) }
end
Please try to do like following. Hopes it work for you. :)
class RegistrationsController < Devise::RegistrationsController
def create
devise_parameter_sanitizer.for(:sign_up) << [:first_name, :last_name]
super
end
end

Rails 4 devise_invitable invitation token invalid

I have been following Ryan Boland's excellent Rails multitenancy tutorial, but have run into a snag with devise_invitable. I am using...
Rails 4.1.5
devise 3.3.0
devise_invitable 1.3.6
Postgresql
I create a new account and user/account owner on a chosen subdomain (mysubdomain.lvh.me:3000), from which I can send a user invitation just fine. I open the invitation link in an incognito Chrome session to ensure I am not logged in or have any current session. Upon clicking on the invitation link, I am redirected to the sign in page (mysubdomain.lvh.me:3000/users/sign_in) and see a flash notice: "The invitation token provided is not valid!"
I am using a very simple mailer view (app/views/devise/mailer/invitation_instructions.html.erb)...
<%= link_to 'Accept invitation', accept_invitation_url(#resource, :invitation_token => #token) %>
As you can see, I ensured the use of #token, as described here.
Upon creating the invitation, I have confirmed the invitation token is saved to the database (in this case for hey#test.com - d1801fd8df78bd8cd125d5d8091fdc6a72c8f8faf4136cb282d497ec612195e9). I have confirmed this matches the token on invitation lookup upon acceptance request (see below traces). Still, it redirects to user sign in page rather than completing sign up, and also displays in the trace log "Filter chain halted as :resource_from_invitation_token rendered or redirected". The user remains uncomfirmed in the end after this transaction.
Any ideas on what might be going wrong for me here? I am including logs, my application controller, and my devise config below...
Here is the trace log for the invitation creation:
Started POST "/users/invitation" for 127.0.0.1 at 2014-09-07 01:28:33 +0800
Processing by Devise::InvitationsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"BiIQ95wwdQz3CJ0+OoLOE9xHHvxhloHsRHrxsqf1D2Q=", "user"=>{"email"=>"hey#test.com"}, "commit"=>"Invite User"}
User Load (4.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
Account Load (0.4ms) SELECT "public"."accounts".* FROM "public"."accounts" WHERE "public"."accounts"."subdomain" = 'mysubdomain' LIMIT 1
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."email" = 'hey#test.com' ORDER BY "users"."id" ASC LIMIT 1
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."invitation_token" = 'd1801fd8df78bd8cd125d5d8091fdc6a72c8f8faf4136cb282d497ec612195e9' ORDER BY "users"."id" ASC LIMIT 1
(0.1ms) BEGIN
SQL (0.5ms) INSERT INTO "users" ("created_at", "email", "invitation_created_at", "invitation_sent_at", "invitation_token", "invited_by_id", "invited_by_type", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING "id" [["created_at", "2014-09-06 17:28:34.296123"], ["email", "hey#test.com"], ["invitation_created_at", "2014-09-06 17:28:34.294987"], ["invitation_sent_at", "2014-09-06 17:28:34.294987"], ["invitation_token", "d1801fd8df78bd8cd125d5d8091fdc6a72c8f8faf4136cb282d497ec612195e9"], ["invited_by_id", 1], ["invited_by_type", "User"], ["updated_at", "2014-09-06 17:28:34.296123"]]
(2.2ms) COMMIT
Rendered devise/mailer/invitation_instructions.html.erb (1.3ms)
Devise::Mailer#invitation_instructions: processed outbound mail in 23.5ms
Sent mail to hey#test.com (26.0ms)
Date: Sun, 07 Sep 2014 01:28:34 +0800
From: please-change-me-at-config-initializers-devise#example.com
Reply-To: please-change-me-at-config-initializers-devise#example.com
To: hey#test.com
Message-ID: <...>
Subject: Invitation instructions
Mime-Version: 1.0
Content-Type: text/html;
charset=UTF-8
Content-Transfer-Encoding: 7bit
Accept invitation
Redirected to http://mysubdomain.lvh.me:3000/users
Completed 302 Found in 888ms (ActiveRecord: 10.0ms)
Here is the trace upon following the invitation link...
Started GET "/users/invitation/accept?invitation_token=3GXDmi7NntDRdhvo57q5" for 127.0.0.1 at 2014-09-07 01:28:38 +0800
Processing by Devise::InvitationsController#edit as HTML
Parameters: {"invitation_token"=>"3GXDmi7NntDRdhvo57q5"}
User Load (0.6ms) SELECT "users".* FROM "users" WHERE "users"."invitation_token" = 'd1801fd8df78bd8cd125d5d8091fdc6a72c8f8faf4136cb282d497ec612195e9' ORDER BY "users"."id" ASC LIMIT 1
Redirected to http://mysubdomain.lvh.me:3000/users/sign_in
Filter chain halted as :resource_from_invitation_token rendered or redirected
Completed 302 Found in 5ms (ActiveRecord: 0.6ms)
Started GET "/users/sign_in" for 127.0.0.1 at 2014-09-07 01:28:38 +0800
Processing by Devise::SessionsController#new as HTML
Account Load (0.4ms) SELECT "public"."accounts".* FROM "public"."accounts" WHERE "public"."accounts"."subdomain" = 'mysubdomain' LIMIT 1
Rendered devise/shared/_links.erb (0.7ms)
Rendered devise/sessions/new.html.erb within layouts/application (4.4ms)
Completed 200 OK in 21ms (Views: 16.6ms | ActiveRecord: 1.3ms)
Here is my application_controller for good measure...
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_filter :load_schema, :authenticate_user!, :set_mailer_host
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(:first_name, :last_name, :company, :email, :password, :password_confirmation, :remember_me, :image, :image_cache)}
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(:first_name, :last_name, :company, :email, :password_confirmation, :current_password, :image, :image_cache)}
end
private
def load_schema
Apartment::Database.switch('public')
return unless request.subdomain.present?
if current_account
Apartment::Database.switch(current_account.subdomain)
else
redirect_to root_url(subdomain: false)
end
end
def current_account
#current_account ||= Account.find_by(subdomain: request.subdomain)
end
helper_method :current_account
def set_mailer_host
subdomain = current_account ? "#{current_account.subdomain}." : ""
ActionMailer::Base.default_url_options[:host] = "#{subdomain}lvh.me:3000"
end
def after_sign_out_path_for(resource_or_scope)
new_user_session_path
end
def after_invite_path_for(resource)
users_path
end
end
Here is my Devise initializer (config/initializers/devise.rb), I have added the line "config.allow_insecure_token_lookup = true" to see if this helps, but to no avail...
Devise.setup do |config|
config.mailer_sender = 'please-change-me-at-config-initializers-devise#example.com'
require 'devise/orm/active_record'
config.case_insensitive_keys = [ :email ]
config.strip_whitespace_keys = [ :email ]
config.skip_session_storage = [:http_auth]
config.stretches = Rails.env.test? ? 1 : 10
config.reconfirmable = true
config.expire_all_remember_me_on_sign_out = true
config.password_length = 8..128
config.sign_out_via = :delete
config.allow_insecure_token_lookup = true
end
I'd prefer to comment but I have only 36 points and am not allowed so here's an incomplete answer:
this is the code from devise_invitable InvitationsController which is redirecting your request
def resource_from_invitation_token
unless params[:invitation_token] && self.resource = resource_class.find_by_invitation_token(params[:invitation_token], true)
set_flash_message(:alert, :invitation_token_invalid)
redirect_to after_sign_out_path_for(resource_name)
end
end
in your rails console try running:
token = '3GXDmi7NntDRdhvo57q5' #the token sent in the invitation email
User.find_by_invitation_token(token, true)
and see if that returns your User. It probably won't but maybe this will bring you closer to an answer. I hope so.

Devise Google Oauth works perfectly but doesn't sign-in on user creation, requires additional log on

I have Devise running on my Rails 3.2 application. Google Oauth is used to sign in.
New Users attempt to sign in with Google and are redirected to the sign-in page without being signed in. I check the DB and the User's accounts are created with the correct credentials (everything is correct except IP).
Returning Users have no problem signing in, Log out also works perfectly.
I'm not sure what I am doing wrong, I followed this tutorial: http://blogs.burnsidedigital.com/2013/03/rails-3-devise-omniauth-and-google/
The difference is that I do not have any need for additional user information, I just want to authenticate users through their google accounts ensuring they belong to a certain domain foobar.com
I have an OmniAuth controller which looks like this:
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
auth = request.env["omniauth.auth"]
proceeder = !!(auth.info.email =~ /^[a-zA-Z0-9.]+#foobar\.com$/)
if proceeder
user = User.from_omniauth(auth)
flash.notice = "Signed in!"
sign_in_and_redirect user
redirect_to :root
else
flash[:notice] = "You must use an email ending in #foobar.com"
redirect_to signup_path
end
and my User model is as follows:
class User < ActiveRecord::Base
has_many :posts
has_many :comments
has_many :votes
has_many :reports
devise :database_authenticatable, :registerable, :omniauthable,
:recoverable, :rememberable, :trackable, :validatable#, :omniauth_providers => [:google_oauth2]
attr_accessible :email, :password, :password_confirmation, :remember_me, :provider, :uid
def self.from_omniauth(auth)
if user = User.find_by_email(auth.info.email)
user.provider = auth.provider
user.uid = auth.uid
user
else
where(auth.slice(:provider, :uid)).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
user
end
end
end
end
For visitors who are not signed in I call posts#login
class PostsController < ApplicationController
...
def login
Rails.logger.debug(current_user)
if current_user
redirect_to :root
end
end
...
and the root_path contains a current_user check which redirects to posts#login if no user is logged in.
I thought the problem was within the method sign_in_and_redirect so I added the following to my ApplicationController:
class ApplicationController < ActionController::Base
protect_from_forgery
serialization_scope :view_context
def after_sign_in_path_for(resource)
root_url
end
def after_sign_up_path_for(resource)
root_url
end
end
Why aren't new accounts signed in? Why would their accounts be created but not logged in?
Any help is greatly appreciated, I am completely stumped (Devise documentation didn't lead me to a solution).
EDIT
Here are the development logs of a new user signing in/up:
>> Listening on 0.0.0.0:3000, CTRL+C to stop
Started GET "/signup" for 127.0.0.1 at 2013-11-16 16:58:54 -0500
Processing by PostsController#login as HTML
Rendered posts/login.html.erb within layouts/application (24.0ms)
Completed 200 OK in 31ms (Views: 30.6ms | ActiveRecord: 0.0ms)
(google_oauth2) Request phase initiated.
Started GET "/users/auth/google_oauth2" for 127.0.0.1 at 2013-11-16 16:58:56 -0500
(google_oauth2) Callback phase initiated.
Started GET "/users/auth/google_oauth2/callback?state=e5c02458190b79758da474baa623717a29078427ad6049f7&code=4/yimrxaCXMOY_FTZyAgd_-CpZxMrF.EhatByjkrMkYshQV0ieZDAoQx9zFhAI" for 127.0.0.1 at 2013-11-16 16:59:00 -0500
Processing by OmniauthCallbacksController#google_oauth2 as HTML
Parameters: {"state"=>"e5c02458190b79758da474baa623717a29078427ad6049f7", "code"=>"4/yimrxaCXMOY_FTZyAgd_-CpZxMrF.EhatByjkrMkYshQV0ieZDAoQx9zFhAI"}
User Load (54.0ms) SELECT "users".* FROM "users" WHERE "users"."email" = 'jquadr01#foobar.com' LIMIT 1
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."provider" = 'google_oauth2' AND "users"."uid" = '105565017494971239846' LIMIT 1
(0.1ms) BEGIN
User Exists (0.4ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = 'jquadr01#foobar.com' LIMIT 1
(0.1ms) ROLLBACK
(0.1ms) BEGIN
SQL (76.2ms) INSERT INTO "users" ("created_at", "current_sign_in_at", "current_sign_in_ip", "email", "encrypted_password", "last_sign_in_at", "last_sign_in_ip", "provider", "remember_created_at", "reset_password_sent_at", "reset_password_token", "sign_in_count", "uid", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) RETURNING "id" [["created_at", Sat, 16 Nov 2013 21:59:01 UTC +00:00], ["current_sign_in_at", Sat, 16 Nov 2013 21:59:01 UTC +00:00], ["current_sign_in_ip", "127.0.0.1"], ["email", "jquadr01#foobar.com"], ["encrypted_password", ""], ["last_sign_in_at", Sat, 16 Nov 2013 21:59:01 UTC +00:00], ["last_sign_in_ip", "127.0.0.1"], ["provider", "google_oauth2"], ["remember_created_at", nil], ["reset_password_sent_at", nil], ["reset_password_token", nil], ["sign_in_count", 1], ["uid", "1055650112345678911846"], ["updated_at", Sat, 16 Nov 2013 21:59:01 UTC +00:00]]
(16.9ms) COMMIT
#<User:0x000000020d7a08>
Redirected to http://localhost:3000/
Completed 302 Found in 338ms (ActiveRecord: 162.0ms)
Started GET "/" for 127.0.0.1 at 2013-11-16 16:59:01 -0500
Processing by MainController#index as HTML
User Load (0.8ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT 1
Redirected to http://localhost:3000/signup
Completed 302 Found in 5ms (ActiveRecord: 0.8ms)
Started GET "/signup" for 127.0.0.1 at 2013-11-16 16:59:01 -0500
Processing by PostsController#login as HTML
Rendered posts/login.html.erb within layouts/application (0.5ms)
Completed 200 OK in 4ms (Views: 2.7ms | ActiveRecord: 0.0m
You say “New Users attempt to sign in with Google and are redirected to the sign-in page without being signed in” and I’m not 100% sure what that means. Every time you use Google OAuth to let someone into your app, they’re going to see a one-time approval screen so they get a chance to say whether or not they’re OK with their identity being sent to your app. They really shouldn’t be going to the sign-in page if they’re already signed in. Which page do they go to?
I don't have a sure solution, but I have an idea.
Consider this code:
if proceeder
user = User.from_omniauth(auth)
flash.notice = "Signed in!"
sign_in_and_redirect user
redirect_to :root
Notice that you're triggering two redirects. First you call the devise redirect, and then you call redirect_to :root. Normally, if you issue two redirects in the same action, it results in an AbstractController::DoubleRenderError. The fact that you're not getting a DoubleRenderError is a clue that something is not right with sign_in_and_redirect.
Now, I don't know what's wrong with sign_in_and_redirect, so let's examine the source:
# File 'lib/devise/controllers/helpers.rb', line 159
def sign_in_and_redirect(resource_or_scope, *args)
options = args.extract_options!
scope = Devise::Mapping.find_scope!(resource_or_scope)
resource = args.last || resource_or_scope
sign_in(scope, resource, options)
redirect_to after_sign_in_path_for(resource)
end
I'm guessing it has something to do with finding the user scope, since the rest of it looks okay, and perhaps your mappings are not configured correctly.
In order to avoid any ambiguity (as well as the DoubleRenderError that I would expect to be happening), try replacing the above code with this:
if proceeder
user = User.from_omniauth(auth)
flash.notice = "Signed in!"
sign_in :user, user
redirect_to :root
Let me know if that works, and if not, I'll take another crack at it.
P.S. do you see the flash message "Signed in!" after you authenticate with Google?
As described here, add the following code to your OmniauthCallbacksController:
skip_before_filter :verify_authenticity_token
The user isn't signed in because of CSRF authentication failure. In Rails 4, if the CSRF authentication fails, the default behaviour is :null_session, which is why the user isn't signed in.
EDIT :
The issue seems to be with the code that creates a new user in the User.from_omniauth method. You're creating a new user, if one doesn't exist with a given provider and uid, without setting the email attribute, which can't be blank! Consequently, validation fails and the user object is not persisted, and hence there's no valid session.

Resources