Devise: Lockable Failed Attempts Never Expire

Created on 24 Oct 2017  路  6Comments  路  Source: heartcombo/devise

I've been asked to modify our login procedure so that failed attempts eventually expire. For example, we have the lockout strategy set for 3 failed attempts, and the unlock strategy for both 1hr or e-mail.

But the use-case we have is that people are putting in two failed attempts, giving up, trying again the next day, and failing: bam, that's their third attempt and they're immediately locked out. Even though more time than the unlock strategy has past.

I'd like to add an optional last_attempt_at datetime field to the user model, and when checking for failed attempts, if the config.unlock_strategy is set to time or both AND the last_attempt_at was more than the config.unlock_in time, it should reset the failed_attempts before continuing.

Is this change desirable? Does it seem like a good idea? Or shall I go back to shoe-horning the behaviour in my own app?

Most helpful comment

Actually, I built it and we've been using it internally for eight months.

https://github.com/LenPayne/devise/commit/3558dbb60e72323fd677bc4f764c199b986a4786

This was originally forked off of 3-stable.

All 6 comments

@LenPayne I understand your use case, you actually need a different behavior.
You want to unlock the account with the time before it was locked by the maximum failed attempts.
Since this seems like a really specific requirement, I don't think we should support it for now.
While I know it's not ideal, I think the best path for you now is to implement this in your app.

I hope you get my point. Thank you!

I also need an expiring failed attempt counter. Failed attempt tracking seems pretty useless without a counter expiry.

Imagine a regular user who makes a typo signing in about once a month. If you allow a maximum of 6 failed sign-in attempts attempts, after 6 months they will be locked out for no real reason and the user will be very confused.

The point of a locking mechanism like this is to prevent an unauthorized person from brute forcing their way into someone else's account, not to punish a user for occasional typos.

A quick fix that doesn't require any changes to Devise code is a cron job that runs at a specified time interval that decrements the failed attempts counter by 1, until reaching 0. For example, if you want to lock the account after 6 failed sign-in attempts within 1 hour, you can decrement the count by 1 every 10 minutes.

Actually, I built it and we've been using it internally for eight months.

https://github.com/LenPayne/devise/commit/3558dbb60e72323fd677bc4f764c199b986a4786

This was originally forked off of 3-stable.

@LenPayne do you have any plans adding a PR with that change to upstream Devise?

This would be nice to have in Devise. As it is now, the current behaviour is very confusing for most users. Are there any plans to add this in? Or at the very least, have the sign in attempts reset upon logging in?

We're still using it in production. Based on my comment above, looks like we turned it on Jan 2018 or so. I have an updated fork from 4.5.0: https://github.com/LenPayne/devise/tree/expire_failed_4.5.0

As the initial idea was shot down, I've never reopened the issue or PR, but it works and has done the job.

The individual commit can be dropped on top of most current branches: https://github.com/LenPayne/devise/commit/16eefb099176e1fe049525058de5a7d037b4b38c

Was this page helpful?
0 / 5 - 0 ratings