Rails : Devise LDAP Authenticate 401 Unauthorized - ruby-on-rails

my company asked me to migrate an application to an Ruby on Rails Web app, but i'm not really experimented on that technology.
The users have to connect to that app with their Active Directory identifiers, so i saw the gem devise_ldap_authenticatable could do that but i always have a error message when cliking "log in" in my server console :
config/initializers/ldpa_authenticatable.rb:14:in `authenticate!'
Completed 401 Unauthorized in 7ms (ActiveRecord: 0.2ms | Allocations: 2778)
Is anyone else met the same problem ? I'm searching for hour here but all solutions i saw don't work at me...
My ldap.yml file :
development:
host: <Host IP>
#port: 389
attribute: sAMAccountName #cn
base: ou=xxxxx,dc=xxxx,dc=xx
admin_user: cn=xxxxxx,dc=xxxx,dc=xx
admin_password: <password>
ssl: false
My User.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :ldap_authenticatable, :registerable,
:recoverable, :rememberable, :validatable
attr_accessor :username
end
sessions_controler.rb
# frozen_string_literal: true
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
super
end
# DELETE /resource/sign_out
def destroy
super
end
protected
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_in_params
added_attrs = [:username, :encrypted_password]
devise_parameter_sanitizer.permit(:sign_in, keys: added_attrs)
end
end
devise.rb
Devise.setup do |config|
# ==> LDAP Configuration
config.ldap_logger = true
config.ldap_create_user = true
config.ldap_update_password = false
config.ldap_config = "#{Rails.root}/config/ldap.yml"
config.ldap_auth_username_builder = Proc.new() {|attribute, username, ldap| "#{username}" }
# config.ldap_check_group_membership = false
# config.ldap_check_group_membership_without_admin = false
# config.ldap_check_attributes = false
# config.ldap_check_attributes_presence = false
config.ldap_use_admin_to_bind = true
# config.ldap_ad_group_check = false
config.authentication_keys = [:username]
Thanks for your help i really don't know what to do...

Related

Devise & Ruby on Rails: How to resolve "Completed 401 Unauthorized" when trying to Log In

I'm trying to use the Devise gem (v4.7.2) with Ruby on Rails (v6.0.3.2).
I'm receiving the following output when I click on the Sign In button:
Started POST "/users/sign_in" for ::1 at 2020-11-21 18:02:54 +0000
Processing by Devise::SessionsController#create as HTML
Parameters: {"authenticity_token"=>"3tBTwyz4dIihzNvUllHVX1b9iOzVANtyceTYQY9vfn2mHdSfmG9ivEFapBiry7I8753OCP6MrMkIVckxSGTxnQ==", "user"=>{"email"=>"johanhanlon#gmail.com", "password"=>"[FILTERED]"}}
Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms | Allocations: 486)
Processing by Devise::SessionsController#new as HTML
Parameters: {"authenticity_token"=>"3tBTwyz4dIihzNvUllHVX1b9iOzVANtyceTYQY9vfn2mHdSfmG9ivEFapBiry7I8753OCP6MrMkIVckxSGTxnQ==", "user"=>{"email"=>"johanhanlon#gmail.com", "password"=>"[FILTERED]"}}
Rendering devise/sessions/new.html.erb within layouts/application
Rendered devise/shared/_links.html.erb (Duration: 0.4ms | Allocations: 191)
Rendered devise/sessions/new.html.erb within layouts/application (Duration: 15.9ms | Allocations: 602)
[Webpacker] Everything's up-to-date. Nothing to do
Rendered layouts/nav/_public.html.erb (Duration: 1.2ms | Allocations: 151)
Completed 200 OK in 347ms (Views: 90.4ms | ActiveRecord: 0.0ms | Allocations: 21362)
"Completed 401 Unauthorized" is showing and I'm not sure how to resolve this. Here are my files:
config/initializers/devise.rb:
# frozen_string_literal: true
# Assuming you have not yet modified this file, each configuration option below
# is set to its default value. Note that some are commented out while others
# are not: uncommented lines are intended to protect your configuration from
# breaking changes in upgrades (i.e., in the event that future versions of
# Devise change the default values for those options).
#
# 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|
# The secret key used by Devise. Devise uses this key to generate
# random tokens. Changing this key will render invalid all existing
# confirmation, reset password and unlock tokens in the database.
# Devise will use the `secret_key_base` as its `secret_key`
# by default. You can change it below and use your own secret key.
# config.secret_key = '###'
# ==> Controller configuration
# Configure the parent class to the devise controllers.
# config.parent_controller = 'DeviseController'
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class
# with default "from" parameter.
config.mailer_sender = 'please-change-me-at-config-initializers-devise#example.com'
# Configure the class responsible to send e-mails.
# config.mailer = 'Devise::Mailer'
# Configure the parent class responsible to send e-mails.
# config.parent_mailer = 'ActionMailer::Base'
# ==> ORM configuration
# Load and configure the ORM. Supports :active_record (default) and
# :mongoid (bson_ext recommended) by default. Other ORMs may be
# available as additional gems.
require 'devise/orm/active_record'
# ==> Configuration for any authentication mechanism
# Configure which keys are used when authenticating a user. The default is
# just :email. You can configure it to use [:username, :subdomain], so for
# authenticating a user, both parameters are required. Remember that those
# parameters are used only when authenticating and not when retrieving from
# session. If you need permissions, you should implement that in a before filter.
# You can also supply a hash where the value is a boolean determining whether
# or not authentication should be aborted when the value is not present.
# config.authentication_keys = [:email]
config.authentication_keys = [ :login ]
# Configure parameters from the request object used for authentication. Each entry
# given should be a request method and it will automatically be passed to the
# find_for_authentication method and considered in your model lookup. For instance,
# if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
# The same considerations mentioned for authentication_keys also apply to request_keys.
# config.request_keys = []
# Configure which authentication keys should be case-insensitive.
# These keys will be downcased upon creating or modifying a user and when used
# to authenticate or find a user. Default is :email.
config.case_insensitive_keys = [:email]
# Configure which authentication keys should have whitespace stripped.
# These keys will have whitespace before and after removed upon creating or
# modifying a user and when used to authenticate or find a user. Default is :email.
config.strip_whitespace_keys = [:email]
# Tell if authentication through request.params is enabled. True by default.
# It can be set to an array that will enable params authentication only for the
# given strategies, for example, `config.params_authenticatable = [:database]` will
# enable it only for database (email + password) authentication.
# config.params_authenticatable = true
# Tell if authentication through HTTP Auth is enabled. False by default.
# It can be set to an array that will enable http authentication only for the
# given strategies, for example, `config.http_authenticatable = [:database]` will
# enable it only for database authentication.
# For API-only applications to support authentication "out-of-the-box", you will likely want to
# enable this with :database unless you are using a custom strategy.
# The supported strategies are:
# :database = Support basic authentication with authentication key + password
# config.http_authenticatable = false
# If 401 status code should be returned for AJAX requests. True by default.
# config.http_authenticatable_on_xhr = true
# The realm used in Http Basic Authentication. 'Application' by default.
# config.http_authentication_realm = 'Application'
# It will change confirmation, password recovery and other workflows
# to behave the same regardless if the e-mail provided was right or wrong.
# Does not affect registerable.
# config.paranoid = true
# By default Devise will store the user in session. You can skip storage for
# particular strategies by setting this option.
# Notice that if you are skipping storage for all authentication paths, you
# may want to disable generating routes to Devise's sessions controller by
# passing skip: :sessions to `devise_for` in your config/routes.rb
config.skip_session_storage = [:http_auth]
# By default, Devise cleans up the CSRF token on authentication to
# avoid CSRF token fixation attacks. This means that, when using AJAX
# requests for sign in and sign up, you need to get a new CSRF token
# from the server. You can disable this option at your own risk.
# config.clean_up_csrf_token_on_authentication = true
# When false, Devise will not attempt to reload routes on eager load.
# This can reduce the time taken to boot the app but if your application
# requires the Devise mappings to be loaded during boot time the application
# won't boot properly.
# config.reload_routes = true
# ==> Configuration for :database_authenticatable
# For bcrypt, this is the cost for hashing the password and defaults to 12. If
# using other algorithms, it sets how many times you want the password to be hashed.
# The number of stretches used for generating the hashed password are stored
# with the hashed password. This allows you to change the stretches without
# invalidating existing passwords.
#
# Limiting the stretches to just one in testing will increase the performance of
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
# a value less than 10 in other environments. Note that, for bcrypt (the default
# algorithm), the cost increases exponentially with the number of stretches (e.g.
# a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
config.stretches = Rails.env.test? ? 1 : 12
# Set up a pepper to generate the hashed password.
# config.pepper = '###'
# Send a notification to the original email when the user's email is changed.
# config.send_email_changed_notification = false
# Send a notification email when the user's password is changed.
# config.send_password_change_notification = false
# ==> Configuration for :confirmable
# A period that the user is allowed to access the website even without
# confirming their account. For instance, if set to 2.days, the user will be
# able to access the website for two days without confirming their account,
# access will be blocked just in the third day.
# You can also set it to nil, which will allow the user to access the website
# without confirming their account.
# Default is 0.days, meaning the user cannot access the website without
# confirming their account.
# config.allow_unconfirmed_access_for = 2.days
# A period that the user is allowed to confirm their account before their
# token becomes invalid. For example, if set to 3.days, the user can confirm
# their account within 3 days after the mail was sent, but on the fourth day
# their account can't be confirmed with the token any more.
# Default is nil, meaning there is no restriction on how long a user can take
# before confirming their account.
# config.confirm_within = 3.days
# If true, requires any email changes to be confirmed (exactly the same way as
# initial account confirmation) to be applied. Requires additional unconfirmed_email
# db field (see migrations). Until confirmed, new email is stored in
# unconfirmed_email column, and copied to email column on successful confirmation.
config.reconfirmable = true
# Defines which key will be used when confirming an account
# config.confirmation_keys = [:email]
# ==> Configuration for :rememberable
# The time the user will be remembered without asking for credentials again.
# config.remember_for = 2.weeks
# Invalidates all the remember me tokens when the user signs out.
config.expire_all_remember_me_on_sign_out = true
# If true, extends the user's remember period when remembered via cookie.
# config.extend_remember_period = false
# Options to be passed to the created cookie. For instance, you can set
# secure: true in order to force SSL only cookies.
# config.rememberable_options = {}
# ==> Configuration for :validatable
# Range for password length.
config.password_length = 6..128
# Email regex used to validate email formats. It simply asserts that
# one (and only one) # exists in the given string. This is mainly
# to give user feedback and not to assert the e-mail validity.
config.email_regexp = /\A[^#\s]+#[^#\s]+\z/
# ==> Configuration for :timeoutable
# The time you want to timeout the user session without activity. After this
# time the user will be asked for credentials again. Default is 30 minutes.
# config.timeout_in = 30.minutes
# ==> Configuration for :lockable
# Defines which strategy will be used to lock an account.
# :failed_attempts = Locks an account after a number of failed attempts to sign in.
# :none = No lock strategy. You should handle locking by yourself.
# config.lock_strategy = :failed_attempts
# Defines which key will be used when locking and unlocking an account
# config.unlock_keys = [:email]
# Defines which strategy will be used to unlock an account.
# :email = Sends an unlock link to the user email
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
# :both = Enables both strategies
# :none = No unlock strategy. You should handle unlocking by yourself.
# config.unlock_strategy = :both
# Number of authentication tries before locking an account if lock_strategy
# is failed attempts.
# config.maximum_attempts = 20
# Time interval to unlock the account if :time is enabled as unlock_strategy.
# config.unlock_in = 1.hour
# Warn on the last attempt before the account is locked.
# config.last_attempt_warning = true
# ==> Configuration for :recoverable
#
# Defines which key will be used when recovering the password for an account
# config.reset_password_keys = [:email]
# Time interval you can reset your password with a reset password key.
# Don't put a too small interval or your users won't have the time to
# change their passwords.
config.reset_password_within = 6.hours
# When set to false, does not sign a user in automatically after their password is
# reset. Defaults to true, so a user is signed in automatically after a reset.
# config.sign_in_after_reset_password = true
# ==> Configuration for :encryptable
# Allow you to use another hashing or encryption algorithm besides bcrypt (default).
# You can use :sha1, :sha512 or algorithms from others authentication tools as
# :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20
# for default behavior) and :restful_authentication_sha1 (then you should set
# stretches to 10, and copy REST_AUTH_SITE_KEY to pepper).
#
# Require the `devise-encryptable` gem when using anything other than bcrypt
# config.encryptor = :sha512
# ==> Scopes configuration
# Turn scoped views on. Before rendering "sessions/new", it will first check for
# "users/sessions/new". It's turned off by default because it's slower if you
# are using only default views.
# config.scoped_views = false
# Configure the default scope given to Warden. By default it's the first
# devise role declared in your routes (usually :user).
# config.default_scope = :user
# Set this configuration to false if you want /users/sign_out to sign out
# only the current scope. By default, Devise signs out all scopes.
# config.sign_out_all_scopes = true
# ==> Navigation configuration
# Lists the formats that should be treated as navigational. Formats like
# :html, should redirect to the sign in page when the user does not have
# access, but formats like :xml or :json, should return 401.
#
# If you have any extra navigational formats, like :iphone or :mobile, you
# should add them to the navigational formats lists.
#
# The "*/*" below is required to match Internet Explorer requests.
# config.navigational_formats = ['*/*', :html]
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :delete
# ==> OmniAuth
# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
# ==> Warden configuration
# If you want to use other strategies, that are not supported by Devise, or
# change the failure app, you can configure them inside the config.warden block.
#
# config.warden do |manager|
# manager.intercept_401 = false
# manager.default_strategies(scope: :user).unshift :some_external_strategy
# end
# ==> Mountable engine configurations
# When using Devise inside an engine, let's call it `MyEngine`, and this engine
# is mountable, there are some extra configurations to be taken into account.
# The following options are available, assuming the engine is mounted as:
#
# mount MyEngine, at: '/my_engine'
#
# The router that invoked `devise_for`, in the example above, would be:
# config.router_name = :my_engine
#
# When using OmniAuth, Devise cannot automatically set OmniAuth path,
# so you need to do it manually. For the users scope, it would be:
# config.omniauth_path_prefix = '/my_engine/users/auth'
# ==> Turbolinks configuration
# If your app is using Turbolinks, Turbolinks::Controller needs to be included to make redirection work correctly:
#
# ActiveSupport.on_load(:devise_failure_app) do
# include Turbolinks::Controller
# end
# ==> Configuration for :registerable
# When set to false, does not sign a user in automatically after their password is
# changed. Defaults to true, so a user is signed in automatically after changing a password.
# config.sign_in_after_change_password = true
end
models/user.rb
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable,
:validatable, :confirmable, authentication_keys: [:login]
# Create relationship - User has many properties.
has_many :properties
attr_writer :login
def login
#login || self.username || self.email
end
end
controllers/application_controller.rb:
class ApplicationController < ActionController::Base
protect_from_forgery prepend: true
before_action :configure_permitted_parameters, if: :devise_controller?
def index
end
protected
# Restrict parameters for sign up input.
def configure_permitted_parameters
added_attrs = [:first_name, :last_name, :email, :password, :password_confirmation, :remember_me]
devise_parameter_sanitizer.permit :sign_up, keys: added_attrs
devise_parameter_sanitizer.permit :account_update, keys: added_attrs
devise_parameter_sanitizer.permit :sign_in, keys: added_attrs
end
end
controllers/users/sessions_controller.rb:
# frozen_string_literal: true
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
# super
# end
# DELETE /resource/sign_out
# def destroy
# super
# end
# protected
# If you have extra params to permit, append them to the sanitizer.
# def configure_sign_in_params
# devise_parameter_sanitizer.permit(:sign_in, keys: [:attribute])
# end
end
views/devise/sessions/new.html.erb:
<section class="form-auth text-center">
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<!-- <img class="mb-4" src="" alt="" width="72" height="72"> -->
<h1 class="h3 mb-3 font-weight-normal">Please Log In</h1>
<label for="inputEmail" class="sr-only">Email address</label>
<%= f.email_field :email, autofocus: true, class: "form-control", id: "inputEmail", placeholder: "Email address", autocomplete: "current-email", required: "" %>
<label for="inputPassword" class="sr-only">Password</label>
<%= f.password_field :password, autocomplete: "current-password", placeholder: "Password", class: "form-control", id: "inputPassword", required: "" %>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2020</p>
<% end %>
<%= render "devise/shared/links" %>
</section>
Appreciate any help.
I solved this and my working code is below.
The main issue was that I was passing in an incorrect parameter in my configure_permitted_parameters function when sanitizing the parameters. I was passing in :password but this should have been :encrypted_password. See below.
# Restrict parameters for sign up input.
def configure_permitted_parameters
added_attrs = [:first_name, :last_name, :email, :encrypted_password, :password_confirmation, :remember_me]
devise_parameter_sanitizer.permit(:sign_up, keys: added_attrs)
devise_parameter_sanitizer.permit(:account_update, keys: added_attrs)
devise_parameter_sanitizer.permit(:sign_in, keys: added_attrs)
end
The parameter/attribute :encrypted_password being sanitized is shown below in the db/migrate/xxxxxxxxxxxxxx_devise_create_users.rb migration file:
# frozen_string_literal: true
class DeviseCreateUsers < ActiveRecord::Migration[6.0]
def change
create_table :users do |t|
## Database authenticatable
t.string :first_name, null: false, default: ""
t.string :last_name, null: false, default: ""
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
t.string :url
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.inet :current_sign_in_ip
t.inet :last_sign_in_ip
## Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
end
Other files from the question are below for reference:
config/initializers/devise.rb below:
# frozen_string_literal: true
# Assuming you have not yet modified this file, each configuration option below
# is set to its default value. Note that some are commented out while others
# are not: uncommented lines are intended to protect your configuration from
# breaking changes in upgrades (i.e., in the event that future versions of
# Devise change the default values for those options).
#
# 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|
# The secret key used by Devise. Devise uses this key to generate
# random tokens. Changing this key will render invalid all existing
# confirmation, reset password and unlock tokens in the database.
# Devise will use the `secret_key_base` as its `secret_key`
# by default. You can change it below and use your own secret key.
# config.secret_key = 'INSERT YOUR SECREY KEY HERE'
# ==> Controller configuration
# Configure the parent class to the devise controllers.
# config.parent_controller = 'DeviseController'
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class
# with default "from" parameter.
config.mailer_sender = 'please-change-me-at-config-initializers-devise#example.com'
# Configure the class responsible to send e-mails.
# config.mailer = 'Devise::Mailer'
# Configure the parent class responsible to send e-mails.
# config.parent_mailer = 'ActionMailer::Base'
# ==> ORM configuration
# Load and configure the ORM. Supports :active_record (default) and
# :mongoid (bson_ext recommended) by default. Other ORMs may be
# available as additional gems.
require 'devise/orm/active_record'
# ==> Configuration for any authentication mechanism
# Configure which keys are used when authenticating a user. The default is
# just :email. You can configure it to use [:username, :subdomain], so for
# authenticating a user, both parameters are required. Remember that those
# parameters are used only when authenticating and not when retrieving from
# session. If you need permissions, you should implement that in a before filter.
# You can also supply a hash where the value is a boolean determining whether
# or not authentication should be aborted when the value is not present.
# config.authentication_keys = [:email]
# config.authentication_keys = [ :login ]
# Configure parameters from the request object used for authentication. Each entry
# given should be a request method and it will automatically be passed to the
# find_for_authentication method and considered in your model lookup. For instance,
# if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
# The same considerations mentioned for authentication_keys also apply to request_keys.
# config.request_keys = []
# Configure which authentication keys should be case-insensitive.
# These keys will be downcased upon creating or modifying a user and when used
# to authenticate or find a user. Default is :email.
config.case_insensitive_keys = [:email]
# Configure which authentication keys should have whitespace stripped.
# These keys will have whitespace before and after removed upon creating or
# modifying a user and when used to authenticate or find a user. Default is :email.
config.strip_whitespace_keys = [:email]
# Tell if authentication through request.params is enabled. True by default.
# It can be set to an array that will enable params authentication only for the
# given strategies, for example, `config.params_authenticatable = [:database]` will
# enable it only for database (email + password) authentication.
# config.params_authenticatable = true
# Tell if authentication through HTTP Auth is enabled. False by default.
# It can be set to an array that will enable http authentication only for the
# given strategies, for example, `config.http_authenticatable = [:database]` will
# enable it only for database authentication.
# For API-only applications to support authentication "out-of-the-box", you will likely want to
# enable this with :database unless you are using a custom strategy.
# The supported strategies are:
# :database = Support basic authentication with authentication key + password
# config.http_authenticatable = false
# If 401 status code should be returned for AJAX requests. True by default.
# config.http_authenticatable_on_xhr = true
# The realm used in Http Basic Authentication. 'Application' by default.
# config.http_authentication_realm = 'Application'
# It will change confirmation, password recovery and other workflows
# to behave the same regardless if the e-mail provided was right or wrong.
# Does not affect registerable.
# config.paranoid = true
# By default Devise will store the user in session. You can skip storage for
# particular strategies by setting this option.
# Notice that if you are skipping storage for all authentication paths, you
# may want to disable generating routes to Devise's sessions controller by
# passing skip: :sessions to `devise_for` in your config/routes.rb
config.skip_session_storage = [:http_auth]
# By default, Devise cleans up the CSRF token on authentication to
# avoid CSRF token fixation attacks. This means that, when using AJAX
# requests for sign in and sign up, you need to get a new CSRF token
# from the server. You can disable this option at your own risk.
# config.clean_up_csrf_token_on_authentication = true
# When false, Devise will not attempt to reload routes on eager load.
# This can reduce the time taken to boot the app but if your application
# requires the Devise mappings to be loaded during boot time the application
# won't boot properly.
# config.reload_routes = true
# ==> Configuration for :database_authenticatable
# For bcrypt, this is the cost for hashing the password and defaults to 12. If
# using other algorithms, it sets how many times you want the password to be hashed.
# The number of stretches used for generating the hashed password are stored
# with the hashed password. This allows you to change the stretches without
# invalidating existing passwords.
#
# Limiting the stretches to just one in testing will increase the performance of
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
# a value less than 10 in other environments. Note that, for bcrypt (the default
# algorithm), the cost increases exponentially with the number of stretches (e.g.
# a value of 20 is already extremely slow: approx. 60 seconds for 1 calculation).
config.stretches = Rails.env.test? ? 1 : 12
# Set up a pepper to generate the hashed password.
# config.pepper = 'xxx'
# Send a notification to the original email when the user's email is changed.
# config.send_email_changed_notification = false
# Send a notification email when the user's password is changed.
# config.send_password_change_notification = false
# ==> Configuration for :confirmable
# A period that the user is allowed to access the website even without
# confirming their account. For instance, if set to 2.days, the user will be
# able to access the website for two days without confirming their account,
# access will be blocked just in the third day.
# You can also set it to nil, which will allow the user to access the website
# without confirming their account.
# Default is 0.days, meaning the user cannot access the website without
# confirming their account.
# config.allow_unconfirmed_access_for = 2.days
# A period that the user is allowed to confirm their account before their
# token becomes invalid. For example, if set to 3.days, the user can confirm
# their account within 3 days after the mail was sent, but on the fourth day
# their account can't be confirmed with the token any more.
# Default is nil, meaning there is no restriction on how long a user can take
# before confirming their account.
# config.confirm_within = 3.days
# If true, requires any email changes to be confirmed (exactly the same way as
# initial account confirmation) to be applied. Requires additional unconfirmed_email
# db field (see migrations). Until confirmed, new email is stored in
# unconfirmed_email column, and copied to email column on successful confirmation.
config.reconfirmable = true
# Defines which key will be used when confirming an account
# config.confirmation_keys = [:email]
# ==> Configuration for :rememberable
# The time the user will be remembered without asking for credentials again.
# config.remember_for = 2.weeks
# Invalidates all the remember me tokens when the user signs out.
config.expire_all_remember_me_on_sign_out = true
# If true, extends the user's remember period when remembered via cookie.
# config.extend_remember_period = false
# Options to be passed to the created cookie. For instance, you can set
# secure: true in order to force SSL only cookies.
# config.rememberable_options = {}
# ==> Configuration for :validatable
# Range for password length.
config.password_length = 6..128
# Email regex used to validate email formats. It simply asserts that
# one (and only one) # exists in the given string. This is mainly
# to give user feedback and not to assert the e-mail validity.
config.email_regexp = /\A[^#\s]+#[^#\s]+\z/
# ==> Configuration for :timeoutable
# The time you want to timeout the user session without activity. After this
# time the user will be asked for credentials again. Default is 30 minutes.
# config.timeout_in = 30.minutes
# ==> Configuration for :lockable
# Defines which strategy will be used to lock an account.
# :failed_attempts = Locks an account after a number of failed attempts to sign in.
# :none = No lock strategy. You should handle locking by yourself.
# config.lock_strategy = :failed_attempts
# Defines which key will be used when locking and unlocking an account
# config.unlock_keys = [:email]
# Defines which strategy will be used to unlock an account.
# :email = Sends an unlock link to the user email
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
# :both = Enables both strategies
# :none = No unlock strategy. You should handle unlocking by yourself.
# config.unlock_strategy = :both
# Number of authentication tries before locking an account if lock_strategy
# is failed attempts.
# config.maximum_attempts = 20
# Time interval to unlock the account if :time is enabled as unlock_strategy.
# config.unlock_in = 1.hour
# Warn on the last attempt before the account is locked.
# config.last_attempt_warning = true
# ==> Configuration for :recoverable
#
# Defines which key will be used when recovering the password for an account
# config.reset_password_keys = [:email]
# Time interval you can reset your password with a reset password key.
# Don't put a too small interval or your users won't have the time to
# change their passwords.
config.reset_password_within = 6.hours
# When set to false, does not sign a user in automatically after their password is
# reset. Defaults to true, so a user is signed in automatically after a reset.
# config.sign_in_after_reset_password = true
# ==> Configuration for :encryptable
# Allow you to use another hashing or encryption algorithm besides bcrypt (default).
# You can use :sha1, :sha512 or algorithms from others authentication tools as
# :clearance_sha1, :authlogic_sha512 (then you should set stretches above to 20
# for default behavior) and :restful_authentication_sha1 (then you should set
# stretches to 10, and copy REST_AUTH_SITE_KEY to pepper).
#
# Require the `devise-encryptable` gem when using anything other than bcrypt
# config.encryptor = :sha512
# ==> Scopes configuration
# Turn scoped views on. Before rendering "sessions/new", it will first check for
# "users/sessions/new". It's turned off by default because it's slower if you
# are using only default views.
# config.scoped_views = false
# Configure the default scope given to Warden. By default it's the first
# devise role declared in your routes (usually :user).
# config.default_scope = :user
# Set this configuration to false if you want /users/sign_out to sign out
# only the current scope. By default, Devise signs out all scopes.
# config.sign_out_all_scopes = true
# ==> Navigation configuration
# Lists the formats that should be treated as navigational. Formats like
# :html, should redirect to the sign in page when the user does not have
# access, but formats like :xml or :json, should return 401.
#
# If you have any extra navigational formats, like :iphone or :mobile, you
# should add them to the navigational formats lists.
#
# The "*/*" below is required to match Internet Explorer requests.
# config.navigational_formats = ['*/*', :html]
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :delete
# ==> OmniAuth
# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
# ==> Warden configuration
# If you want to use other strategies, that are not supported by Devise, or
# change the failure app, you can configure them inside the config.warden block.
#
# config.warden do |manager|
# manager.intercept_401 = false
# manager.default_strategies(scope: :user).unshift :some_external_strategy
# end
# ==> Mountable engine configurations
# When using Devise inside an engine, let's call it `MyEngine`, and this engine
# is mountable, there are some extra configurations to be taken into account.
# The following options are available, assuming the engine is mounted as:
#
# mount MyEngine, at: '/my_engine'
#
# The router that invoked `devise_for`, in the example above, would be:
# config.router_name = :my_engine
#
# When using OmniAuth, Devise cannot automatically set OmniAuth path,
# so you need to do it manually. For the users scope, it would be:
# config.omniauth_path_prefix = '/my_engine/users/auth'
# ==> Turbolinks configuration
# If your app is using Turbolinks, Turbolinks::Controller needs to be included to make redirection work correctly:
#
ActiveSupport.on_load(:devise_failure_app) do
include Turbolinks::Controller
end
# ==> Configuration for :registerable
# When set to false, does not sign a user in automatically after their password is
# changed. Defaults to true, so a user is signed in automatically after changing a password.
# config.sign_in_after_change_password = true
end
models/user.rb below:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
# devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable, :trackable, :confirmable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable,
:validatable, :confirmable#, authentication_keys: [:login]
# Create relationship - User has many properties.
has_and_belongs_to_many :properties
has_many :portfolios, dependent: :destroy
# attr_writer :login
# def login
# # #login || self.username || self.email
# #login || self.email || self.encrypted_password
# end
# def contact_name
# "#{first_name} #{last_name}"
# end
# def company_name
# "AGENT"
# end
end
controllers/application_controller.rb below:
class ApplicationController < ActionController::Base
# Store last page for redirecting to last page on log in or log out.
before_action :store_user_location!, if: :storable_location?
protect_from_forgery prepend: true
# To enable sign in to function correctly.
skip_before_action :verify_authenticity_token, :only => :create
before_action :configure_permitted_parameters, if: :devise_controller?
def index
end
protected
# Restrict parameters for sign up input.
def configure_permitted_parameters
added_attrs = [:first_name, :last_name, :email, :encrypted_password, :password_confirmation, :remember_me]
devise_parameter_sanitizer.permit(:sign_up, keys: added_attrs)
devise_parameter_sanitizer.permit(:account_update, keys: added_attrs)
devise_parameter_sanitizer.permit(:sign_in, keys: added_attrs)
end
private
def storable_location?
request.get? && is_navigational_format? && !devise_controller? && !request.xhr?
end
def store_user_location!
# :user is the scope we are authenticating
store_location_for(:user, request.fullpath)
end
end
controllers/users/sessions_controller.rb below:
# frozen_string_literal: true
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
# super
# end
# DELETE /users/sign_out
# def destroy
# super
# end
def after_sign_in_path_for(resource_or_scope)
stored_location_for(resource_or_scope) || super
end
# protected
# If you have extra params to permit, append them to the sanitizer.
# def configure_sign_in_params
# devise_parameter_sanitizer.permit(:sign_in, keys: [:attribute])
# end
end
views/devise/session/new.html.erb below:
<section class="form-auth text-center">
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<!-- <img class="mb-4" src="" alt="" width="72" height="72"> -->
<h1 class="h3 mb-3 font-weight-normal">Please Log In</h1>
<label for="inputEmail" class="sr-only">Email address</label>
<%= f.email_field :email, autofocus: true, class: "form-control", id: "inputEmail", placeholder: "Email address", autocomplete: "current-email", required: "" %>
<label for="inputPassword" class="sr-only">Password</label>
<%= f.password_field :password, autocomplete: "current-password", placeholder: "Password", class: "form-control", id: "inputPassword", required: "" %>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> Remember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2020</p>
<% end %>
<%= render "devise/shared/links" %>
</section>

Ruby on Rails Devise Confirmation Token is nil

I've got a User model (created by $ rails g devise User) and it is set to use confirmable (in the model and migration).
When a User is created the confirmation token is not being set (and the confirmation email is not being sent).
Here's app/models/user.rb:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :lockable, :timeoutable
def password_required?
super if confirmed?
end
def password_match?
self.errors[:password] << "can't be blank" if password.blank?
self.errors[:password_confirmation] << "can't be blank" if password_confirmation.blank?
self.errors[:password_confirmation] << "does not match password" if password != password_confirmation
password == password_confirmation && !password.blank?
end
# new function to set the password without knowing the current
# password used in our confirmation controller.
def attempt_set_password(params)
p = {}
p[:password] = params[:password]
p[:password_confirmation] = params[:password_confirmation]
update_attributes(p)
end
# new function to return whether a password has been set
def has_no_password?
self.encrypted_password.blank?
end
# Devise::Models:unless_confirmed` method doesn't exist in Devise 2.0.0 anymore.
# Instead you should use `pending_any_confirmation`.
def only_if_unconfirmed
pending_any_confirmation {yield}
end
protected
def confirmation_required?
false
end
end
Any ideas?
That's because you are overriding confirmation_required? to always return false.
Take a look at this
before_create :generate_confirmation_token, if: :confirmation_required?
The token is only generated if that method returns true.
The default behavior of confirmation_required? is to return true if the record hasn't been confirmed.
def confirmation_required?
!confirmed?
end
To complement #nbermudezs answer, this confirmation_required? method was added to devise in case you want to bypass confirmation for some users (eg users with special promo code, or whatever)
If you don't want to have any exceptions, I suggest you simply remove those lines of code or comment them, so you return to the default behavior of devise_confirmable which is the one you seem to want (and the one given by #nbermudezs)
# def confirmation_required?
# false
# end

