Guide to implementing spring security password recovery with dynamic URL sent to email

19,879

Solution 1

The problem doesn't really have much to do with Spring Security. Provided you know the structure of the user database and the password encoder used, it's really just implementing a workflow involving data access, web controllers and sending an email. The link should contain a random token string (use SecureRandom and a base64 encoder, for example) and it should be stored in a database with the userId and a timestamp (for validating the window within which the link is valid). The controller would simply extract the token from the incoming request, load the data from the database using the token. It would check the timestamp and then forward the user to a password entry form. Depending on requirements, you might also want them to answer some other security questions too. You'd then validate and encode the password and store it in the account matching the userId stored in the reset link table. It would also make sense to have a batch job running to remove expired links from the database.

The Grails Spring Security UI plugin already has a forgot password option which you can either use directly or use as a reference.

Solution 2

I have implemented a JAVA project for this use case. It is on GitHub, open source.

There are explanation for everything (and if something is missing - let me know...)


Have a look: https://github.com/OhadR/Authentication-Flows

This is the client web-app that uses the auth-flows, with the README with all explanations. it directs you the implementation: https://github.com/OhadR/oAuth2-sample/tree/master/authentication-flows

Share:
19,879
Aubergine
Author by

Aubergine

Spring; Spring Boot; Java; Kotlin; Couchbase; Reactor; WebFlux

Updated on June 13, 2022

Comments

  • Aubergine
    Aubergine almost 2 years

    I found it very difficult to do password recovery, since I've never done it before.

    So far I have web app which has:

    Spring Security, where password is properly hashed and user roles implemented and work correctly.

    The strategy hints research from stackoverflow:

    1. User hits forgot-password button, where he enters his email address.
    2. Dynamic link is sent to email address
    3. User opens link in email address
    4. Which redirects him to password reset page

    What is not known:

    • How to give link dynamic nature - methods of generations
    • Link has a timeout - some questions were found here, but often involve custom handler or extension to spring security functionality
    • A request mapping methods to respond to such dynamic link
    • Temporary link storage methods - database, session etc. ?

    As you can see the list is quite severe for a single question. So was hoping you might be able to provide guide resources to how to do it step by step. I was a little surprised I could not find much on this in Spring Security documentation. Thanks.

    I am student so don't know really industry best practices for doing so especially in the context of Java, so I really hope anyone will be able to help.

  • Aubergine
    Aubergine almost 11 years
    great, simple and concise. I believe emailadress+timestamp(as salt) hash generation would do the job for link generation? Also just for quick reference to respond to dynamic link I use something like: @RequestMapping(value="/var/{name}", method = RequestMethod.GET)
  • Shaun the Sheep
    Shaun the Sheep almost 11 years
    Why use a hash? You would still need to store the token anyway in order to verify it and timestamps are guessable. If I knew someone had requested a reset and knew their email, I could just iterate through all the possible timestamps over a suitable window until the system let me in. Use random bytes for the link token, and make it long enough that you don't have to worry about it (e.g. 16 bytes).
  • Kafkaesque
    Kafkaesque over 10 years
    Is this stable enough to adapt for production use?
  • OhadR
    OhadR over 10 years
    I've implemented something similar to Luke's description, only without using the DB; instead, I use encryption to encrypt the data in the link, so I do not have to access the DB. If you are interested, have a look in my answer here, and find there all relevant links
  • OhadR
    OhadR over 10 years
    it is a good question. In short: YES. Note that for production, each one (usually) has its own needs. for example, there are companies who needs "secret question" mechanism, which i did not implement. but it is a very good basis to start from, and to add whatever needed. have a look in the README. let me know if something is not clear. and yes - it is stable :-) NOTE: I've changed the links in my answer. have a look..
  • Khanh Luong Van
    Khanh Luong Van about 7 years
    Hi @OhadR: I'm referring to your project, it useful for me, I received an exception: AuthenticationFlowsProcessorImpl - Authentication failed; nested exception is javax.mail.AuthenticationFailedException, UserActionController - Account is locked or does not exist, I checked and user data has inserted in db
  • OhadR
    OhadR about 7 years
    @KhanhLuongVan I think you should open a new "question" here in stack overflow with all the details. it will be better to trace and answer, and might help other poeple... please do not forget to tag your question with "authentication-flows"...
  • Khanh Luong Van
    Khanh Luong Van about 7 years
    Thanks @OhadR: I have created new question and have some issue and hope you support: this is my ticket: stackoverflow.com/questions/43067900/…