ActionController::InvalidAuthenticityToken on updating the password - ruby-on-rails

I have a Ruby On Rails application. Now, I started getting ActionController::InvalidAuthenticityToken error while updating password in admin_controller.
CSRF token is present in layout.
Earlier it was working, today when I get a warning from google to change password, I tried to update the password & got this error.
Below is the request:
Started PATCH "/admin/password/change" for 127.0.0.1 at 2020-07-25 22:05:38 +0530
Processing by Admin::PasswordsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"osXhNhqJZ9qXeJ4F2BXrJvOTflrG5G3MGPl7yuOa4Y8PoqIXKEVe17bqO5u9nGYG2Bn0Zun2U9mOR4/uxNajsg==", "current_password"=>"[FILTERED]", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}
I am using devise-4.3 for authentication.
If tried to update the password 3-4 time, then it works but not each time.
I believe I should refresh the token, turbolinks might be creating an issue.
Every other post/patch request is working.
Ruby-2.4.0, Rails-5.1.4

Go to the controller that’s generating the error, and paste following line of code above all the defined functions:
skip_before_filter :verify_authenticity_token, :only => :create
OR
protect_from_forgery with: :null_session
save it then restart the server!
Let me know if this works for you!

Need to Hard reload the page/disable turbolinks, so I added the following in link_to
<%= link_to 'Change Password', change_admin_password_path, data: { turbolinks: false }) %>
Now the complete page reload is happening and I am able to update the password.

Related

Logging out returns Can't verify CSRF token authenticity

I am able to login and logout most of the time, but sometimes during logging out I am returned with this error as stated below and I am not logged out.
Can't verify CSRF token authenticity.
User excluded error: #<ActionController::InvalidAuthenticityToken: ActionController::InvalidAuthenticityToken>
It doesn't happen always that I am not able to logout but when I am not able to logout above is the error which I get. I read about it this is what I have done so far. I am using vuejs on my front end and rails on the backend. I am using rails version 5.1.
application_controller.rb
protect_from_forgery with: :exception
application.html.erb
<%= csrf_meta_tags %>
this is the axios request I am making to logout the user
index.vue
logout() {
this.$axios.delete('/users/sign_out').then(function(response) {
console.log("Logged out")
});
}
Please help me resolve this issue
You may need to add the csrf_meta_tags to the request
In your case, the csrf_meta_tags in application.html.erb is not re-rendered.

Rails 3.2 error overriding devise for email only signup

