We have an existing membership site setup in php/MySQL, and are looking to integrate Facebook registration and login. The login and registration forms have been imported, and are hooked up to php/MySQL code which creates new users in the database. However, in order that we can prevent a single user having multiple logons (eg. one site logon, one Facebook logon), we need to check the email address of the user before adding a new line to the members database table.
We can do this through php/MySQL code, but that gets needlessly complex when you have to cater for all the permutation of cross-site/FB membership, plus we do not want the user to connect to the FB registration app without becoming a site member. A better solution would be to prevent the user from registering under an email address which is already present in the database (rather directing them to obtain a new password, and update connect their facebook profile to the existing profile). We have been looking for weeks for a solution, and have consulted the Facebook Developers Async Validation (http://developers.facebook.com/docs/plugins/registration/advanced/), as well as the stackexchange forum, but have not been able to implement a solution which validates the email address against the database, and prevents/allows registration accordingly.
The code we have so far is
<fb:registration redirect-uri="http://www.mysite.com/register.php"
fields='[{"name":"name"},{"name":"email"}
{"name":"username","description":"Username","type":"text"}]'
onvalidate="validate_async"></fb:registration>
<script src="https://code.jquery.com/jquery-1.4.4.min.js"></script>
<script>
function validate_async(form, cb) {
$.getJSON('http://www.mysite.com/register_check.php/' + form.email + '?callback=?',
function(response) {
if (response.error) {
// Username isn't taken, let the form submit
cb();
}
cb({username: 'That email is taken'});
});
}
</script>
register_check.php
//connect to the database
include 'mysql_connect.php'
$email = $_GET('email');
$data = array();
$sqlCommand = "SELECT * FROM members WHERE email='$email'";
$query = mysql_query($sqlCommand) or die (mysql_error());
$num_rows = mysql_num_rows($query);
if($num_rows>0){
$email_check = $row['email'];
$data['email'] = $email_check;
} else {
$data['error'] = "true";
}
echo json_encode($data);
Unfortunately, this process is not working at all. The registration form simply hangs endlessly, without validating nor passing the information to the database. We have done considerable research into how to properly code getJSON and the server-side php, but have come up against brick wall, so would very much appreciate any help or advice on this issue.
I hope this isn't too late, but after facing the same problem I found out the registration plugin doesn't send with the form object the preset details (name, email, gender, birthdate) -- only sends any custom fields. Quite dumb imo but could have an advantage or two.
Solution was to override the description of the email so as to trick it into thinking it's custom (which it would be) -- disadvantage being your regular checks will not be checked against (valid email et al) so you'll need to take care of those manually.
This may be late, but:
Change your JSON address to
http://www.mysite.com/register_check.php?email=' + form.email +
You were using facebook's check for existing user. Change:
cb({username: 'That email is taken'});
to:
cb({email: 'That email is taken'});
You want error message to appear next to email field.
Related
I am building a login form using ajax php and MySql.
I've done my fair share of research and I didn't like much posts found online, so I've built the below code.
My question is, is this secure at all? I'm not using any hashing and I'm not sure how it would be done with ajax. All the examples are much appreciated
INDEX.PHP
<script>
$(document).ready(function(){
$('form[name=loginForm]').submit(function() {
$.post('ajax.php', { username: $('[name=username]').val(),
password: $('[name=password]').val()},
function(data){
if(data.success){
alert('welcome');
}else{
alert("incorrect");
}
}, 'json');
return false;
});
});
</script>
ajax.php
<?php
if($_POST){
/** Fetch data from mysql **/
$u = $_POST['username'];
$p = $_POST['password'];
$sql = "SELECT * FROM users WHERE username='$u' AND password='$p' ";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$_SESSION['userid'] = $row["username"];
$_SESSION['userid'] = $row["username"];
$data['success'] = true;
}
}
else
{
$data['success'] = false;
}
/** Fetch data from mysql **/
echo json_encode($data);
} ?>
THANKS ALOT
My question is, is this secure at all?
No, it is not secure.
I'm not using any hashing and I'm not sure how it would be done with ajax.
Authentication actually cannot be done with ajax. With respect, you're barking up the wrong tree.
Start by reading this part of the PHP manual. http://php.net/manual/en/faq.passwords.php Go read it now. We'll wait.
Welcome back. You should never put your plain text password into a database. If you're not sure why that's true read about the "Ashley Madison data breach" online or go visit https://haveIBeenPwned.com/
You want to make it as hard as possible for a cybercriminal who steals your user table to guess your users' passwords. If you store them as text, they are trivial to guess.
Let's say your users are registered already. The point of your password authentication is to
gather the username and password from the user.
look up the user by name in your database, pulling back the hashed password.
compare the hashed password in your database with the one you gathered from the user. php's password_verify() function does this well.
if the validation fails, refuse the user's information. Do not give them any hint what was wrong. Simply tell them "your login failed." You don't want to tell them "you gave the right username but the wrong password."
if the validation succeeds, you then generate a session for that user so they can continue to use other pages in your web app without logging in again. Read about php sessions here.
you use a session id to represent the session. A session id is a hard-to-guess data token with a limited lifetime. php offers a session_create_id() method for this.
you put that session id in a cookie and feed it back to your browser. You can't reliably feed cookies to browsers with AJAX so your authentication strategy won't work.
Subsequent requests to your web app present the session id in the cookie. You check it to make sure it it's valid and it hasn't timed out. Then you do what the user asks you to do.
in ProcessWire admin you're only able to log in using your name (username) but as I'm using e-mail log in in front end I want to use e-mail for backend, too.
How can I change admin login form to allow e-mail-address?
Here is the solution I came up with
I placed those hooks in my site/init.php file
// change login name input label to e-mail-address
$wire->addHookAfter('ProcessLogin::buildLoginForm', function(HookEvent $event) {
// on liner as we don't change anything else
$event->return->get('login_name')->set('label', $event->_('E-Mail-Address'));
});
// hook into session::login to get user by mail
$wire->addHookBefore('Session::login', function(HookEvent $event) {
// need to get email from $input as processLogin::execute is pageName sanitizing
$email = $event->input->post->email('login_name');
// stop here if login_name not a valid email
if (!$email) return;
// new selector arrays don't seem to work on $user so using $pages here
$user = $event->pages->get([['email', $email]]);
// if valid user set login name argument
if ($user->id) $event->setArgument('name', $user->name);
});
bare in mind that e-mail is not a unique field so if you don't ensure uniqueness of e-mail addresses this won't work, you could change it a little to overcome this though..
Have a look at https://processwire.com/talk/topic/1838-login-using-e-mail-rather-than-username-and-general-login-issues/ where Ryan posts some more infos about this and possible solutions in case of duplicate e-mail addresses
and https://processwire.com/talk/topic/1716-integrating-a-member-visitor-login-form/ for more on front-end login strategies
Is checking against my table with the user's email and dedicated hash enough to verify and activate an account if a match is found against those two values?
A user is asked to register themselves with user data and their email id. They are then sent a URL to their email which they are asked to click on to confirm and activate their account.
This is my current setup:
<?php //The user-account-creation processing page
$email_id = taken from user input;
$randomnessWhateverItsCalled = "lots-of-randomness-here";
UPDATE advert SET advert_hash = SHA1(CONCAT($email_id, $randomnessWhateverItsCalled))
//For simplicity's sake I omitted the PDO stuff
INSERT INTO table_name (..., user_email, hash, account_activated, ...) VALUES (..., usersEmail, advert_hash, NO, ...)
/**
Send an email with some php code with the URL that would look like this
URL to click on attached to email body:
*/
$attachStringToEmailBody = "http://www.domainname.com/activate-user?email_id=" . $usersEmail . "&hash=" . $randomnessWhateverItsCalled;
enter code here
//Send email from this process page with a little email php code
//Redirect user to a page informing the user to activate the account by visiting their email and clicking on the url
?>
Then in the activate-user.php page I have the following:
<?ph
$user_email = $_GET['email_id'];
$hash = $_GET['hash'];
/**
search database and return a row if there is a match containing both the $user_email and the $hash
if(match){
Update database and set the `account_activated` column to `YES`
}
else{
//Tell if there was no match then activation failed
//Let the user know that we do not recognise the link they used to try and activate their account.
}
*/
?>
It seems secure enough, as long as you made the "randomness" part hard to guess. You can put there the email, username, password, etc. and mix them up with another key - all encrypted - that's what I usually do.
But I would advise you to use 0/1 for active/inactive - why using strings, when you can do the same with smallint (1) - and save some space, thus making the database a bit lighter ?
I'm not sure where to begin with this task, so I'm looking for an answer on just the idea of how to go about doing this.
When a new user creates an account on my Codeigniter site I send him/her an email about signing up (very typical). Here is how I'm sending the email...
...
$subject = 'Welcome to __________, ' . $firstName . '!';
$emailData = array(
'name' => $name,
'blah' => $blah,
'blah' => $blah,
// etc.
);
$html_email = $this->load->view('emails/signup_html_view', $emailData, true);
$text_email = $this->load->view('emails/signup_text_view', $emailData, true);
$this->email->from('team#_________.com', '________ Team');
$this->email->to($to);
$this->email->subject($subject);
$this->email->message($html_email);
$this->email->set_alt_message($text_email);
$this->email->send();
...
As you can see, I'm passing data to those views to send the email. In the email view, at the top, I have a link that says "Problem viewing email? Click here to view it online.". That is common practice for emails on newsletters, signups emails, etc. so that the user can view the email online if it renders weird or something goes wrong.
Where I'm getting lost is how do I generate that unique "...view it online." link so that when the user clicks it, they see an online version of the email and the online version still has all the data still passed to it? Do I need to create a separate controller or what is the best way to handle that? How do I generate that unique link?
#zach,
yes, what you do is:
1) create a separate controller that can display this email, just like you were making a page
2) I'm assuming the user is already created in the db, but is not yet activated or taken steps to be able to login. So, backing up a bit, when you make your user record, also create a random hashtag & store that.
Now, in the email link, set it to www.mysite.com/welcome/hashtag
This way you are allowing them to get a unique record without using an id that they could just use to go look at everyone else
This welcome page, of course, doesn't require them to be logged in. Probably you give them a submit (maybe after they fill out some more info) that will then activate their account
Hope that was close enough to what you were asking to get you through
I have a mailing list form to sign up to a mailing list and input the details into the database. But now I want an admin section where the user can create an email within the website and send it to all the people that have signed up to the mailing list. How can I do this?
Here is my code for originally creating the mailing list:
<?php
// start the session handler
require_once('dbfunction.php');
//connect to database
$conn2 = DB2();
require_once('header.php');
/*
* should we proceed with the form (if page is not submitted to itself echo the form)
*/
if (isset($_POST['submit'])) {
//detect if we have errors or not
$errors = false;
$error_msg = "Error, please try again";
if (!isset($_POST['full_name']) || $_POST['full_name'] == "") {
$errors = true;
echo "<p style='color: red; position: absolute; top:115.5em; right:28em;'>Enter your full name</p>";
}
if (!isset($_POST['email']) || $_POST['email'] == "") {
$errors = true;
echo "<p style='color: red; position: absolute; top:120.1em; right:25.7em;'>Enter an email</p>";
}
$email = $_POST['email'];
//prepare and set the query and then execute it
$stmt = $conn2->prepare("SELECT COUNT(email) FROM maillist WHERE email = ?");
$stmt->bind_param('s',$email);
$stmt->execute();
$stmt->bind_result($count);
while($stmt->fetch()){}
if(!empty($count)){
echo "<p class='red'>Email already registered, please enter an alternative email</p>";
}
else
//if we have no errors, do the SQL
if (!$errors) {
$full_name = $_POST['full_name'];
$full_name = ucfirst($full_name);
//insert data
$stmt = $conn2->prepare("INSERT INTO maillist (billing_name, email) VALUES (?, ?)");
//bind the parameters
$stmt->bind_param('ss', $full_name, $email);
// Execute query
$stmt->execute();
//if the query worked, put out the confirmation message (you can make this look however you want)
if ($stmt) {
echo "<p class='black'>Thank you for joining out mailing list</p>";
//put out the footer and then stop the rest of the script from running, so we don't display the rest of the form (this is after the form has been submitted)
require_once('footer.php');
exit;
}
}
}
Admin Control Panel (ACP) aka Backoffice can be written with php easily.
You can create a new file or folder which will follow the next "logic":
1.Is the member logged-in and has permissions for ACP? (sessions/cookies)
2.If not , print the login form and check for his details.
2.1 If those details exists in your DB admin table - create a cookie or session.
3.If logged in show him the ACP.
There will be an option for the admin to write an email and send it to all of your subscribers. (according to your needs).
So you need to have a simple form with 2 fields: Subject and message (content).
When you submit the form , it will run a php script that will do:
1.Get the data of the form ($_POST['title'] for example)
2.Fetch all the subscribers from the database with a loop (while)
3.And while fetching them , send them an email with the mail function.
Why reinvent the wheel. There are several great services that already do this. They all have an api/functionality that you can use to build your subscriber lists. Plus, you get great reporting and click/link tracking and stats. Creating this functionality yourself would take a lot of effort.
Personally I use use Campaign Monitor - http://www.campaignmonitor.com/. It's rock solid, we've used it to send campaigns of 800,000 emails before :)
Here are the php code examples which enable you to manage list and subscribers:
https://github.com/campaignmonitor/createsend-php
You'd use an external mailing list manager, and send the message to the list address. The external MLM is configured to forward only mail from the web host, and divert everything else to the mailing list administrator. Be sure to test that noone but you can post to the list.
Reinventing the wheel, in PHP nonetheless, is only going to lead to pain, suffering and, in the case of mailing lists, public humiliation. There are just too many things to consider here, for example bounce handling (when an email cannot be delivered, you might want to react and update your database), so stick with an established solution.