Often times, when people think of doing password recovery, their immediate instinct is to store a unique token in the database, and to use that as an identifying piece of information.
The following example shows the entire sketch of doing password recovery with Cuba and Nobi, without going into the nitty gritty details of validation, error handling, and good UX messages (all of which are left as an exercise for the reader)
Usermodel with a
fetchmethod that retrieves via email, and also a
Usermethod which fetches by ID.
on "forgot-password" do on get do render("forgot-password") end on post do user = User.fetch(req[:email]) on user do nobi = Nobi::TimestampSigner.new('my secret here') signature = nobi.sign(String(user.id)) # Send an email here containing the token puts "Go to http://localhost:9393/otp/%s" % signature res.redirect "/login/?recovery=true", 303 end on default do session[:error] = "Can't find a user with that email." res.redirect("/forgot-password", 303) end end on "otp/:signature" do |signature| nobi = Nobi::TimestampSigner.new('my secret here') # Let's unsign it, and specify that we want tokens to live # for only 2 hours user = begin user_id = nobi.unsign(signature, max_age: 7200) User[user_id] rescue Nobi::BadData end on user do on get do render("otp", user: user) end on post, param(:password), param(:password_confirmation) do |pass1, pass2| # You probably need to do some validation here, left # as an exercise for the reader :-p user.update(password: pass1) res.redirect "/", 303 end end on default do session[:error] = "Invalid signature found" res.redirect("/forgot-password") end end end
So that’s basically it, we’re relying on the heavy lifting of Nobi to deal with signature verification – and therefore the needless task of storing the token in the database.