Creating a timed validation with PHP and MySQL - php

How would I go about creating a system in which a user must click a link to validate something.
Let us say that on my website, each user has their own folders that are not shared. I want their to be an option for each user on their account page in which they can create a trust with another user to access each others folders. Perhaps by typing in the name of the user in which they want to create a trust with.
So in this case, user Jim types into his create trust input box "Tom", and so a trust needs to be established. I figure, A) There will need to be something that stores Jim's request, B. then assigns it as unverified, C. and finally then sends the vaerification link to Tom. Tom then recieves a message somehow? (not sure yet), perhaps with something to check and see if there are any verification links for Tom? and then Tom clicks the verification link sent to verify that he wants to also establish a trust with Jim. once Tom clicks it, A. tells whatever it is that stored Jim's request that Tom accepted, B. assigns validation as verified C. notifies Jim that Tom's request has been accepted or declined.,
HOWEVER there also needs to be a way to remove the validation storage (whatever it will be) if 24 hours runs up, or Tom declines Jim's request.
Can anyone please help me? :)

Sounds like a good job for a database. When user A requests a share, it is entered in the database as pending. When user B is notified, he can click a link who's script will check the database for the original request, verify that it is within 24 hours, and if so, the database record us updated as accepted or declined. If 24 hours is up, the record is updated as expired.

If you're using a database, this is simple. Just generate some sort of unique ID for each request, and store the request (with status "awaiting response" or similar) in the database, then send an email to Tom with a link to one of your php pages with the unique ID of the request in the querystring.
This way, you can save update the "time accepted" field for the request to whenever Tom clicked the link in his email, and change the status to "accepted".
It is trivial to logically determine if 24 hours have passed, and you can deny access to the trusted share after this time period.

You can define a table wich has the attributes:
-Unique ID
-ID1 (Of Person 1)
-ID2 (Of Person 2)
-Validated State (TRUE OR FALSE)
-Validation Hash MD5(Name(ID1)+RANDOM(100,99999),Name(ID2))
-Date and Time of requested relationship
-Other information pertinent to the system that needs this function...
Then you proceed like you said.
1)On 12/5/2009 at 5:25pm Tom (ID=15) asks Mark(ID=21) to join his network, then your script add the data to the table as follows:
-Unique ID: Assigned automatically by autoincrement
-ID1: 15
-ID2: 21
-Validated: False
-Validation Hash MD5: MD5("Tom".42574."Mark")=bedbcfc6e679be69ff3587f15213c83f
-Date and Time: 12/5/2009 at 5:25pm
-Other information pertinent to the system that needs this function...
Be sure that, before setting the data into database, check for duplicates.
After that, erase all fields wich Date And Time is older than 24 hours =D
2)If no duplicates, Send mail to Mark with a link back to your page, including md5 hash as a Get attribute of the url. Lets sat the page name is validate.php?h=bedbcfc6e679be69ff3587f15213c83f
3)Your script validate.php recieves a request with the get parameter h=bedbcfc6e679be69ff3587f15213c83f
Proceed to chek de db.
If hash exists, and date and time is not older than 24hours, set Validated to true, and send a mail to Tom's email with the info of his new friend.
If hash does not exists, inform it to Mark throught the validation page results.
Ok. Thats all. Hope its usefull to you in some way.

Related

PHP / Mail / MySQL: Email Confirmation for Register

