I know that forcing passwords to expire after a certain period from the moment the user creates it is not part of the Devise logic, and I plan to write my own code for this to happen.
In practice, security studies have shown this to be a bad idea. This is because you reduce the return on each change. That is, the password starts strong, and then becomes weaker over time, as the user tries to execute the policy. See Peter Gutmann Engineering Security and Chapter 7, Passwords.
From the book, other stupid things include complexity requirements. (Before objecting, read the relevant section of the book).
... create something like a user_passwords table and use the logic in my code to make sure that the new password does not match any one in this table for this user.
And as soon as you read the chapter, I can ask: why did you allow the user to choose a weak / wounded / broken password in the first place? These 60 KB Bloom filters look very useful when combined with Mark Brunett containing 10 million missing passwords :)
Password Reuse Prevention ...
Reuse that could damage - reuse of passwords on sites. Brown, Bracken, Zokkoli, and Douglas state that numbers make up about 70% in Password Generation and Storage (Applied Cognitive Psychology, Volume 18, Issue 6, pp. 641-651). And Das, Bonno, Caesar, Borisov, and Van all report about 45% in The Tangled Web of Password Reuse . Note that the Tangled Web study was supposed to crack passwords, so the number is probably higher because they could not recover all the passwords.
To make reuse a more acute problem, users need to remember passwords for about 25 different sites according to Das, Bonneau, Caesar, Borisov and Wang in The Tangled Reuse of Web Password .
I even burned out with this a few years ago. I used the same password for two low value accounts. Then, GNU Savannah was hacked, and attackers were able to use the recovered password to violate an under-used email account.
Now I just create a long random string when I need credentials. I donβt even bother them for most sites. When I need to access the site again, I just take the recovery process.