Is there anything wrong with this procedure?
Enter in username and email in a reset form.
Flask creates a really long random string and stores it into the session under "reset_code". Session will also have a key for "reset_pw_username"
Flask sends an email with a link to the path /password_reset/reset_pw_username/reset_code
That link displays a form where the customer can reset the password if the session reset code matches the session reset_code item. Otherwise it bombs out.
The session will expire the reset code after an hour.
If I can enter a username and email address, then I can get a reset token for any user of your service emailed to me. Maybe you should check that the email address is one that actually belongs to the user whose password is going to be reset.
You must ensure that username and email entered match one of the accounts (or use emails as username in the first place).
From a usability perspective, this won't work if the browser that displays the link contained in the email is not the same as the one initially used.
Apart from that, you should pay special attention to the randomness (not so much the length) of the reset_code. It should be cryptographically random (i.e. os.urandom) so that an attacker cannot simply guess it. random.random and derived methods are not suitable.
As Jean-Paul pointed out, asking for both username and e-mail requires checking whether they both match the same user. Hence it is more common to ask for either username or e-mail, verifying they are in your database, and sending recovery link to appropriate address.
Storing the recovery token in session data will likely be cumbersome for some users, as phihag described. Such tokens are usually stored in regular database. Note, however, that they are password-equivalent: once obtained, they can be freely exchanged for a password. Because of that, they need to salted & hashed (in the same secure manner that is applied to passwords themselves) before storing in the database. This also means that your recovery handler must salt & hash the incoming token before searching for it in your database.
The best solution is use email address as username,then user just have to remember his email address.And you just only have to validate user's email address.
Related
I would like that every time a user changes the password, it is also changed on firebase. The main problem is that the passwords taken from the wordpress database are hashed, while the auth.update_users command takes the raw password.
Obviously I'm not aware of the password in raw format...
What can I do?
i had try it:
...
users = auth.get_user_by_email('user1#gmail.com')
print('Successfully email fetched user data: {0}'.format(users.uid))
user = auth.update_user(
uid=users.uid,
password='$P$BOCNIc5Nw1e9fwm8HaLBChsd7eE4Hh1'
)
print('Sucessfully updated user: {0}'.format(user.uid))
There's nothing you can reasonably do here with the hash. The whole purpose of storing hashes (and hopefully salts) is to make it unfeasible to brute force revert password hashes to their cleartext password. If you could do that, so could any malicious user that gets access to the database of hashes.
If you want to send the cleartext password to two providers, you'll have to capture it at the source (so when the user enters it in the web app) and then send it to both providers.
I am very new to Django rest framework. I am building APIs for my mobile application.
In forgot password module, I have the below flow
Ask user to enter mobile
check existence
If exists - > send OTP
Verify and let user create a new password.
But in this case, I would like to know the way of handle the below situation.
When one user requests otp and waiting for it to verify, meanwhile another user requests for OTP
At this time, how to handle the both users?
I thought of
creating the dictionary and save the user id as key and otp as value in views.py to verify particular user.
store the otp temporarily until it verifies.
Which is the secured way and any alternative for this kind of scenario?
You should create a table look like this:
===== UserOTP =====
user: foreign-key to user
code: CharField, random generated code here (or token)
create_date: auto-fill created datetime
used_date: nullable datetime field
Then on each password reset request create a row on this table, send generated code to user via SMS or Email,
And then on another end-point receive the code from user and check it (for expiration and used before, belongs to this user and etc.) then continue password reset process.
There is a better way to do this, since otp are for temporary use, there is no use case for storing them in database, we can use hashlib.blake2s(b'otp', key=b'secretkey').hexdigest() to generate a hashed string and send it to user and then accept the same hashstring in the otp verification request and check for truthy of hashstring generated from user shared otp, this is oneway to handle otp verification.
The hashlibs blake2s accepts only bytestring, and you can also use any other hashing algorithm for this purpose. I am also open to ideas if there are any better ways to do this, please update in comments.
Using sessions would be better choice as it works for both django and djangorestframework.
In my python project i am planning to use TOTP.
A new User enter his email. Then he recieves a OTP generated using TOTP.
import pyotp
totp = pyotp.TOTP('base32secret3232')
totp.now() # => '492039'
The OTP is valid for 30s.
Now one can enter a fake email and use this same OTP which will be valid till 30s.
totp.verify('492039') # => True
So how to protect from such things.
Till the user's email is verified i dont want to save the firt time user in database
From the PyOTP docs:
At minimum, application implementers should follow this checklist:
...
Deny replay attacks by rejecting one-time passwords that have been used by the client (this requires storing the most recently authenticated timestamp, OTP, or hash of the OTP in your database, and rejecting the OTP when a match is seen)
...
So when using a TOTP, you have to store something. There's no way around that.
Also note that 30s is a pretty short time for email-based OTPs. If the mail server is only a bit slow, the OTP will have expired.
There is an alternative approach for verifying email addresses that doesn't require you to store anything. In the email, include a link with a query parameter that is encrypted using a key that only your server knows. In the encrypted data, include the email address and registration timestamp. The server decrypts this, checks that the timestamp is still within acceptable range, and adds the email address the database.
Theoretically, there's not even a reason to encrypt; signing would serve the purpose. But the client has no need to know the URL contents, so we might as well not reveal it.
I have managed to salt and hash password using this method:
import hashlib, uuid
salt = uuid.uuid4().hex
hashed_password = hashlib.sha512(password + salt).hexdigest()
How do I reverse this process to recover the actual password?
Update: You are supposed to take a password from the user, apply the same salt and hash method to their password, and then compare it with the originally salted/hashed password to see if they match. That makes perfect sense.
You don't. Hashing is a technique which is only one way. This is the whole point of hashing.
You never store raw passwords in order to protect your user if you got a leak of information in your DB.
If you want to implement some "password recover" procedure, you need to do as everyone do, send a email to the person with a temporary link to reset password on send a new one randomly generated.
Hashing is one way as in you can only encrypt (for example) a string and then compare the user provided hash with the one your app generates.
However, there is simple-crypt and it may be what you're looking for if you want "2 way" hashing.
Good question.
First off: never send users their passwords in plaintext!!
It's considered a bad security practice for a few reasons.
If anyone gets access to a user's email account (gmail, etc), then they have the password and can hijack the user account.
Second, hashing is a one-way form of encryption where you turn the password into gibberish. The big value in hashing is that the same password will always be turned into the same gibberish: every time. This means you can do password matching without ever storing the raw password. The reason you're supposed to hash a password and not do 2-way encryption like AES-256, is that 2-way encryption requires the creation, management, and securing of encryption keys which can be hard. Hashing is just easier and more secure for the vast majority of developers.
Instead of implementing password reset stuff by sending a user their password, you should instead send a user a link to a secure page where they can reset their password with a one-time token that expires after a certain amount of time.
This way, even if an attacker gets a hold of someone's email account (gmail, etc.) -- there's only a limited amount of time they can do damage.
There are a variety of ways to do this stuff yourself, but an easy approach to getting a one-time use token you don't have to store or manage is to offload user management to a microservice like Stormpath where it takes care of all the user management for you: password reset, password storage, user profiles, authentication, encryption, hashing, etc.
If you wanted to implement something like this in a Flask web app, for instance, you'd use the Flask-Stormpath library like so:
from flask import Flask
from flask.ext.stormpath import StormpathManager
app = Flask(__name__)
app.config['STORMPATH_ENABLE_FORGOT_PASSWORD'] = True
stormpath_manager = StormpathManager(app)
app.listen(3000)
NOTE: I work at Stormpath, but these rules apply regardless of what you're using and help make any application more secure.
I have a client app that interacts with a web service to retrieve account information. There's a requirement that the user is notified if they mistyped the username/password. I'm modifying the web service to return something to my client to provide a hint to the user that there's an error in input.
How do I correctly implement the "username/password" not found for a web service using Python?
Do I tell the user that the username exists, but the password is incorrect?
Do I tell the user that there is no such username, but the password matched something?
Do I show a generic username/password combination is not found?
Do I use different status codes for different situations or provide a JSON payload with the error?
here's my code so far:
from flask.ext.httpauth import HTTPBasicAuth
accounts = [
["user0", "password0"],
["user1", "password1"],
]
#app.route('/accountlist')
#auth.login_required
def accountlist()
username = auth.username();
if ... : #check if accounts does not have the given username
#notify the sender that there is no such username
return Response('Not Authorized', 401, {'WWW-Authenticate': 'Basic'})
else:
#proceed to check password and retrieve/return account information
Do I show a generic username/password combination is not found?
Yes. Why do you think this is "generic"? Because it is the standard. This is the correct way because than a hacker can't go phishing for usernames.
Do I tell the user that the username exists, but the password is incorrect?
No, letting the user know that the username is correct is a user enumeration vulnerability. You are letting an attacker know which usernames are valid allowing them to narrow their target range. This would be useful if they later decided to try a brute force attack as they already know the usernames are correct and now they only need a working password.
Do I tell the user that there is no such username, but the password matched something?
Definitely not. This would mean that the attacker now had a valid password and could use any other username enumeration vulnerability on your site in order to try and find a valid username. Another common username enumeration location is the forgotten password form - many sites report back that there is no such username allowing an attacker to refine their list. Alternatively, they could use this password and brute force a username from it which may be a much easier job as usernames shouldn't benefit from being complex.
As an aside to this, you should be storing your passwords salted and hashed using a secure, slow algorithm such as bcrypt. This should mean it is not possible for you to practically check to see if any password matches the one entered.
Do I show a generic username/password combination is not found?
Yes!
Do I use different status codes for different situations or provide a JSON payload with the error?
Your JSON could return true or false to let the calling JavaScript know whether authentication was successful. If you ever develop any brute force protection, this should be accomplished by introducing a delay in the response rather than hard locking accounts. Hard locking accounts leads to a DoS attack as an attacker can lock out a valid account by repeatedly using the wrong password on purpose. For this reason, only a true/false response is really needed to let the user know if they were successful. Even if the account was hard locked, I would return false but include in the message that the user should contact technical support if they believe they should have access with the password provided.
You don't mention what kind of data you're serving but if you're working in financial or health care data: make it so either the user can log in or they cannot, you shouldn't endeavor to give them any information as to why.
If you want you can tell them that the username is incorrect but you cannot suggest other usernames. And, of course, you cannot give any information about what might be wrong with the password, just tell them that it's incorrect.
About the code you presented, I realize you didn't really ask for coding advice, still, I do tons of code reviews and consistently see the same issues over-and-over with these roll-your-own authentication schemes. If your code is ever audited the auditor will likely find the following issues:
You must never hardcode passwords.
You must never persist a password in cleartext, always use an irreversible hash (SHA-1 or greater) when a password is received and only work with the hash value
Your applicatoon should 'fail-closed', meaning set up the accountList() function to return a 'not authorized' prior to the if statement and prior to calling any functions that would throw an exception (like a database access). Make the auth check in the if statemnt. That way if something fails in the things that the if statement calls (say an exception in data access or file i/o) the user fails to log in.