I'm not familiar with PHP / MySQL and Emails. And I'm pretty sure this question has been asked somewhere already, but I cannot find it. So I apologise if this is troubling and thank you in advance!
Is it possible to do something that user has to click on a link in email first before the user is added into database???
And you know how, for some websites, they have a unique web address for each email validation (Shown in red on the picture)? How do they create a webpage that's unique in for every email ?
Picture credited: https://kayako.atlassian.net/wiki/download/attachments/5734920/subs-validation.png?version=1&modificationDate=1291956283000&api=v2
Thank you a lot for the attention! If it's possible, I prefer not having straight scripts that I can copy and paste because I like to find out myself :P But please do give me some hints because I'm totally lost.
If there's anything that's not clear, please tell me, I'll try my best to clarify it!
The Registration process
User fills out a form online with basic details including an email and password, and submits the form to register.php
register.php adds user info to a temporary location, such as a pending_users table which has all the fields the user submitted along with an expiration and an activation_code fields. This code can be any random, impossible to guess value. eg: hash('sha1', mt_rand(10000,99999).md_rand(10000,99999)). Just don't do anything predictable such as hash the current time, or the username
register.php sends an email to the user with a URL that will link to activate.php and that includes the activation code. eg: example.com/activate.php?code=a2ef24... The email should also inform the user of the expiration (1 to 12hrs validity seems ok to me)
When user clicks the link, she triggers a GET request to activate.php. In doing so, the user proves ownership of the email address
activate.php gets the code from the request parameters, eg: $code=$_GET['code']. With that code, the script queries the pending_users table for the record matching that code.
If the code is found, check that it hasn't expired before proceeding. Expiration prevents someone else much later who gets in the user's account from completing the registration.
If the code is valid, capture the user details from the matching record and delete that record from pending_users table.
Write a matching record in the regular users table. Until this is done, the user could not log in because login script only checks the users table, and ignores the pending_users table.
Registration complete.
Security Note I:
For your users' protection, never store passwords in cleartext. When you receive it from the registration form (eg: $_POST['pwd'], do:
$pwd = $_POST['pwd'];
//first validate; it should meet minimum requirements
$pwd_hash = password_hash($pwd, PASSWORD_DEFAULT); // <- the hash gets stored
Later, to verify the password, do:
password_verify($cleartext_pwd, $pwd_hash);
It will return true if the password is correct; false otherwise.
Security Note II:
For your protection, never insert user supplied values directly in your DB queries. This means any value that arrives from the outside. Not just usernames, emails, passwords... but also values that you're getting back from the user such as activation_code above or cookie values or headers (eg User-Agent). Instead, learn to use prepared statements. This will protect you from SQL injection.
Not sure if it's possible to add datas in database after the validation...
When I want to do something like that, I create a data in the users table (or metas users table) like "validate".
If this data is "true", then the user already did the validation and he can use his account. If it's still set on "false", the user didn't validate his account : he can't use it.
With that, you have to make sure the account is validate when the user tries to log in, but it's not a big deal ^^
Hope it's usefull.
Those are not a unique websites, there is only one script validating the registration finalization. The incoming requests (when the user has clicked the link) are routed all to the same script by means of server side "request rewriting", so that the random token value is available as an argument (parameter) to the script execution.
What the script does: it checks if that random token value does exist in the database where it has been generated and stored before when the user actually registered.
The only thing left to do for that script is to remove the confirmation random token and/or set a flag indicating that the registered use has actually confirmed his identify (email address) by clicking the link.
Easy and straight forward. Hard to bypass, since you cannot guess what random token value has been generated for what registered user without receiving the email. However take into consideration that it is trivial for an attacking script to use anonymous email services (one time email addresses) to receive and evaluate such a confirmation request, if the process is known to the attacker.

Qualtrics 3rd Party Add-On Best Practices

I am working with Qualtrics, which is just a web-based survey engine. The request is that, once users finish the survey, they will receive a small prize in the form of a gift code. Since I can't host the prize code data on the Qualtrics platform, my idea was to store the prize codes on a remote server. When the user finishes the survey they will be directed to my server (https), to a PHP script that will give out the prizes. On the surface this is possible, because as one piece of customization they allow to re-direct to a URL upon completion of the survey.
The problems that I am faced with, regarding my PHP script that gives out the prizes are as follows:
1) Make sure visitors have COME FROM the survey and have actually
finished the survey.
2) Only give out 1 prize per participant per survey.
It is difficult to address #1 because it seems like after the survey is complete, you just get a basic re-direct to my site. It would be possible to add GET data to the URL, its very easily readable and doesn't offer security. Even encrypting the GET data doesn't seem feasible because a hacker could just copy the data string once they see it.
The idea I had to address #2 was to check the user's IP address using PHP, and store the address in my DB after a 1-way encryption. This way the IP would be unknown, but I could check for duplicates, only allowing 1 prize per IP.
So the question is, is it even possible to do what I am trying to do with just a simple URL re-direct? Is my idea for addressing #2 acceptable?
Thanks.
There are probably many ways this could be handled. Two that come to mind:
1) At the end of survey, Qualtrics creates an embedded data field called ResponseID which is in the Qualtrics data. You can include the ResponseID in the redirect then have your php script call the Qualtrics REST API, and try to retrieve the response with that ResponseID to make sure it exists.
2) Just before the end of survey, you could do a web service call to a script that creates a unique id, store the id on the server side, and return it to the survey as an embedded data field. Then pass the unique id in your redirect and make sure it matches a unique id you stored.
EDIT based on comment below:
You can add custom parameters to your redirect by piping in parameter values like this:
http://mywebsite.com/myscript.php?rid=${e://Field/ResponseID}
If you are able generate special request parameter for redirect url and make it for every user unique, then you could invent some algorithm, and encrypt user ID with it and pass this ID as parameter in redirect url.

