I am trying to check the users input on my login form.
I am sending an HTTP request to the server to check the database for the username.
Here is the network URL:
https://bceec5a5-eba3-49e3-b255-d3976d185fad-ide.cs50.xyz:8080/user_name?username=fabianomobono
Here's the html
<form id="login_form" action='/home' method='post'>
<input id="login_credentials_username" name='login_username' type='text' placeholder='Username' >
<input id="login_credentials_password" name='login_password' type='password' placeholder="Password" >
<button class="btn btn-primary" type='submit'>Log in</button>
</form>
This is the JS code:
$('#login_form').ready(function() {
$('#login_form').on('submit', function(e) {
e.preventDefault();
logincheck();
});
});
function logincheck(){
var username = document.getElementById("login_credentials_username").value;
var password = document.getElementById("login_credentials_password").value;
if (username == ''){
alert("no user");
return false;
}
else if (password == ''){
alert('no password');
return false;
}
else if (password && username){
alert(password + username);
console.log(username)
$.get('/user_name?username' + username, function(r){
if (r === false){
alert('python returned false');
return false;
}
else{
alert('python returned true');
return true;
}
});
return false;
}
else {
return true;
}
}
and here is the python function:
#app.route("/user_name", methods=["GET"])
def login_usercheck():
print(Fore.GREEN + "user_check function, line 171")
username = (request.args.get('login_username'),)
print(username)
conn = sqlite3.connect('database.db')
c = conn.cursor()
c.execute("SELECT username FROM users WHERE username =?", username)
old_user = c.fetchall()
if len(old_user) > 0:
return jsonify(True)
else:
return jsonify(False)
The problem is that my username variable in the python function always returns NULL. I tried all combinations of,(request.form.get, request.args.get... and so on)
Funny thing is I have a similar function to check for the register credentials and that one works just fine. I can't seem to figure out what the problem is...
Here's what I get in the terminal:
(None,)
192.168.164.98 - - [05/Nov/2019 17:54:01] "GET /user_name?username=cf HTTP/1.0" 200 -
username = request.args.get('username')
$.get('/user_name?username' + username,...
the bold parts need to match
it was pointed out to me by another user...
Related
I want the user to verify his email address in the "email2" field and in case he has entered the wrong email address the function returns an error message and corrects his email address from the "email" field. This function returns no error but also does not work, ie does not report an error message when email addresses differ. I'm asking for help.
<html>
<script>
function validateForm() {
var x = document.forms["contactform"]["email"].value;
if (x == "") {
alert("E-mail is empty");
return false;
}
var x = document.forms["contactform"]["email2"].value;
if (x == "") {
alert("Verification E-mail is empty");
return false;
if(email != email2){
// Display the error message
document.getElementById("emailMismatch").style.display="inline";
alert("Email address does not match");
return false;
}else{
document.getElementById("emailMismatch").style.display="none";
}
}
}
</script>
<body>
<form name="contactform" method="post">
<input type="text" name="email" maxlength="80" size="30" placeholder="E-mail contact person" title="The e-mail must be in the format, example: primer#email.com ">
<input type="text" name="email2" maxlength="80" size="30" placeholder="Verify E-mail address" title="The e-mail must be in the format, example: primer#email.com ">
<input type="submit" value="Send" style="border:1px solid #000000">
</form>
</body>
</html>
You are missing a } to terminate the second IF so the third IF is inside the second and therefore never runs because it is after a return :)
<script>
function validateForm() {
var x = document.forms["contactform"]["email"].value;
if (x == "") {
alert("E-mail is empty");
return false;
}
var x = document.forms["contactform"]["email2"].value;
if (x == "") {
alert("Verification E-mail is empty");
return false;
} <-- !!!!!!!!!!!!! THIS WAS MISSING !!!!!!!!!!!!
if(email != email2){
// Display the error message
document.getElementById("emailMismatch").style.display="inline";
alert("Email address does not match");
return false;
}else{
document.getElementById("emailMismatch").style.display="none";
}
#} <-- THIS WAS IN THE WRONG PLACE REMOVE IT
}
</script>
You defined a variable named x to hold email input values, then you do comparison with email and email2 variable, which are not defined.
function validateForm() {
var email = document.forms["contactform"]["email"].value;
if (email == "") {
alert("E-mail is empty");
return false;
}
var verificationEmail = document.forms["contactform"]["email2"].value;
if (verificationEmail == "") {
alert("Verification E-mail is empty");
return false;
} <-- !!!!!!!!!!!!! THIS WAS MISSING !!!!!!!!!!!!
if(email != verificationEmail){
// Display the error message
document.getElementById("emailMismatch").style.display="inline";
alert("Email address does not match");
return false;
}else{
document.getElementById("emailMismatch").style.display="none";
}
}
I am trying to integrate CSRF protection on my forms, and I have started with my registration form that started out working before the CSRF tokens were added, but now just produce a "Invalid or Unexpected Token" error. Here is my current form:
<form method="post" name="registration_form" action="<?php echo esc_url($_SERVER['PHP_SELF']); ?>">
<input type="hidden" name="<?= $token_id; ?>" value="<?= $token_value; ?>" />
First Name: <input type="text" name='<?=$form_names['firstname'];?>' id='firstname' /><br>
Last Name: <input type="text" name='<?=$form_names['lastname'];?>' id='lastname' /><br>
Phone: <input type="tel" name='<?=$form_names['phone'];?>' id='phone' /><br>
Email: <input type="email" name="<?=$form_names['email'];?>" id="email" /><br>
Username: <input type="text" name='<?=$form_names['username'];?>' id='username' /><br>
Password: <input type="password"
name="<?=$form_names['password'];?>"
id="password"/><br>
Confirm password: <input type="password"
name="<?=$form_names['passwordconf'];?>"
id="confirmpwd" /><br>
<input type="button"
value="Register"
onclick="return regformhash(this.form,
this.form.<?=$form_names['firstname'];?>,
this.form.<?=$form_names['lastname'];?>,
this.form.<?=$form_names['phone'];?>,
this.form.<?=$form_names['username'];?>,
this.form.<?=$form_names['email'];?>,
this.form.<?=$form_names['password'];?>,
this.form.<?=$form_names['passwordconf'];?>);" />
</form>
</body>
I have included a hidden field with a name/value pair token, as well as random tokens for each name field. The tokens all work as intended, so the issue isn't in generating them. There is also a Javascript file that validates form entry, I don't know if it is relevant, but here is the js validation:
function regformhash(form, firstname, lastname, phone, username, email, password, confirmpwd) {
// Check each field has a value
if (firstname.value == '' || lastname.value == '' || phone.value == '' || email.value == '' || password.value == '' || confirmpwd.value == '') {
alert('You must provide all the requested details. Please try again');
return false;
}
// Check the First Name
re = /^[A-Za-z\s]+$/;
if(!re.test(form.firstname.value)) {
alert("First Name must contain only upper and lower case letters. Please try again");
form.firstname.focus();
return false;
}
// Check the Last Name
re = /^[A-Za-z\s]+$/;
if(!re.test(form.lastname.value)) {
alert("Last Name must contain only upper and lower case letters. Please try again");
form.lastname.focus();
return false;
}
// Check the Phone Number
re = /\d{3}[\-]\d{3}[\-]\d{4}/;
if(!re.test(form.phone.value)) {
alert("Phone Number must be formatted as follows, xxx-xxx-xxxx or (xxx) xxx-xxxx. Please try again");
form.phone.focus();
return false;
}
// Check the username
re = /^\w+$/;
if(!re.test(form.username.value)) {
alert("Username must contain only letters, numbers and underscores. Please try again");
form.username.focus();
return false;
}
// Check that the password is sufficiently long (min 6 chars)
// The check is duplicated below, but this is included to give more
// specific guidance to the user
if (password.value.length < 6) {
alert('Passwords must be at least 6 characters long. Please try again');
form.password.focus();
return false;
}
// At least one number, one lowercase and one uppercase letter
// At least six characters
var re = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}/;
if (!re.test(password.value)) {
alert('Passwords must contain at least one number, one lowercase and one uppercase letter. Please try again');
return false;
}
// Check password and confirmation are the same
if (password.value != confirmpwd.value) {
alert('Your password and confirmation do not match. Please try again');
form.password.focus();
return false;
}
// Create a new element input, this will be our hashed password field.
var p = document.createElement("input");
// Add the new element to our form.
form.appendChild(p);
p.name = "p";
p.type = "hidden";
p.value = hex_sha512(password.value);
// Make sure the plaintext password doesn't get sent.
password.value = "";
confirmpwd.value = "";
// Finally submit the form.
form.submit();
return true;
}
I don't know if the parameter names need to match up with the form names, they didn't all before and it worked.
Finally, the "Invalid or Unexpected Token" error was pointing to the closing </body>, if that helps as well.
Update:
I'm going to go more in depth about how this particular CSRF is working for this particular form. The form has an include to another php file, called register.inc.php, that does a series of sanitizations when adding data to the database, but I decided to also use it for the CSRF check. Here is the base code that relates to the CSRF (note, I haven't added the sanitization functions inside of the if statement yet, I'm trying to get the form to work without it before I add it in. I have a comment where it will eventually go):
include 'csrf.class.php';
require 'Sessions/session.class.php';
$session = new session();
// Set to true if using https
$session->start_session('_s', false);
$csrf = new csrf();
// Generate Token Id and Valid
$token_id = $csrf->get_token_id();
$token_value = $csrf->get_token($token_id);
// Generate Random Form Names
$form_names = $csrf->form_names(array('firstname','lastname','phone','email', 'username', 'password','passwordconf'), false);
if(isset($_POST[$form_names['email']], $_POST[$form_names['password']])) {
// Check if token id and token value are valid.
if($csrf->check_valid('post')) {
// Get the Form Variables.
// Add Sanitization function here
}
// Regenerate a new random value for the form.
$form_names = $csrf->form_names(array('email', 'password'), true);
}
Here is the csrf.class.php that is being referenced here:
<?php
class csrf{
public function get_token_id() {
if(isset($_SESSION['token_id'])) {
return $_SESSION['token_id'];
} else {
$token_id = $this->random(10);
$_SESSION['token_id'] = $token_id;
return $token_id;
}
}
public function get_token() {
if(isset($_SESSION['token_value'])) {
return $_SESSION['token_value'];
} else {
$token = hash('sha512', $this->random(500));
$_SESSION['token_value'] = $token;
return $token;
}
}
public function check_valid($method) {
if($method == 'post' || $method == 'get') {
$post = $_POST;
$get = $_GET;
if(isset(${$method}[$this->get_token_id()]) && (${$method}[$this->get_token_id()] == $this->get_token())) {
return true;
} else {
return false;
}
} else {
return false;
}
}
public function form_names($names, $regenerate) {
$values = array();
foreach ($names as $n) {
if($regenerate == true) {
unset($_SESSION[$n]);
}
$s = isset($_SESSION[$n]) ? $_SESSION[$n] : $this->random(10);
$_SESSION[$n] = $s;
$values[$n] = $s;
}
return $values;
}
private function random($len) {
if (function_exists('openssl_random_pseudo_bytes')) {
$byteLen = intval(($len / 2) + 1);
$return = substr(bin2hex(openssl_random_pseudo_bytes($byteLen)), 0, $len);
} elseif (#is_readable('/dev/urandom')) {
$f=fopen('/dev/urandom', 'r');
$urandom=fread($f, $len);
fclose($f);
$return = '';
}
if (empty($return)) {
for ($i=0;$i<$len;++$i) {
if (!isset($urandom)) {
if ($i%2==0) {
mt_srand(time()%2147 * 1000000 + (double)microtime() * 1000000);
}
$rand=48+mt_rand()%64;
} else {
$rand=48+ord($urandom[$i])%64;
}
if ($rand>57)
$rand+=7;
if ($rand>90)
$rand+=6;
if ($rand==123) $rand=52;
if ($rand==124) $rand=53;
$return.=chr($rand);
}
}
return $return;
}
}
When the form is submitted, it saves the CSRF tokens from the form in a Session and compares it to the Tokens in the Post value. If the two match, then it continues with the code. Here is the site I used to create the CSRF protection, Prevent CSRF.
So, I have a question about Javascript and HTML. Below I have my code, and I'm not sure why but whenever I try and run it(ie: hit Submit), my website freezes. I have it set right now so that it checks if the username/password EXISTS, but it does not have to be a combination of the 2 quite yet. Can someone help me?
<!DOCTYPE html>
<html>
<title> Welcome to my website!</title>
<body>
<form action="action_page.php" method = "post">
Username: <input type="text" name="user">
Password: <input type="password" name="pass">
<input type="submit" value="Submit" onclick="myLogin()">
</form>
<script type="text/javascript">
function myLogin(){
var usernames = ["rdoucett", "hovland"];
var passwords = ["Rd200161", "hovland1"];
usernames[5] = "stop";
passwords[5] = "stop";
var a = false;
var b = false;
var i = 1;
while(a===false) {
if(usernames[i] != form.user.value) {
i++;
}else if(usernames[i] == form.user.value){
a=true;
}else if(usernames[i] == "stop"){
alert("Incorrect username or password!");
a=true;
};
};
i = 1;
while(b===false) {
if(passwords[i] != form.pass.value) {
i++;
}else if(passwords[i] == form.pass.value){
b=true;
}else if(passwords[i] == "stop"){
alert("Incorrect username or password!");
b=true;
};
};
if(b&&a===true){
alert("Welcome " + document.getElementsByName("user") + "!");
}else{
alert("I do not recognize you " + document.getElementsByName("pass") + "!");
};
};
</script>
</body>
Don't use a while loop at all, just exit the myLogin function if it was an invalid username or password.
Be aware that what you have written here is completely insecure. Anyone visiting your website with even a basic technical knowledge can see your full list of usernames and passwords.
I changed your code a lot, but I think it is what you wanted. In your scenario beside a few errors, any valid username and any valid password would match. (i.e. user = "rdoucett" and psw= "hovland1").
function myLogin(){
var usernames = ["rdoucett", "hovland"];
var passwords = ["Rd200161", "hovland1"];
var username;
for (var i = 0; i < usernames.length; i++) {
if (usernames[i] == form.user.value) {
username = usernames[i];
break;
}
}
if (!username || passwords[i] != form.pass.value) {
alert("Incorrect username or password!");
}
else {
alert("Welcome " + document.getElementsByName("user") + "!");
}
};
From the security point of view, as already been said this is very insecure. You should think the HTML and JS as information any client can see. So this kind of functionality is what you must do server side.
Also note that the alerts wont avoid the form of being submitted. If you want to avoid that, you should add return false;.
Thanks for the input so far.
The logic is there but it still does not want to submit when passing true to submit...
I added an alert to see if it gets called when value is true, but for some strange reason, the 'return false' is not passing value to submit....
I cant understand what the issue is. Starting to get intimidated lol
<form name="newuser" id="form" method="post" action="do_new_user.php" onSubmit="return validateForm(false)">
function validateForm(submitNow){
if (submitNow == true){
alert ('call ok');
return true;
}
else
{
var x=document.forms["newuser"]["name"].value;
var x2=document.forms["newuser"]["surname"].value;
var x3=document.forms["newuser"]["email"].value;
var x4=document.forms["newuser"]["password1"].value;
var x5=document.forms["newuser"]["password2"].value;
if (x==null || x=="")
{
$("#form_status").fadeIn("slow");
$("#form_status").text("Please enter your name.");
return false;
}
if (x2==null || x2=="")
{
$("#form_status p").fadeIn("slow");
$("#form_status").text("Please enter your surname.");
return false;
}
if (x3==null || x3=="")
{
$("#form_status").fadeIn("slow");
$("#form_status").text("Please enter your email address.");
return false;
}
var atpos=x3.indexOf("#");
var dotpos=x3.lastIndexOf(".");
if (atpos<1 || dotpos<atpos+2 || dotpos+2>=x3.length)
{
$("#form_status").fadeIn("slow");
$("#form_status").text("Email address in invalid.");
return false;
}
if (x4==null || x4=="")
{
$("#form_status").fadeIn("slow");
$("#form_status").text("Please enter your password.");
return false;
}
if (x5==null || x5=="")
{
$("#form_status").fadeIn("slow");
$("#form_status").text("Please re-enter your password.");
return false;
}
if (x4!==x5)
{
$("#form_status").fadeIn("slow");
$("#form_status").text("Password Mismatch.");
return false;
}
//Check if username exists.
$.post("http://ryangosden.com/breadcrumbs/check_user_exists.php",
{
x3 : x3
} ,
function(data)
{
var obj = jQuery.parseJSON(data);
if (obj.email_exists == 1)
{
$("#form_status").fadeIn("slow");
$("#form_status").text("Email Address Taken.");
}
if (obj.email_exists == 2)
{
$("#form_status").fadeIn("slow");
$("#form_status").text("Email ok.");
validateForm(true);
}
});
return false;
}
}
If I understand correctly, the form should submit when email is not taken (and all other fields OK)
Which seem to be done at this point of your code :
$("#form_status").fadeIn("slow");
$("#form_status").text("Email ok.");
validateForm(true);
}
You have to catch the argument so you can submit the form, which could be done at the beginning of your function :
function validateForm(submitNow) {
if (submitNow) return true;
[... rest of function...]
}
Thanks to A. Wolff and Karl-André Gagnon for their comments, my first answer was too quick :)
Update:
Here is a working example you can extend on
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>
function validateform(submitNow) {
if (submitNow) return true;
else if ($('#input').val()) return validateform(true);
alert('Please enter a value');
return false;
}
</script>
<form id="#form" action="http://google.com" onsubmit="javascript:return validateform()">
<input type="text" id="input"><input type="submit">
</form>
I have a sign-up form which prompts for the first name, last name, username, password and e-mail address. I'm using two separate $.get() methods to check if the username and e-mail address are not existing.
This is my function:
function validateSignUp() {
var firstName = $("#first-name").val();
var lastName = $("#last-name").val();
var username = $("#username").val();
var password = $("#pass").val();
var email = $("#email").val();
var passwordVerifier = $("#retype-pass").val();
var emailVerifier = $("#retype-email").val();
errorMessage = "";
var isUsernameValid = validateUsername(username);
var isError = false;
// validate first name field
if (firstName == "" || lastName == "") {
isError = true;
$("#error-message").html("All fields are required");
}
// validate password
if (validatePassword(password) == false) {
isError = true;
$("#check-password").html("Password is invalid");
}
else {
$("#check-password").html("");
}
// validate password verifier
if (passwordVerifier == password) {
if (validatePassword(passwordVerifier) == false) {
isError = true;
$("#recheck-password").html("Minimum of 6 characters and maximum of 30 characters");
}
else {
if (password != passwordVerifier) {
isError = true;
$("#recheck-password").html("Minimum of 6 characters and maximum of 30 characters ");
}
else {
$("#recheck-password").html("");
}
}
}
else {
isError = true;
$("#recheck-password").html("Passwords didn't match");
}
// validate username field
if (isUsernameValid == false) {
isError = true;
$("#check-username").html("Alphanumeric characters only");
} // if
else if (isUsernameValid == true) {
$.get("/account/checkavailabilitybyusername", { username: username },
function(data) {
if (data == "Not Existing") {
$("#check-username").html("");
}
else if (data == username) {
isError = true;
$("#check-username").html("Sorry, this username is already registered");
}
}
);
} // else
// validate e-mail address field
if (validateEmail(email) == false) {
isError = true;
$("#check-email").html("Sorry, the e-mail you typed is invalid");
} // if
else if (validateEmail(email) == true) {
$.get("/account/checkavailabilitybyemail", { email: email },
function(data) {
if (data == "Not Existing") {
$("#check-email").html("");
}
else if (data == email) {
isError = true;
$("#check-email").html("Sorry, this e-mail is already registered");
}
});
}
if (isError == true) {
return false;
}
return true;
}
When other fields are blank and the username and/or e-mail address is existing, the form is not submitted. And the callback functions of the get methods are called as well. But when I'm going to submit my form with no empty fields, it is automatically submitted without checking the username and/or e-mail by $.get(). Is there anything wrong with my function or I'm not yet discovering something. Thanks.
You need to use a full ajax() call and set the async property to false. This makes your request synchronous, i.e. it forces the browser to wait until doing anything else. Try this:
$.ajax({
url: "/account/checkavailabilitybyemail",
data: { email: email },
async: false,
success: function(data) {
if (data == "Not Existing") {
$("#check-email").html("");
} else if (data == email) {
isError = true;
$("#check-email").html("Sorry, this e-mail is already registered");
}
})
});
if (isError == true) {
return false;
}
I suggest you leverage Jquery validate with two remote rules. It's quite easy to implement and a very mature plugin. This way you can focus on other aspects of your UX and not have to re implement this validation logic should you need to validate another form in your project.
Inside your main function, you cannot directly wait for the $.get() to return. But you can move the form submission to the success callback of the AJAX call (assuming form to contain a reference to the actual form element):
$.get("/account/checkavailabilitybyusername", { username: username },
function(data) {
if (data == "Not Existing") {
$("#check-username").html("");
form.submit();
//--------------------------^
}
else if (data == username) {
isError = true;
$("#check-username").html("Sorry, this username is already registered");
}
}
);
Note however, that then the form submission depends on the AJAX to return. Most useful would be a timeout (with window.setTimeout()) and a server-side validation, if the JS doesn't respond or the user has JS disabled.