rails 4, activeAdmin, Devise not saving reset_password_token for admin_user

I am using ActiveAdmin to create other admin members by supplying email, and having a block to send a password reset to the newly added email:
class AdminUser < ActiveRecord::Base
after_create { |admin| admin.send_reset_password_instructions }
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable,
:recoverable, :rememberable, :trackable, :validatable
def password_required?
new_record? ? false : super
end
end
However, I started getting a reset token invalid error, and on checking, discovered that the reset_password_token is not getting saved.
When I tried to debug, I traced the error to the method of the set_reset_password_token method of the Recoverable module ( recoverable.rb file ) of devise:
def set_reset_password_token
raw, enc = Devise.token_generator.generate(self.class, :reset_password_token)
self.reset_password_token = enc
self.reset_password_sent_at = Time.now.utc
self.save(validate: false)
raw
end
the token is getting generated, but when I checked self just before the self.save(validate: false) line, there was nothing attached to self.reset_password_token, it was nil.
To finally complicate it for me, when i now manually run the line self.reset_password_token = enc and self.reset_password_token actually now holds the token, after saving it, and checking the database, the reset_password_token of the newly saved AdminUser was still nil.
What could be going on here?
Note however: devise test suit on git shows that this should not be the case as shown below:
test 'should not clear reset password token for new user' do
user = new_user
assert_nil user.reset_password_token
user.send_reset_password_instructions
assert_present user.reset_password_token
user.save
assert_present user.reset_password_token
end

