Retrieve hashed password in Odoo 13 using API - python

In Odoo 11 I could retrieve the hashed password from password_crypt field in res_users table, but this doesn't work in Odoo 13 any more.
I used the Odoo 11 credentials to login to other applications, which can't be integrated in Odoo. This authentication stopped working as the password seems to be write only. Now I'm looking for a way to get read access to the Odoo password, any clue how to do that using the API?
I use the following python test code, but password field is empty:
import xmlrpclib
common = xmlrpclib.ServerProxy('{}/xmlrpc/2/common'.format(url))
uid = common.authenticate(db, username, password, {})
models = xmlrpclib.ServerProxy('{}/xmlrpc/2/object'.format(url))
user = models.execute_kw(db, uid, password,
'res.users', 'search_read',
[[['id', '=', 2]]],
{})[0]
print user
Any idea how to read the write only hashed password?

Since the read() method is overridden on res.users to exclude some fields, such as the password field, I would (not*) recommend to create a method on the res.users that does a SQL read like so:
def read_password(self):
self.ensure_one()
self.env.cr.execute("SELECT password FROM res_users WHERE id=%s", self.id)
*Disclaimer: There is a reason that Odoo hides the password field, so here you are essentially bypassing Odoo's security. You will need to make triple sure that this method is 100% secure. Some ideas:
Add a check for the correct API key
Only allow a certain user to execute this method
Only allow a certain IP source to execute this method

Related

unable to compare password using firebase admin sdk in python

I am using admin-SDK of firebase in python
I have created a new user using the following code
user = auth.create_user(
email=email,
email_verified=False,
password=password,
display_name=name,
disabled=False)
now I have created a function that takes name , _email id _ and password from the user and fetch user using it's email id and then checks if entered details are correct.
def check_user(self, name, email, password): # fixme compare password
user = auth.get_user_by_email(email)
if user.display_name == name and user.email == email:# add password comparision
print('successful login')
return True
else:
print('username or password incorrect')
return False
I want to compare password entered with the password stored, but I am unable to compare as I can't access password, I can only access passwordHash using user.passwordHash and passwordSalt using user.passwordSalt.
is there any away I can find passwordHash or passwordSalt of password so I can compare the hashes.
The usual flow when using Firebase Authentication is that your users sign in with client-side code that uses a Firebase SDK directly. So in that case,
Firebase itself would be performing the check whether the password is correct.
You can perform the check yourself, but you'll have to hash the plaintext password from the user in your code and then compare the stored and calculated hash values, essentially duplicating what Firebase already does. Firebase uses a modified version of scrypt to encrypt the passwords.
There's a library called pyrebase. You can use it to mimic client in server. Simply use sign_in_with_email_and_password(email, password) once you initiate the pyrebase object.
GitHub url: https://github.com/thisbejim/Pyrebase
Firebase Admin SDK for python do not provide a way to compare password. However, there is a solution to confirm user authenticity.
This might be helpful https://stackoverflow.com/a/71398321/9681645

MongoEngine - Call function only when document is being created or specific field being set?

I'm not sure what is the best/pythonic way of having a User document that automatically hashes its password upon creating.
Consider the following mongoengine model :
class User(Document):
email = EmailField(required=True, primary_key=True)
name = StringField(required=True)
pswd = StringField(required=True)
def check_pswd(self, password):
return verify_password(password, self.pswd)
def hash_pswd(self, password):
return hash_password(password):
def save(self, *args, **kwargs):
self.pswd = self.hash_pswd(self.pswd)
super().save(*args, **kwargs)
When I create a user, it works fine :
user = User()
user.email = 'user#email.com'
user.pswd = 'password'
user.name = 'User'
user.save()
Buf if I update it, it will double hash its password, I don't want that.
#User wants to change his name
user = User.objects(email='user#email.com')
user.name = 'User 2'
user.save()
Is there a way for me to hash its password only when creating or changing the password?
Or maybe I should delegate the responsibility of hashing the password to the View/Controller?
I am not giving you the code sample, you can use Document.update() method which will update the fields that only has changed.
If you still wanna use the save method,
Then you can create a logic along the following lines.
Check if the user has changed the password(by comparing the existing stored hash and new hash if any)
If the new hash is different then user has changed the password in that case you can push an Document.update method.
If not, don't call update on that field.
Alternatively update in Mongoengine accepts a iterable, so you can simply create a list or a dictionary object and convinently choose to Remove the password hash field from it.
As for who should execute this i.e View / Controller, its a Design decision but I would rather keep Representation (GUI / Front End) seperate from logic, so I would delegate this to the controller or even more Intrinsically to the Object who is responsible for handling all database/network related tasks, this way it would be isolated and easy to modify. And would not complexify or slow the View objects process / thread
Link for update using an iterable like Dict.
stackoverflow question for Mongoengine update using iterable
Link discussing save methods deprecation (The Maintainer Has commented below as save method not being deprecated, so trust him/her and proceed at will on this link)
Mongoengine save method deprecated?
Link for update method in mongoengine.
Mongoengine Atomic Update