I have been trying to follow https://github.com/plataformatec/devise/wiki/How-To:-Override-confirmations-so-users-can-pick-their-own-passwords-as-part-of-confirmation-activation in order to allow users on my app to supply only an email address when they sign up, and then be prompted for the remainder of their information after they confirm their email. But the approach seems to be slightly broken or I don't fully understand it.
In the instructions, in the confirmations_controller there is this method:
def with_unconfirmed_confirmable
original_token = params[:confirmation_token]
confirmation_token = Devise.token_generator.digest(User, :confirmation_token, original_token)
#confirmable = User.find_or_initialize_with_error_by(:confirmation_token, confirmation_token)
if !#confirmable.new_record?
#confirmable.only_if_unconfirmed {yield}
end
end
If I leave it as is, I always get a "Confirmation Token is Invalid" error. It appears to be due to the new token being generated and not found. You can see what I mean in the log:
Started GET "/users/confirmation?confirmation_token=9835abdff3d03d0a29e1c5a640c6a22f1ed6289b4cf696ed514ba183aad49caa" for 127.0.0.1 at 2013-11-12 07:39:42 -0700
Processing by ConfirmationsController#show as HTML
Parameters: {"confirmation_token"=>"9835abdff3d03d0a29e1c5a640c6a22f1ed6289b4cf696ed514ba183aad49caa"}
ESC[1mESC[36mUser Load (0.3ms)ESC[0m ESC[1mSELECT "users".* FROM "users" WHERE "users"."confirmation_token" = '98e17d2ea3cc3fcba5cab7d37bd9a865fc2e318372cb293b541b8a05b46f
e4a3' LIMIT 1ESC[0m
But if I change the method to use the original_token instead of the generated confirmation_token, it all works. What am I missing? Should I be worried about not using the derived token?
Turns out the error was because my app was on an older version of devise that inadvertently got upgraded to devise 3.1. Thanks to this post: Upgrading to devise 3.1 => getting Reset password token is invalid
I updated the mailer to send the correct token and now all is working.

Devise warden 401 Unauthorized when wrong credentials

I have a quite standard Devise login procedure with:
View:
resource_name, :url => session_path(resource_name)) do |f| %>
<%= f.input :password, input_html: {class: "span6"} %>
<% if devise_mapping.rememberable? -%>
<p><%= f.check_box :remember_me %> Remember me</p>
<% end -%>
<input type="hidden" name="after_sign_in_page" value="<%=#after_sign_in_page%>">
<p><%= f.submit "Sign in", class: "btn btn-success" %></p>
And I just created a sessioncontroller to downcase the email:
class SessionsController < Devise::SessionsController
def create
params[:user][:email].downcase!
super
logger.debug "Errors: #{resource.errors}"
end
A login with good credentials happens fine.
With wrong credentials, It redirects to the sign-in page with this log:
Started POST "/users/sign_in" for 127.0.0.1 at 2013-01-10 09:59:44 +0100
Processing by SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"8eytQkr20JOOOdDvpCWakbmUzNoaHMxK9/BSEVxETik=", "user"=>{"email"=>"nicolas#demoreau.be", "password"=>"[FILTERED]", "remember_me"=>"0"}, "after_sign_in_page"=>"", "commit"=>"Sign in"}
Time zone: (GMT+00:00) UTC, current area: , user to register: , current controller: sessions
Completed 401 Unauthorized in 69ms
Processing by SessionsController#new as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"8eytQkr20JOOOdDvpCWakbmUzNoaHMxK9/BSEVxETik=", "user"=>{"email"=>"nicolas#demoreau.be", "password"=>"[FILTERED]", "remember_me"=>"0"}, "after_sign_in_page"=>"", "commit"=>"Sign in"}
Rendered devise/sessions/_new.html.erb (17.8ms)
Rendered devise/sessions/new.html.erb within layouts/application (19.7ms)
Rendered layouts/_header.html.erb (66.1ms)
Completed 200 OK in 173ms (Views: 98.3ms | ActiveRecord: 0.9ms)
Apparently the 401 is dropped by Warden but I couldn't figure out why.
The user is correctly redirected back to the login page but there is no error message displayed (which is normal as they are wiped out by the redirect)
What am I doing wrong?
thanks!
EDIT 1:
For now, I found a quick hack. I added this in SessionsController#new
if params[:user]
flash[:alert] = "Incorrect login or password"
end
Not very elegant but at least, I have something.
First of all, let me advice you against overriding Devise controllers:
In this case, Devise takes care of transforming the email to lower
case for you, so there's really no need to overwrite the create method.
Your app will support Devise updates seamlessly if you stick to the
standard.
Also, Devise should set a flash error automatically, make sure you're displaying it in your view.
The status code 401 is just a standard response for unauthorized requests.
401 Unauthorized is similar to 403 Forbidden, but specifically for use
when authentication is required and has failed or has not yet been
provided
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
You should definitely consider dropping your custom controller,
Cheers
Your flash message is not going to be set because Devise::SessionsController#create calls warden for the authentication which, in case of failures, will call Devise::FailureApp. Your controller never handles the failure scenarios.
If you want a custom message, you can customize the failure app for that, there are some articles in the Devise wiki explaining how to do so.
But in general, you can customize your failure messages via I18n and there is probably a better way to achieve what you want without a need to override Devise controllers.
I agree with jassa, just update your Devise version (with bundle update devise).
Case insensitive emails are already present in Devise, just make sure you have this config:
# devise.rb
Devise.setup do |config|
config.case_insensitive_keys = [:email ]
end
In any case, since you seem to be missing some flash messages and this config, perhaps it would better if you just re-ran the generator:
rails generate devise:install
You should then let Devise overwrite some files, just make sure you backup yours first.

Devise with mobile mime type, 401 only displays flash message

I have a Rail 3.2.2 app with Devise 2.0 that I've begun to incorporate mobile views with. I'm using a before_filter in my application_controller.rb to use the mobile layout as follows:
before_filter :adjust_format_for_mobile
private
def adjust_format_for_mobile
if request.env["HTTP_USER_AGENT"] && request.env["HTTP_USER_AGENT"][/(iPhone|iPod)/]
request.format = :mobile
end
end
I have the mime type defined in initializers/mime_types:
Mime::Type.register_alias "text/html", :mobile
Whenever I attempt to access the root_path as defined in routes.rb:
root :to => "wells#index"
(which is protected via before_filter :authenticate_user!)
All that is rendered is the Devise flash message (no HTML whatsoever):
You need to sign in or sign up before continuing
I have the necessary mobile layout, what am I missing here? The behavior on the desktop version is that you're redirected to the new_user_session_path, why is that not the case here?
EDIT:
The console log is as follows:
Started GET "/" for 127.0.0.1 at 2012-03-21 17:07:35 -0500
Processing by WellsController#index as HTML
Completed 401 Unauthorized in 0ms
Additionally, this only occurs with that particular path (the root path). If I manually go to users/sign_up or users/sign_in it works perfect. I can then log in and everything works fine.
Found a wiki on the process:
How To: Make Devise work with other formats like mobile, iphone and ipad (Rails specific)

rails 3.1.0 devise with cancan getting unauthorized with invalid username and/or password

I have a fairly simple app using devise and cancan for authentication and authorization. Everything works great except when users try signing in with invalid usernames and/or passwords. When this happens, we get an error loading page with the following exception in the logs:
Started POST "/users/sign_in" for 127.0.0.1 at 2012-02-09 22:23:22 -0600
Processing by Devise::SessionsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"blahblahblahblah", "user"=>{"login"=>"asdasd", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Sign in"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE (lower(username) = 'asdasd' OR lower(email) = 'asdasd') LIMIT 1
Completed 401 Unauthorized in 74ms
I'm not sure what I need to set to allow the authorization and/or how to get more detailed logs to see exactly what is not authorized? If I enter valid credentials I can access the application and all other pieces of the app work as expected.
I know this question has been posted a couple months ago but I hot the same issue, and after fighting it for a few hours, overwriting Devise SessionController, Devise Custom Failure, debugging through, etc.., I finally found out what was going on and I decided to share the solution so you guys won't have to go through that.
The error 'Completed 401 Unauthorized in XXms' happens within the create method of SessionController at the line:
resource = build_resource(...)
And the resource cannot be built since the resource is not passed to the server. Now the problem resides in WHY the resource isn't passed to the server? I'm using JQUERY mobile which post the sign_in as an AJAX call, which JQUERY cannot upload data like that through AJAX.
You need to add to your signin form the data-ajax=false:
in Devise/sessions/new.html.erb modify the form to look like this:
form_for(resource, :as => resource_name, :url => user_session_url, html: {data: {ajax: false}}) do |f|
Hope that helps someone down the road.

Resources