uncaught throw :warden with devise

When ever I goto a route that requires the user to be logged in I get an ArgumentError (uncaught throw :warden): in the server log.
Here is the controller code:
class TracksController < ApplicationController
include ActionController::Live
before_filter :authenticate_user!, except: [:index, :show]
before_filter :set_track, only: [:show, :edit, :update, :destroy, :queue]
before_filter :ensure_current_user_is_owner, only: :queue
def index
if params[:tag]
#tracks = Track.where(:is_private => false).order('created_at desc').tagged_with(params[:tag])
else
#tracks = Track.where(:is_private => false).order('created_at desc')
end
end
# Public View
def show
#approved_stems = #track.stems.where(:approved => true).order('created_at desc')
#comment = Comment.new
#comments = #track.comments.order("created_at desc")
end
# Private queue
def queue
#disapproved_stems = #track.stems.where(:approved => false).order('created_at desc')
end
def new
#track = current_user.tracks.new
#track.stems.build
end
def edit
#track = current_user.tracks.find(params[:id])
end
def create
#track = current_user.tracks.new(track_params)
respond_to do |format|
if #track.save
format.html { redirect_to #track, notice: "Track created."}
else
format.html { render action: 'new'}
end
end
end
def update
#track = current_user.tracks.find(params[:id])
respond_to do |format|
if #track.update(track_params)
format.html { redirect_to #track, notice: 'Track was successfully updated.' }
else
format.html { render action: 'edit' }
end
end
end
def destroy
#track = current_user.tracks.find(params[:id])
#track.destroy
respond_to do |format|
format.html {redirect_to tracks_url}
end
end
private
def set_track
#track = Track.find(params[:id])
end
def ensure_current_user_is_owner
if current_user != #track.user
redirect_to tracks_url, :alert => "You don't have permission!"
end
end
def track_params
# params[:track][:stems_attributes]['0'][:user_id] = current_user.id
# params[:track][:stems_attributes]['0'][:approved] = true
params.require(:track).permit(:tag_list, :cover_art, :title, :description, :bpm, :is_private, :stems_attributes => [:audio, :title, :user_id, :approved], :collabs_attributes =>[:email, :id, :_destroy])
end
end
Here's the complete server log:
Completed 500 Internal Server Error in 2ms
NoMethodError (undefined method `call' for nil:NilClass):
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-4.0.0/lib/action_controller/metal/live.rb:66:in `call_on_error'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-4.0.0/lib/action_controller/metal/live.rb:136:in `rescue in block in process'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-4.0.0/lib/action_controller/metal/live.rb:145:in `block in process'
ArgumentError (uncaught throw :warden):
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/warden-1.2.1/lib/warden/proxy.rb:128:in `throw'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/warden-1.2.1/lib/warden/proxy.rb:128:in `authenticate!'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/devise-3.0.0.rc/lib/devise/controllers/helpers.rb:48:in `authenticate_user!'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:427:in `_run__2832861654928389119__process_action__callbacks'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/activesupport-4.0.0/lib/active_support/callbacks.rb:80:in `run_callbacks'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-4.0.0/lib/abstract_controller/callbacks.rb:17:in `process_action'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-4.0.0/lib/action_controller/metal/rescue.rb:29:in `process_action'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-4.0.0/lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/activesupport-4.0.0/lib/active_support/notifications.rb:159:in `block in instrument'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/activesupport-4.0.0/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/activesupport-4.0.0/lib/active_support/notifications.rb:159:in `instrument'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-4.0.0/lib/action_controller/metal/instrumentation.rb:30:in `process_action'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-4.0.0/lib/action_controller/metal/params_wrapper.rb:245:in `process_action'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/activerecord-4.0.0/lib/active_record/railties/controller_runtime.rb:18:in `process_action'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-4.0.0/lib/abstract_controller/base.rb:136:in `process'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-4.0.0/lib/abstract_controller/rendering.rb:44:in `process'
/usr/local/rvm/gems/ruby-1.9.3-p392/gems/actionpack-4.0.0/lib/action_controller/metal/live.rb:132:in `block in process'
Any help would be appreciated, been stuck on this one for a while.
EDIT:
User model:
class User < ActiveRecord::Base
attr_accessor :login
mount_uploader :avatar, AvatarUploader
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :confirmable, :rememberable, :trackable, :validatable, :authentication_keys => [:login]
validate :sanitize_username, :on => :create
validates :username, uniqueness: true
validates :username, presence: true
has_many :tracks, :dependent => :destroy
def self.find_first_by_auth_conditions(warden_conditions)
conditions = warden_conditions.dup
if login = conditions.delete(:login)
where(conditions).where(["lower(username) = :value OR lower(email) = :value", { :value => login.downcase }]).first
else
where(conditions).first
end
end
private
def sanitize_username
self.username = username.downcase.gsub(" ", "")
end
def confirmation_required?
true
end
end
Devise:
# 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|
# ==> Mailer Configuration
# Configure the e-mail address which will be shown in Devise::Mailer,
# note that it will be overwritten if you use your own mailer class with default "from" parameter.
config.mailer_sender = "------------"
# Configure the class responsible to send e-mails.
# config.mailer = "Devise::Mailer"
# ==> ORM configuration
# Load and configure the ORM. Supports :active_record (default) and
# :mongoid (bson_ext recommended) by default. Other ORMs may be
# available as additional gems.
require 'devise/orm/active_record'
# ==> Configuration for any authentication mechanism
# Configure which keys are used when authenticating a user. The default is
# just :email. You can configure it to use [:username, :subdomain], so for
# authenticating a user, both parameters are required. Remember that those
# parameters are used only when authenticating and not when retrieving from
# session. If you need permissions, you should implement that in a before filter.
# You can also supply a hash where the value is a boolean determining whether
# or not authentication should be aborted when the value is not present.
# config.authentication_keys = [ :email ]
# Configure parameters from the request object used for authentication. Each entry
# given should be a request method and it will automatically be passed to the
# find_for_authentication method and considered in your model lookup. For instance,
# if you set :request_keys to [:subdomain], :subdomain will be used on authentication.
# The same considerations mentioned for authentication_keys also apply to request_keys.
# config.request_keys = []
# Configure which authentication keys should be case-insensitive.
# These keys will be downcased upon creating or modifying a user and when used
# to authenticate or find a user. Default is :email.
config.case_insensitive_keys = [ :email ]
# Configure which authentication keys should have whitespace stripped.
# These keys will have whitespace before and after removed upon creating or
# modifying a user and when used to authenticate or find a user. Default is :email.
config.strip_whitespace_keys = [ :email, :username ]
# Tell if authentication through request.params is enabled. True by default.
# It can be set to an array that will enable params authentication only for the
# given strategies, for example, `config.params_authenticatable = [:database]` will
# enable it only for database (email + password) authentication.
# config.params_authenticatable = true
# Tell if authentication through HTTP Auth is enabled. False by default.
# It can be set to an array that will enable http authentication only for the
# given strategies, for example, `config.http_authenticatable = [:token]` will
# enable it only for token authentication. The supported strategies are:
# :database = Support basic authentication with authentication key + password
# :token = Support basic authentication with token authentication key
# :token_options = Support token authentication with options as defined in
# http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html
# config.http_authenticatable = false
# If http headers should be returned for AJAX requests. True by default.
# config.http_authenticatable_on_xhr = true
# The realm used in Http Basic Authentication. "Application" by default.
# config.http_authentication_realm = "Application"
# It will change confirmation, password recovery and other workflows
# to behave the same regardless if the e-mail provided was right or wrong.
# Does not affect registerable.
# config.paranoid = true
# By default Devise will store the user in session. You can skip storage for
# :http_auth and :token_auth by adding those symbols to the array below.
# Notice that if you are skipping storage for all authentication paths, you
# may want to disable generating routes to Devise's sessions controller by
# passing :skip => :sessions to `devise_for` in your config/routes.rb
config.skip_session_storage = [:http_auth]
# ==> Configuration for :database_authenticatable
# For bcrypt, this is the cost for hashing the password and defaults to 10. If
# using other encryptors, it sets how many times you want the password re-encrypted.
#
# Limiting the stretches to just one in testing will increase the performance of
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
# a value less than 10 in other environments.
config.stretches = Rails.env.test? ? 1 : 10
# Setup a pepper to generate the encrypted password.
# config.pepper = "0db8498926b0e113b27106a661d47fcec43fcb3e9ed761e4b9fa8bd26fd5a97f5edd79362f2120364c4f0aa4dae321cc9ad1ab6219d3452c273dc3e35164362c"
# ==> Configuration for :confirmable
# A period that the user is allowed to access the website even without
# confirming his account. For instance, if set to 2.days, the user will be
# able to access the website for two days without confirming his account,
# access will be blocked just in the third day. Default is 0.days, meaning
# the user cannot access the website without confirming his account.
config.allow_unconfirmed_access_for = 0.days
# A period that the user is allowed to confirm their account before their
# token becomes invalid. For example, if set to 3.days, the user can confirm
# their account within 3 days after the mail was sent, but on the fourth day
# their account can't be confirmed with the token any more.
# Default is nil, meaning there is no restriction on how long a user can take
# before confirming their account.
# config.confirm_within = 3.days
# If true, requires any email changes to be confirmed (exactly the same way as
# initial account confirmation) to be applied. Requires additional unconfirmed_email
# db field (see migrations). Until confirmed new email is stored in
# unconfirmed email column, and copied to email column on successful confirmation.
# config.reconfirmable = false
# Defines which key will be used when confirming an account
# config.confirmation_keys = [ :email ]
# ==> Configuration for :rememberable
# The time the user will be remembered without asking for credentials again.
# config.remember_for = 2.weeks
# If true, extends the user's remember period when remembered via cookie.
# config.extend_remember_period = false
# Options to be passed to the created cookie. For instance, you can set
# :secure => true in order to force SSL only cookies.
# config.rememberable_options = {}
# ==> Configuration for :validatable
# Range for password length. Default is 8..128.
config.password_length = 8..128
# Email regex used to validate email formats. It simply asserts that
# one (and only one) # exists in the given string. This is mainly
# to give user feedback and not to assert the e-mail validity.
# config.email_regexp = /\A[^#]+#[^#]+\z/
# ==> Configuration for :timeoutable
# The time you want to timeout the user session without activity. After this
# time the user will be asked for credentials again. Default is 30 minutes.
# config.timeout_in = 30.minutes
# If true, expires auth token on session timeout.
# config.expire_auth_token_on_timeout = false
# ==> Configuration for :lockable
# Defines which strategy will be used to lock an account.
# :failed_attempts = Locks an account after a number of failed attempts to sign in.
# :none = No lock strategy. You should handle locking by yourself.
# config.lock_strategy = :failed_attempts
# Defines which key will be used when locking and unlocking an account
# config.unlock_keys = [ :email ]
# Defines which strategy will be used to unlock an account.
# :email = Sends an unlock link to the user email
# :time = Re-enables login after a certain amount of time (see :unlock_in below)
# :both = Enables both strategies
# :none = No unlock strategy. You should handle unlocking by yourself.
# config.unlock_strategy = :both
# Number of authentication tries before locking an account if lock_strategy
# is failed attempts.
# config.maximum_attempts = 20
# Time interval to unlock the account if :time is enabled as unlock_strategy.
# config.unlock_in = 1.hour
# ==> Configuration for :recoverable
#
# Defines which key will be used when recovering the password for an account
# config.reset_password_keys = [ :email ]
# Time interval you can reset your password with a reset password key.
# Don't put a too small interval or your users won't have the time to
# change their passwords.
config.reset_password_within = 6.hours
# ==> Configuration for :encryptable
# Allow you to use another encryption algorithm besides bcrypt (default). You can use
# :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1,
# :authlogic_sha512 (then you should set stretches above to 20 for default behavior)
# and :restful_authentication_sha1 (then you should set stretches to 10, and copy
# REST_AUTH_SITE_KEY to pepper).
#
# Require the `devise-encryptable` gem when using anything other than bcrypt
# config.encryptor = :sha512
# ==> Configuration for :token_authenticatable
# Defines name of the authentication token params key
# config.token_authentication_key = :auth_token
# ==> Scopes configuration
# Turn scoped views on. Before rendering "sessions/new", it will first check for
# "users/sessions/new". It's turned off by default because it's slower if you
# are using only default views.
# config.scoped_views = false
# Configure the default scope given to Warden. By default it's the first
# devise role declared in your routes (usually :user).
# config.default_scope = :user
# Set this configuration to false if you want /users/sign_out to sign out
# only the current scope. By default, Devise signs out all scopes.
# config.sign_out_all_scopes = true
# ==> Navigation configuration
# Lists the formats that should be treated as navigational. Formats like
# :html, should redirect to the sign in page when the user does not have
# access, but formats like :xml or :json, should return 401.
#
# If you have any extra navigational formats, like :iphone or :mobile, you
# should add them to the navigational formats lists.
#
# The "*/*" below is required to match Internet Explorer requests.
# config.navigational_formats = ["*/*", :html]
# The default HTTP method used to sign out a resource. Default is :delete.
config.sign_out_via = :delete
# ==> OmniAuth
# Add a new OmniAuth provider. Check the wiki for more information on setting
# up on your models and hooks.
# config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo'
# ==> Warden configuration
# If you want to use other strategies, that are not supported by Devise, or
# change the failure app, you can configure them inside the config.warden block.
#
# config.warden do |manager|
# manager.intercept_401 = false
# manager.default_strategies(:scope => :user).unshift :some_external_strategy
# end
# ==> Mountable engine configurations
# When using Devise inside an engine, let's call it `MyEngine`, and this engine
# is mountable, there are some extra configurations to be taken into account.
# The following options are available, assuming the engine is mounted as:
#
# mount MyEngine, at: "/my_engine"
#
# The router that invoked `devise_for`, in the example above, would be:
# config.router_name = :my_engine
#
# When using omniauth, Devise cannot automatically set Omniauth path,
# so you need to do it manually. For the users scope, it would be:
# config.omniauth_path_prefix = "/my_engine/users/auth"
end
The way I have handled it:
1. Authenticated routes rather than controllers:
Liveexample::Application.routes.draw do
devise_for :users
authenticate :user do
resource :dashboard, controller: :dashboard, only: [:show] do
get 'events', on: :member
end
root to: "dashboard#show", as: "root"
end
end
authenticate directive will force Devise authentication.
Also, notice as: "root" addendum, which is required for Rails 4 routing to get unique names
2. Changed JavaScripts to be only loaded for their namesake's controllers:
application.js
//= require jquery
//= require jquery_ujs
Notice absence of //= require tree .
application.html.haml
= javascript_include_tag "application", controller_name unless controller_name == "sessions"
Here = javascript_include_tag "application" line has been replaced with = javascript_include_tag "application", controller_name. unless condition is needed to skip loading attempt of non-existing session.js file for Devise's session controller.
3. Changed environment-specific configuration files to enable serving static assets, e.g.
production.rb
config.serve_static_assets = true
config.assets.compile = true
Hope it may help.
This is a duplicate of SO11152671. I've pasted a full answer there. In short, you'll need to add includes for the Devise test helper and the Warden test helper both in the actual ControllerTest class and not in test_helper.rb.

Devise - remember me not working? LocalHost Issue?

I'm using devise with my rails 3 app. For some reason the sign in with Remember Me is not working.
Could this be due to testing on localhost:3000 ?
in devise.rb, I have the following set:
config.remember_for = 2.weeks
In the logs, when I post a signin I see:
Started POST "/users/sign_in" for 127.0.0.1 at Thu May 12 20:53:04 -0700 2011
Processing by SessionsController#create as HTML
Parameters: {"signIn"=>"LOG IN", "authenticity_token"=>"GR09TIq4uSbu6UWxDRhpfQeLWp7qtJTxkCFksLmFzdE=", "utf8"=>"✓", "user"=>{"remember_me"=>"on", "password"=>"[FILTERED]", "email"=>"xxxx#xxxxxxx-inc.com"}}
Is there anything wrong there?
I also have the following in my sessions_controller.rb
class SessionsController < Devise::SessionsController
prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
include Devise::Controllers::InternalHelpers
# GET /resource/sign_in
def new
clean_up_passwords(build_resource)
render_with_scope :new
end
# POST /resource/sign_in
def create
resource = warden.authenticate!(:scope => resource_name, :recall => "new")
#set_flash_message :notice, :signed_in
sign_in_and_redirect(resource_name, resource)
end
# GET /resource/sign_out
def destroy
#set_flash_message :notice, :signed_out if signed_in?(resource_name)
sign_out_and_redirect(resource_name)
end
protected
def after_sign_in_path_for(resource)
if resource.is_a?(User) && resource.banned?
sign_out resource
flash[:error] = "This account has been suspended."
root_path
else
super
end
end
end
Any ideas why signing in and remembering is not working? Thanks
This happens because remember_me comes in params as "on", but is compared to Devise::TRUE_VALUES, which are [true, 1, '1', 't', 'T', 'true', 'TRUE'].
The easiest way is to make it work is to insure your remember_me comes as one of that values. Example of check-box(notice value="1"):
<input type="checkbox" name="user[remember_me]" value="1" checked="checked" />
Another way if you want to make it work with "on" value you can add "on" to Devise::TRUE_VALUES.
So in your config/initializers/devise.rb just add as the first line:
Devise::TRUE_VALUES << ["on"]
The Devise remember_user_token cookie could be set to 'secure only', in which case it doesn't work with the development rails server on http (browser never sends it back to the server).
Check initializers/devise.rb for rememberable_options = {:secure => true}
Do you have the sessions set aswell with config.timeout_in = 10.minutes?
If so see this contribution on stackoverflow which solves it solution
My problem with this was this single line in User.rb (I updated from Michael Hartl login mechanism to devise)
before_save :create_remember_token
I commented it out and it worked.
I also have :
User.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,:token_authenticatable,
:recoverable, :rememberable, :trackable, :validatable
On devise.rb, I only added Devise::TRUE_VALUES << ["on"] and uncommented config.remember_for = 2.weeks

Resources