I am working on a user authentification app using Django. The app allows the user to create an account then login. However, on the login side i am getting an error when checking for the user password using bcrypt.checkpw
I tried printing the value of the user password and the one saved on the data base. I am using SQLite for the database by the way
print(request.POST['login_password'].encode())
print(user.password)
here is the output:
b'87654321'
b'$2b$12$bQ6tEDKh.tOJnnPAj84Xe.BZnGi9kI.Sc6Q4gFPeTLw9x53VSVQOW'
I also tried:
print(request.POST['login_password'].encode())
print(user.password.encode())
b'87654321'
b"b'$2b$12$bQ6tEDKh.tOJnnPAj84Xe.BZnGi9kI.Sc6Q4gFPeTLw9x53VSVQOW'"
To creat user:
user = MasjeedUser.objects.create(first_name=request.POST['first_name'],last_name=request.POST['last_name'],password=bcrypt.hashpw(request.POST['password'].encode(), bcrypt.gensalt()),email=request.POST['email'])
to query password:
when i use
if bcrypt.checkpw(request.POST['login_password'].encode(),user.password)
i get as an error: Unicode-objects must be encoded before checking
when i tried
if bcrypt.checkpw(request.POST['login_password'].encode(),user.password.encode())
i get as an error: invalid salt
The reason you have an invalid salt is that you have an extra b'...' around the hashed password. That's because the result of hashpw is a bytestring, and Django will automatically call str on anything passed into a charfield that is not a string. You would need to decode it first.
But in any case you must not do any of this. Although bcrypt is a perfectly good hashing library, there is no reason for you to duplicate the functionality that Django gives you; by doing so, you will almost certainly introduce new security vulnerabilities. Don't do this. Inherit your MasjeedUser from the AbstractUser or AbstractBaseUser models in django.contrib.admin, and use their set_password and check_password methods.
Related
Have a local copy of Wiki (MediaWiki) but my predecessor left without handing over the password.
I got access to the server panel, and to mySQL, but despite I try to change the password as explained at https://www.mediawiki.org/wiki/Manual:Resetting_passwords I can't get it working.
In the localSetting.php file there is not a salt specified, which from ver 1.13 onward seems to be deprecated, but somehow my password have one.
E.g. :B:d1c1ee33:115272fdacb0ff5f6dcb3639d0bc08b3
Looking at the ./includes/User.php file, there is a crypt function that generate a random salt, so technically as long as I use a random name while using the following update statement I should be fine.
UPDATE `user` SET user_password = CONCAT(':B:somesalt:', MD5(CONCAT('somesalt-', MD5('somepass')))) WHERE user_name = 'someuser';
That's not the case. Anybody can help?
Use a maintenance script such as changePassword.php or createAndPromote.php.
I'm currently building a Google Cloud Endpoints backend with the endpoints-proto-datastore library, and am running into trouble requiring an apikey when you request a user.
Once a user logs in, they receive an APIkey which they send back for successive puts (which works) but how do I require the username/email and apikey on a GET ? Currently if a user does a get like so:
#User.method(request_fields=('id', 'apiToken',), path='users', http_method='GET', name='user.get')
def user_get(self, query):
return query
The user is pulled from the datastore because the ID is correct, and it completely ignores the apiToken. How do I require both fields?
(on a different note, how do I send back the user's ID on a request?)
If you are implementing your own API key scheme, as your code suggests, then you need to manually check if the API key is valid or not yourself.
Your example looks like the one from the 'basic' example, and you've added parameters as per the 'simple_get' example. For some background, the docs in the 'simple_get' example mention that 'id' is one of five special helper properties automatically defined by EndpointsModel for common operations like retrieving by id. This is why your code works automatically without you doing anything 'special' with the 'id' parameter. The example still checks though that the entity exists if you try to get it:
if not my_model.from_datastore:
raise endpoints.NotFoundException('MyModel not found.')
Since there's no special helper property for your 'apiKey' field, you need to add your own code in the method to check if the key is valid and return a 401 or suitable error if it's not. Another option is to also utilize some of Google's built-in authentication as per the 'basic_with_auth' example.
Finally, since endpoints-proto-datastore is just syntactic sugar for the main endpoints library, you'll want to read the full documentation on that for more information on things like how to return values from your endpoints methods.
The easiest way I found to do this is:
#User.method(request_fields=('id', 'apiToken',), path='users', http_method='GET', name='user.get')
def user_get(self, user_model):
user = ndb.Key('User', int(user_model.id)).get()
if user.apiToken != user_model.apiToken:
raise endpoints.UnauthorizedException('You are not authorized to view this data')
return user.clean()
The user_model will have the userId and the apiToken stored in it, so I pull the "real" data from ndb with the key and check if the user_model has the correct token and return the model if it is correct, if not, I refuse
I have installed django_two_factor_auth successfully: token logins, backup tokens and SMS via Twilio all seem to work fine. My users will not tolerate having to enter their token for every login, though.
My needs are similar to those discussed in the following:
https://github.com/Bouke/django-two-factor-auth/issues/56
I wish to offer the user an option to defer OTP verification for 30 days after a successful verification.
To this end, I installed django_agent_trust. I patched AuthenticationTokenForm to add a BooleanField if django_agent_trust is installed:
(two_factor/forms.py, in AuthenticationTokenForm)
try:
from django_agent_trust import trust_agent
trust_this_agent = forms.BooleanField(label=_("Trust this browser for 30 days"),
required=False)
except:
pass
and I have been able to unconditionally set and reset the is_trusted flag by using django_agent_trust's django_agent_trust.trust_agent API.
The problem is figuring out where to capture the user's selected value of the BooleanField. I'm lost somewhere in the form wizard.
I would accept an answer questioning the wisdom of my overall approach if I think your argument makes sense. Is there something I'm missing here?
in the beginning
django_agent_trust seemed like a good shortcut for this use case. It already had secure cookie support, a feature of Django I'd never used before, plus all the convenience methods I thought I'd need.
I was able to get it working with a little extra work.
problem
The problem I ran into was that django_agent_trust validates the signed cookie only after the user is authenticated -- with an authenticated user from the request object. Since I was trying to minimize changes to django_two_factor_auth, I needed to decide whether or not to show the OTP form before authentication occurs.
solution
All the tools I needed were in django_agent_trust. I pulled the methods I needed out of its middleware and into a new utils.py, adding a 'user' argument to load_agent(). Then I was able to check the cookie against the validated-but-not-yet-logged-in user object from django_two_factor_auth's LoginView class.
Now django_two_factor_auth's LoginView can test for agent trust in has_token_step and has_backup_step, and everything works more or less as the author predicted 11 months ago...sigh.
I think adding this trust element might make sense as an enhancement to django_two_factor_auth. Juggling hacks to all these components seems like the wrong way to do it.
later
I took a cue from the django_otp project and added agent_trust as a "plugin" to two_factor. It seems usable and maybe a little easier to digest in this form. This worked for me, but I suspect there's a much better way to do it. Patches welcome.
How do we retrieve a password of an user?
u = User.objects.get(username__exact=username)
print u.password
displays sha1$f0971$441cac8f604d49869e33ca125a76253a02fef64e
Is there a function to find the password from this encoded string?
No. It's impossible, by design. But there should never be a need to do it anyway.
Due to security restrictions the password hash method is one way. You will need to reset that users password.
Try using the set_password(raw_password) method to give the user a new password. Remember to call the save() method to ensure you save the change to the database.
u = User.objects.get(username__exact=username)
u.set_password(raw_password)
u.save()
You can check if the password is correct with:
u.check_password("your password")
This method and u.set_password("you password") solves all of your problems.
sha1$f0971$441cac8f604d49869e33ca125a76253a02fef64e is:
hash function algorithm $ salt $ hash code
no. and there shouldn't be. as part of the security, passwords are passed through a one-way function before they are saved, so that they aren't reveled if the database is compromised
what you can do is replace the user's password with one you know. this is how (good) site's "forgot your password" functions work: they send you a new random password, not your old one, since they (shouldn't) have access to it
No, the field contains the salted hash of the password. from the string we know it's SHA1 function. If you have the password, you will be able to produce the same hash value which acts as the footprint. For security reason there should be now way to recover the password in a economical means (you can still brute force, but will take long time).,
There is no way you can get the existing password because that password is been converted to salt hash.
I'm using this snippet, that allows users to only need to enter an email address to register for my app: http://djangosnippets.org/snippets/686/
Things are almost working perfectly. The problem is when a user has an email address that's above 30 characters. I get a "Ensure this value has at most 30 characters (it has 40)." error.
This is because the username is only supposed to be 30 characters. Is there a simple way to just tell Django that the username can be longer? It seems like there should be a fairly straightforward override for this.
This actually isn't simple at all. This requires subclassing the User model and using that everywhere. I've never had to do it, for this case, but it would likely cause significant issues with the Admin interface. You could also edit django's source to pull it off (ick).
Or even use this solution:
Can django's auth_user.username be varchar(75)? How could that be done?
It's quite ugly though.
You're probably better off writing an authentication backend to use the email field for authentication rather than using the username field. To populate the username (which is required) then you'd just generate some sort of random unique username maybe by hashing or using a UUID.
Hopefully this solution should help you : http://www.micahcarrick.com/django-email-authentication.html