I am porting my data from old system to a new system written in ruby on rails. To get the older users registered I am planning to transfer their old data into new system but I can't transfer their old password so I'm planning to create a random password and then a password reset link and send them a custom email inviting them to my new system.
Devise provides this:
user.send_reset_password_instructions
But this sends a "forgot password" email to user. I just want to get the forgot password url somehow so that I can use that url in my own mail and send it at some later time. I've tried looking up but everywhere they talk about "send_reset_password_instructions" function. Any idea how I can do this?
The reset password url was formed by reset_password_token in User model.
So saving the reset_password_token is enough to recover reset password url later on.
reset_password_token = 'XYZ' # Example token
reset_password_url = Rails.application.routes.url_helpers.edit_user_password_path(reset_password_token: reset_password_token)
Due to security (an attacker could read the link from the database to bypass email verification), what Devise stores in user.reset_password_token is only a digest of the token that is sent into the password reset link.
Specifically, in the set_reset_password_token method, the encoded token is saved to the database, while the raw token is returned and then sent in the password reset email.
What you can do is to reset the token yourself and save the raw token somewhere to be used later:
raw = user.send(:set_reset_password_token)
It's also worth noting that you can customize the devise mailer and provide your own templates. However, in this case, it would also affect the legitimate password reset emails.
Related
I am trying to implement a reset password flow with devise token auth gem: https://github.com/lynndylanhurley/devise_token_auth
The end client will be a mobile device (e.g. iOS, Android). I am uncertain as to how the native clients will be able to catch the url to reset password and display a password form through deep linking. Here are the general steps as I understand them:
Fire a POST to auth/password with an email and redirect_url
This will send an email with a link to reset the password and an included reset_password_token query param.
Clicking on the link fires a GET to auth/password/edit
This GET then fires a http 302 redirect to the redirect_url sent in the first request with the reset_password_token in the query params. The redirect_url should route to the form intended to display a password field to reset a user's password. On mobile clients, ideally this would be handled as a deep link.
I am confused as to how the mobile apps will handle step 4. I heard it's difficult to deep link in a native app through a 302 redirect/may not be possible. Is there a part of the flow I am misunderstanding perhaps? I'd appreciate any clarity on how I can implement this flow successfully for mobile clients.
For reference here is the guide I am following from the official docs: https://devise-token-auth.gitbook.io/devise-token-auth/usage/reset_password
My app has been using devise (3.1.0, 3.0.3, 3.0.2, 3.0.1, 3.0.0, 2.2.4), so the current version is 3.1.0. With this upgrade there is a new way Devise does token confirmation (blog).
When I click on the email link it leads to an invalid token error, so I'm trying to find out how to resolve this. Please let me know any pointers you have. Thank you.
With 3.1.0, Devise has changed the way it handles token authentication. Rather than storing an unencrypted token in the database, Devise now encrypts that token and sends the unencrypted token in the confirmation email. You will need to set config.secret_key in order to facilitate this encryption. More info on that here: Devise Secret Key was not set
Thus, if you have an old email, or an old token in the database, it is not likely to match what you expect. You can set
config.allow_insecure_token_lookup = true
in your Devise initializer file to remedy this problem, but this is supposed to be a short-term solution while you wait for users to click on the confirmation emails that you sent out before the switch.
Lastly, if you've changed the mail message to reference the token directly (e.g. #user.reset_password_token), you are using the encrypted version in the email and will need to change it to reference the #token variable defined by Devise instead. Here's an example email: https://github.com/plataformatec/devise/blob/2a8d0f9beeb31cd2287094c5dcf843d0bd069eb8/app/views/devise/mailer/reset_password_instructions.html.erb#L5
authenticate_or_request_with_http_basic do |user, password|
user == USER && password == PASSWORD
end
The above code asks for a username and password in a regular fashion (using basic_http_auth)
My idea was to create a user login page , some how check the username & password to be valid and then authenticate him.
Now authenticate him means to create a header that would have been sent by browser if he was actually authenticated via basic_http_auth . i.e to set the simple http auth credentials
The requirement is so because there is another non ruby app that would run on the same domain internally & would check if the user is authenticated via simple_http_auth.
The over all picture would be something like this :
Rails app : authenticates user.
The second non ruby app just checks if the user is authenticated since its under the same domin it can simply access the user_name password send via http_basic auth.
The other idea is to run a rails api service that would determine if the user is logged in or not , and call it via the second app. But I don't prefer doing that.
Hi Gaurav you should try to set your default username and password values with default http setting in "config/initializers " folder inside setup_mail.rb file
I'm creating a password_reset feature in rails the same way I did it when I used codeigniter.
For a user to reset their password, they type in their email address and click a button. The token is generated and stored in the database, and an email is sent to their email address with a URL containing that token.
When user clicks the link in the email, a method is called that checks that the token in their email matches the token stored in the db.
Now my question is: is it ok to use BCrypt's generate_salt method to generate this token, or is there some other way I should be doing this?
SecureRandom.hex is more suitable in that case.
since the modern encrption mechanism like shai doesnt allow decryption of the currrent passwords it is mandatory one to generate a new password. bcrypt should be fine doing this
After extensive research, I have not been able to find a clear answer to my question. Firstly, can anyone tell me the basic logic of handling "login functionality" for a native iphone app connecting to a web service? For instance, the facebook app ask for a username and password immediately after launch, and from there you have full access to your account in all successive views of the app. Each time you post something etc, you do not have to re-login... Can someone please explain this process to me? Is it done through cookies or sessions? is Keychain involved?
I have a semi-working app right now but I'm almost positive I could be doing it better and more securely. Here is what I'm doing:
1) Set up a local server with a database of users (username and password columns and other tables etc.) using mysql. Wrote a simple web-service that takes in POST data and queries the database to check that the username exists... and if it does, that the passwords are equal. Using sha1 hashing. Echo true or false accordingly.
2) My app has an initial login screen with a 2 textfields (1 for username and 1 for password) and a button that calls the login method. My login method does the following:
init an *NSURL with a string (the url of my web service: #"http://webservice.com/login.php")
init an *ASIFormDataRequst with that url
set the post value with the password and email text in the text fields
set the delegate to itself
call startAsycronous on the request
implemented the requestFininshed method to retrieve the "true" or "false" echo-ed from the webservice
depending on the response, move forward to the next view, else, make an alert telling the user to retry
So, my questions are:
1) Is this secure for sending passwords? (via ASIHTTPRequest and the POST method?)
2) In the succeeding views, the user should be able to interact with their account (like posting messages and status's and pictures on the Facebook) How do I persist the user's logged in status so that every time the user interacts with the database, I can ensure that the user is still logged in and that it's the same user? For instance, the only way I can think of doing this is if I store a cookie on the users device with the username and password, and then every successive interaction with the web service / database, it does an authentication with the cookie values (username and password).
There has got to be a better way of doing this? Maybe sessions or cookies? or by using keychain??
Thanks for the help guys, and sorry for the long question!
Here are my thoughts based on what I know:
1) Is this secure for sending passwords? (via ASIHTTPRequest and the POST method?)
You need to make sure you are sending this information via https (SSL) and not a plain Http. The reason is, you don't have control over where the user wireless access point is. For all you know, the user could connect to open access point that is belong to a particular hacker. Having it transmitted will enable him to sniff the packet and get the required information to access the WebService even though the password is hashed. Having it send via https would ensure that the packet is encrypted with strong key. Even if a hacker manage to sniff the packet out, it will take him a long time before he/she is able to decrypt the message.
In the succeeding views, the user should be able to interact with their account (like posting > messages and status's and pictures on the Facebook) How do I persist the user's logged in status > so that every time the user interacts with the database, I can ensure that the user is still logged in
and that it's the same user?
One commonly employed method to do this is to get the session token after the user logged in. That is, you create a random generated ID that you return upon successful login. You would then map this token with the user id in the backend and it is associated with a session time out. You refresh this time out every time the user connects to a webservice and time it out after certain period to avoid breach of security. You would then persist the session token in your device and then used that for subsequent call. As long the session is alive then the user is logged in. As the token is associated with a specific user, you also ensure the identity of the caller.
To prevent someone else using other people token is the reason why you need SSL to secure the channel and prevent sniffing. Assuming that you have secured your connection channels, the only way to get the token is
to verify the identity via login
The phone is stolen by hackers who could take the token by inspecting the local storage.
The mapping is necessary so you could validate the token is a real token that has been associated with the user via login activity. Furthermore,for number 2, you can offer remote wipe out feature that basically kills the mapping and making that token invalid.
Another very important part of this token is the token cannot be guessable and have to be random cryptographically (see Randomness Recommendations for Security). If the token is only based on pseudo randomness, a clever hacker might be able to guess its algorithm and can guess its next/previous token and has a possibility of obtaining any valid token in the table.
There are many algorithm to generate this token. For example, Java Programming Language provides a SecureRandom class in order to provide cryptographically randomness and .NET has similar secure RandomGenerator class.
If you want to look at the algorithm OATH has proposed Time-Based One-Time Password Algorithm (TOTP) which is an extension of HOTP. Most of the languages/platforms would have the cryptographically strong random generator that you could leverage immediately though without you having to write it yourself.
Depending on your service implementation/platform, you might want to ask SO for a suitable class/module for cryptographically random generator such as the one asked here "How do you generate cryptographically secure random numbers with php"