We have an issue with CSRF tokens that started when moving our sessions to Redis. The issue is that users sign-out, and leave the login screen for a long time, e.g. overnight. Then, in the morning, the first login attempt always fails as the form CSRF token is not valid anymore as the redis session was deleted from the server (TTL).
I searched online for a few hours, but not sure what's the right way to go. Adding this file solves the issue:
class SessionsController < Devise::SessionsController
skip_before_filter :require_no_authentication, only: [:new]
end
but from what I read online, this is a security risk. I kept searching, and saw few alternatives:
If I understood the security risk correctly, I don't see how any of those solution solves the security issue. I mean, from what I read the risk of unprotected login API is that an attacker can trick someone else into signing in to the attacker profile and enter private data, which will then be available to the attacker. So, with any of those solutions, the attacker could mimic the same behavior and hack himself in, right?
What's the most secure way to fix this issue?
I fixed it by adding a API to get a new token and using it if the login form was open for a long time. Code:
app/controllers/my_controller.rb:
def token
render json: { token: form_authenticity_token }, status: :ok
end
signin.html:
$('form#login').submit(function(e) {
var that = this;
e.preventDefault();
// assuming the session TTL is 30 min
if (new Date() - window.loginPageRenderedAt > 1800000) {
$.get('token', function(data) {
var token = data.token;
$('input[name=authenticity_token]').val(token)
that.submit();
}).fail(function() {
that.submit();
})
} else {
this.submit();
}
}