Member gets member: granting points

My site has a recommend to a friend button.
To encourage people to use this functionality I want to reward those who use it with points (points will be redeemed for prizes .. don't know yet).
Ok, so I have this structure:
form.php
Here's where you enter your friend's email and a message to him/her if you want. Also there's a hidden input that will be sending your user id to action.php.
action.php
is where phpmailer does the magic and your message if any and a "visit my site" link (a link to process.php in my site containing your user id) is sent to your friend.
Your friend clicks the link and visits process.php
This file connects to my MySQL database table selects the points the user id sent has, adds 10 more points for the friend recommendation and insert the final points back to the table.
Then there's a :
header("Location: http://www.mysite.com");
so your friend does not see process.php working.
Everything is working great but for:
if your friend keeps clicking the link, he/she will earning points endlessly.
How can I fix that?
Thanks a ton!
Generate a unique token for every e-mail you send and include that token in the url/link inside the e-mail. Also store all the tokens in a database table. When someone clicks the link and visits your site, search for that token and mark it as visited. Only add the 10 points when the token wasn't already marked as visited.
My preferred method for making a process occur only once when they are clicking a link in an email is to have a table something like:
CREATE TABLE friends (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
hash VARCHAR(100),
active TINYINT(1) DEFAULT 1,
[user id's or other associative fields you want]
) TYPE=innodb;
then when i generate the url for email I'll attach a hash to the end so:
http://my.url.com/process.php?hash=[hash]
and store the hash and relative info in the database then when they click the link I use the hash to pull the user id's and do any processing and change active from 1 to 0.
The next time they click the link you would pull the record and if active is set to 0 you just return a page that says "You've already got the points you cheater" :) or something more professional. (I've always wanted to call people out, but the powers that be always stop me)
Let me know if you need further explanation :)
You can keep either the IP or the SessionID on file (perhaps in the database) and check every time someone votes.
If you keep the SessionID they will be able to vote again whenever they reopen the browser. If you keep the IP they will be able to vote again upon IP change, whichever fits your application.
This is how I would do it.

How to do a registration confirmation email which will expires within 24 hr

I have a php registration form but now I want to create a registration confirm email which will send to provided email and expires within 24 hr. and when that link is clicked then registration will be confirmed.
Please anybody help and provide some code.
Thanks in advance.
The idea that's generally used is as follow :
When generating / sending the mail, you include in it a unique identifier (random, hard to guess) -- that identifier is in the link the user has to click on
This means thins link will look like http://www.yoursite.com/validate.php?id=HQGETBDC
At the same time, you record a piece of data in your database, with :
the user's to which the mail has been sent
the unique identifier (to be able to find this record)
the current date / time
when the user clicks the link, he'll visit a page on your server
that page will use the unique identifier (present in the link), to find the relevant record in the database
if that record is more that 24 hours old, the user will not be allowed to validate his account.
In addition, you'll probably want to code something to remove old entries (more than 24 hours and not validated) from your database -- using a cronjob, for instance.
You can store a list of email addresses, confirmation codes, and dates they were sent in a database. When the user tries to run the confirmation you check if the current time is less than 24 hours ago.
Once a day or once a week you run an automated script to delete stale entries.
If you don't use a database you can also use a bunch of text files as an "ad-hoc" database.
Supposing the e-mail only sends a link to an activation page with a key (/activate.php?key=14315515151...), then it is as easy as blacklisting/disabling the key.
If you explained better how your activation system works, it would result in a more precise answeer.
For email verification, you want to provide a token. And since you store that in the database, just save the expiry time too:
db("INSERT INTO confirmtoken ...", $confirm_token, time()+24*3600);
The time()+24*3600 represents a timestamp 24 hours from then.
When the user clicks your confirmation link ../confirm?token=3281nfakjnih98 then simply check if the time hasn't passed:
db("SELECT * FROM confirmtokens WHERE id=? AND maxtime<UNIX_TIMESTAMP()");
These are the steps you need to follow
On registration create a new user and set his status as pending (or similar). Also create a hash to uniquely identify the user. Remember to have a created (or similar) column
Send out a mail with a link that points to your confirmation page. You just need the hash as the identifier
When the user clicks the hash, you can compare the current time with the created column and check whether it falls withing your date range (24 hours)
Normally you would enter a line in a database which has the uid attached to the registration with the date/time it was sent, and a clean up that runs every so often, depending on how busy you expect the site to be.
Therefore, if the link is clicked before 24 hours is up, then its removed and the registration complete, if not, after 24 hours even if the clean up hasnt run its then removed and the user told its expired, if its cleaned up, its already expired and the user can be told it cant be found, this could be because more than 24 hours has elapsed.

How should I handle when a friend ignores someone in a PHP/MySQL app?

I have a table like friends(friendship_id, fid1, fid2, ENUM('pending', 'accepted', 'ignored'). When a user ignores someone's friend request, I want to make sure that they don't get a message saying, "You've been ignored!", but I also want that data logged. Any suggestions on how to approach this?
Obviously the first thing you should do is to not implement any code that would display the You've been ignored! message. This solves most of your issue.
But you have to be a little careful. There is a more subtle issue - your system should behave from the sender's viewpoint in every way as if the user hadn't clicked ignore. That means that if the sender issues a second request and normally your system says "You have already sent a request to this user" then it should continue to display this message even after the recipient has ignored the first request. You need to be careful not to leak out information by changing messages in response to an event that was supposed to be private.
Response to comments:
Do you think it's best to not even send a "You have already sent a request to this user" message in the first place?
I think this is a bit out of scope for this question and is a long discussion in itself so I will only touch upon it here. The answer depends on how your application is implemented. The short answer is: your application should help your users and be intuitive so if the message helps them then add it.
An alternative is that requests expire automatically after one week if there is no reply. Once the current request has expired you can allow the user to make a new request. You might want to consider if ignoring a request means ignoring just that one request or all requests from that user.
I've not really considered how you would distinguish who's ignoring who under my current schema.
Friendship requests are directed relationships. You have a sender and a receiver. Friendships on the other hand are usually (but not always) considered to be undirected relationships. A friendship request will usually have a message associated with it "Hey, remember me? We met in the bar last night!". On the other hand an established friendship does not typically have a message associated with it. So it might make sense to store these different types of relationship in different tables in your database.
How are you distinguishing who ignored who? If one friend ignores the other, then I suppose that ENUM would be changed to 'ignored', and the ignored friend would also become the ignoring friend. You could tell who has ignored you, because you would appear to be ignoring them as well.
Better to put an intermediate table, like ignore(ignorer, ignoree), where the columns are just friend IDs. That way whenever a message, update... whatever, is sent to one friend, the app first checks whether the destination friend is ignoring the source friend.
I implemented this recently in application I'm writing. I actually had two rows in the database. My columns were sourceUserId and destUserId. When someone (person A) sends a request to another person (person B), it automatically inserts a row with A's UserId as the sourceUserId and B's UserId as the destUserId. If they send it again, it notices that the row already exists. To have B approve A, insert B's UserId as the sourceUserId and A's UserId as the destUserId.
My application also had a notification table, so each time someone adds someone else (i.e. the row with A's UserId=sourceUserId and B's UserId=destUserId is successfully inserted), a notification is sent to the destination.
To check if two people are friends, you simply check if the reciprocal rows exist.
Example:
User A sent friend request to user B, user B ignored this request:
User A does not know that his/her request has been ignored. To user A this request status should be seen as 'pending'.
For same 2 users:
Even though user B ignored user A's request, it does not necessarily entail that user B can't try to become friends with user A. Such action should clear previous 'ignore' of user A's request (as if it never happened).
So your table schema is okay. You just have to think about the language and logic of all possible scenarios.

Categories