Is it possible to deny access to copied password field in database?

My Django app password in database looks like this:
pbkdf2_sha256$100000$XXXXXXXXXX$XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
But if I duplicate it to another user, I could log in to that user's account.
Assuming a database breach or some kind of injection, can I detect if password was somehow duplicated/copied so that I can deny access to the account or alert admins?
as Selcuk says if some one has access to write into your database, he/she can do anything like generate password as your system want.
but you can make it harder to change password.
if you want to deny password copy from database you must create your own user model and update hashing algorithm like this.
first create a user model:
from django.contrib.auth.hashers import make_password, check_password
class MyUser(User):
def set_password(self, raw_password):
self.password = make_password(self.username + raw_password)
self._password = raw_password
def check_password(raw_password):
def setter(raw_password):
self.set_password(raw_password)
self._password = None
self.save(update_fields=['password'])
return check_password(self.username + raw_password, self.password. setter)
by these changes user password hashes are contain username and copy hash for other user does not works correctly

Querying information for HTTPBasicAuth

For my site for auth I'm using https://flask-httpauth.readthedocs.io/en/latest/ . Now I'm trying to make it that it's using data from database. To do that i created database named Users and created columns named username and password.
To get data from this table after defining its class as model I've made get_user functions which looks like it:
#staticmethod
def get_user():
query = (Users
.select())
user = []
for s in query:
user.append(s)
return user
(I'm not sure if it's correct)
Next I had to modify get_pw function but I also wasn't sure how to modify it so I made it look like it:
#auth.get_password
def get_pw(username):
if username in Users.get_user():
return users.get(Users.get_user())
return None
Now after running the site I get prompt to give login and password but those that I set up in my database doesn't seem to work so there must be a problem with get_pw function. Also I'm using peewee SQL to manage database : http://docs.peewee-orm.com/en/latest/peewee/querying.html
You can get rid of your get_user method since you are issuing a very large select query that fetches all records from user table. The get_pw can be redefined as:
def get_pw(username):
user = Users.get(Users.name == username) #assuming you have a username field in model
return user.password #assuming a password field
Also, its a good practice to define your model class as a singular noun rather than plural. So, its better to call it User rather than Users.
This'll help you get started in no time: http://docs.peewee-orm.com/en/latest/peewee/quickstart.html#quickstart

django, entering a hashed password in registration and storing it as such

I am working on openedx(works on django) and i need to create an api to register the user coming from a particular site, i am being given a hashed password not a normal one and i need to save it as so.
The problem here is that the openedx's registration function hashes the password that is being passed into it.
so is there a way in django to store a password/register a user without hashing the password.
Should i go for updating the user's credentials directly using
raw()
any help would be appreciated, thanks.
I would suggest to override method set set_password in user_model.
class MyUser(AbstractBaseUser):
# if you need to hash passwords for some users.
is_password_hashed = models.BooleanField(default=True)
...
def set_password(self, raw_password):
if self.is_password_hashed:
super(MyUser, self).set_password(raw_password)
else:
self.password = raw_password
If you want to store only non-hashed passwords:
class MyUser(AbstractBaseUser):
...
def set_password(self, raw_password):
self.password = raw_password
Or even override default user model set_password method.
It's as simple as:
from django.contrib.auth.models import User
User.objects.filter(username="myuser").update(password=hashed_password)
(remember passwords are stored as hashed values in the database)
The Open edX manage_user management command was recently updated to support this use case when creating a new user.
Example:
./manage.py lms --settings=devstack manage_user jane jane#example.com --initial-password-hash 'pbkdf2_sha256$20000$mRxYkenyBiH6$yIk8aZYmWisW2voX5qP+cAr+i7R/IrZoohGsRK2fy4E='
However, that command requires a very recent version of Open edX and it will not have any effect if the user account already exists.
As an alternative, you could set up SSO between the external app and Open edX using OAuth2, in which case there's no need for Open edX to store any password at all.

Categories

Resources