Validating a Devise User password WITHOUT changing it - security

i am using Devise and devise_security_extension.
https://github.com/plataformatec/devise
https://github.com/phatworx/devise_security_extension
I tried to figure out how i could validate a provided password WITHOUT updating a User record.
Validation (password was not used before, password is complex enough ....)
For example:
john = User.find(1)
john.password = "Testing"
john.password_confirmation = "Testing"
result = john.save
Result would return true or false. With result.errors i would get the related error messages (Thats exactly what i want but without really change this user password).
My Problem is that this would really change the password of this user (object). That would cause problems with old_passwords.
Is there any way to do a dry run ? (result = john.save_dry_run)
FYI:
I already tried to change the User password and change it back after i got the result. But this is really ugly and also make much trouble with devise old_passwords table.
I hope my question is clear enough. If you need any further information please let me know !

You should call valid? rather than save in your example. This will only run the model validations without actually saving any data to the database:
john = User.find(1)
john.password = "Testing"
john.password_confirmation = "Testing"
result = john.valid?
You can find more information in the Rails documentation.

Related

How Can I Check For The Existence of a UUID

I am trying to check for the existence of a UUID as a primary key in my Django environment...and when it exists...my code works fine...But if it's not present I get a "" is not a Valid UUID...
Here's my code....
uuid_exists = Book.objects.filter(id=self.object.author_pk,is_active="True").first()
I've tried other variations of this with .exists() or .all()...but I keep getting the ['“” is not a valid UUID.'] error.
I did come up with a workaround....
if self.object.author_pk is not '':
book_exists = Book.objects.filter(id=self.object.author_pk,is_active="True").first()
context['author_exists'] = author_exists
Is this the best way to do this? I was hoping to be able to use a straight filter...without clarifying logic....But I've worked all afternoon and can't seem to come up with anything better. Thanks in advance for any feedback or comments.
I've had the same issue and this is what I have:
Wrapping it into try/except (in my case it's a View so it's supposed to return a Response object)
try:
object = Object.objects.get(id=object_id)
except Exception as e:
return Response(data={...}, status=status.HTTP_40...
It gets to the exception (4th line) but somehow sends '~your_id~' is not a valid UUID. text instead of proper data. Which might be enough in some cases.
This seems like an overlook, so might as well get a fix soon. I don't have enough time to investigate deeper, unfortunately.
So the solution I came up with is not ideal either but hopefully is a bit cleaner and faster than what you're using rn.
# Generate a list of possible object IDs (make use of filters in order to reduce the DB load)
possible_ids = [str(id) for id in Object.objects.filter(~ filters here ~).values_list('id', flat=True)]
# Return an error if ID is not valid
if ~your_id~ not in possible_ids:
return Response(data={"error": "Database destruction sequence initialized!"}, status=status.HTTP_401_UNAUTHORIZED)
# Keep working with the object
object = Objects.objects.get(id=object_id)

Inquirer.js: ask multiple questions if one prompt is true

I'm writing an account creator using Inquirer.js, and wanted to ask for the user's e-mail and password only if the user asked for such protection. It goes like this:
inquirer.prompt([
{type:'input', name:'username', message:'Choose an username:'},
{type:'confirm', name:'protect_ask', message:'Do you want to password-protect your game list?'},
{type:'input', name:'email', message:'E-mail (for password recovering):', when:function(answers){return answers.protect_ask}},
{type:'password', name:'password', message:'Password:', when:function(answers){return answers.protect_ask}},
{type:'password', name:'confirm_password', message:'Confirm you password:', when:function(answers){return answers.protect_ask}}
]
As you can see, I'm running the exact same when statement three times, for it verifies if the password-protection was chosen or not. I want to know if there's a more intelligent, pragmatic way to do so, this is, to run this verification without repeating the when function.
Maybe nesting the three questions would do it, but how to do so without breaking the prompt flow?

Bcrypt Encoding Error

I'm creating a flask-app and using wtforms. I have password stored in my database that is created from a form using the following:
salt = bcrypt.gensalt()
hashed_password = bcrypt.hashpw(form.password.data.encode('utf-8'), salt)
Now I want to check the password using:
if bcrypt.checkpw(form.password.data.encode('utf8'), password_from_db):
When I do this the following error arises:
TypeError: Unicode-objects must be encoded before checking
Not sure exactly what is causing this or how to resolve. It is something to do with the form and the data type though as I can follow standard python examples.
Many thanks
EDIT
I've checked this question here but it didn't resolve my query. My query is using data from forms. I'm using the same method as in the answer but am still receiving the error.
salt = bcrypt.gensalt()
hashed_password = bcrypt.hashpw(form.password.data.encode('utf-8'), salt).decode('utf-8')
# While checking:
password_hashed=bcrypt.hashpw(form.password.data.encode('utf8'), password_from_db.encode('utf-8')).decode('utf-8')
if password_hashed == password_from_db:
print('User succesfully logged in')

Yii2 - how to properly use generatePasswordHash()?

I'm trying to generate a random password for a user in a Yii2 application.
I have the following code:
$rand_password = Yii::$app->security->generateRandomString(8);
$user->password = Yii::$app->security->generatePasswordHash($rand_password);
After that I save the $user model and the hashed string is also saved in the database. However, I cannot log in with the $rand_password string after that as I'm getting Invalid Password error message.
The generatePasswordHash description says that the hash is generated from the provided password and a random salt string. Indeed, I called the function with the same password string several times in a row and I got different result every time. So my question is, if that salt string is random and different every time, how can I use this function at all to verify passwords? When I try to login I call the same function with the password string provided by the user but this time the salt will be different so I'm unable to produce the same hash as before? What am I missing here?
Well, after hours of debugging and looking for resources and explanation, it turns out the the user module I'm using: https://github.com/amnah/yii2-user is actually automatically hashing the passwords before saving them in the database. In other words, as soon as you call:
$user->password = SOMETHING;
that SOMETHING is automatically going through the generatePasswordHash() function upon save. My problem was that I was dropping it in there in my code as well so basically the password got hashed twice.

Returning a string from LINQ

For a school project we have to create an evaluation website that requires a login.
For the database connection I chose LINQ, because it's new and is supposed to be easier/better in use.
I managed to create a login check with the following:
public static Boolean Controle(int id, string wachtwoord)
{
DataClassesDataContext context = new DataClassesDataContext();
var loginGebruiker =
from p in dc.Gebruikers
where p.GebruikerID == id
where p.GebruikerWachtwoord == wachtwoord
select p;
return true;
}
Now I'm trying to create a "forgot password" option, where you enter your id and the password gets returned (later it would be emailed to you, don't know how I would do this either, suggestions?)
I tried with the following code:
public static string Forgot(int id)
{
var context = new DataClassesDataContext();
var wachtwoordLogin = (
from p in dc.Gebruikers
where p.GebruikerID == id
select p.GebruikerWachtwoord);
return wachtwoordLogin.ToString();
}
Code behind the button on the page:
lbl1.Text = Class1.Forgot(Convert.ToInt32(txt1.Text));
Now when I enter the an id of the first user (1), lbl1 becomes this:
SELECT [t0].[GebruikerWachtwoord] FROM
[dbo].[Gebruiker] AS [t0] WHERE
[t0].[GebruikerID] = #p0
I don't know how to solve this and I have been looking everywhere, I hope somebody can help me.
Thanks,
Thomas
LINQ uses delayed execution, so your 'wachtwoordLogin' is really just "how to get your data." Its not until you apply an operator that LINQ will actually attempt to retrieve your data.
Your first statement:
var loginGebruiker = (
from p in dc.Gebruikers
where p.GebruikerID == id
where p.GebruikerWachtwoord == wachtwoord
select p).FirstOrDefault()
if (loginGeruiker != null) {
//Valid login
} else {
// invalid
}
FirstOrDefault means, take the first item in the list, or return none.
In you other case you need the same thing:
user = wachtwoordLogin.FirstOrDefault();
Further reading: MSDN 101 LINQ Samples
For your question about emailing a forgotten password, have you ever thought about implementing the golden questions algorithm instead? Its simplified, and does the same thing.
Basically, at the time of registering just get them to answer some questions, and if they can verify them, allow them to reset the password.
you enter your id and the password gets returned
What, then, is the point of having a password if anybody who knows a username can see it? I know this isn't what you're asking, but for someone getting started in programming I feel a duty to point this out. What you're creating here is essentially a completely broken login model. Nobody should ever use a system like this.
You should never ever display a password. Not on the screen, not in an email, never.
Passwords, if they even need to be stored at all (CodingHorror has had a couple of good posts on this lately, advocating things like OpenID), should be stored in hashed form and essentially unable to be retrieved. When a user logs in, similarly hash the password they provide (immediately upon reaching the application code, before transporting it anywhere else in the system) and compare that to the stored hashed version.
If the user asks for his password, you don't have it. You can't give it to him. This is for his protection. Instead of providing the user with his password, if it's forgotten then you provide the user with a means to reset his password (sending an email to the address on file with a temporarily available URL, a set of "security questions" to verify his identity, etc.) so that he can enter a new one to overwrite the old one. But you shouldn't be able to "show" the user his password because even you as the administrator of the system shouldn't be able to see it in any usable form.
wachwoordLogin will be an IQueryable so you can get this by using FirstOrDefault() which will return null if not found:
(from p in dc.Gebruikers
where p.GebruikerID == id
select p.GebruikerWachtwoord).FirstOrDefault();

Resources