PHP Password Reset by Email

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video you'll learn how to develop  functionality that lets a user reset their own   password if they forget it we'll be building on  code created in the first video where we developed   sign up and login functionality so if you haven't  seen that yet there's a link in the description   all the codes developed in this video is  freely available and a link to that is also   in the description so how is this going to work  what happens when a user forgets their password   they could ask us to email it to them but we can't  do that because we don't know it passwords are   stored as hashes in the database we deliberately  have no way of getting to the plain text password   any website that sends you a password if  you forget it is storing them in plain   text so be very careful with that site  we could create a new password for them   either manually or programmatically email it  to them and then save the hash in the database   but unless they think of the password  themselves they're more likely to forget it   also it will be extra work for us if we  had to do it manually much better if we   could give the users the option to securely  reset their own password when they forget it   so how do we do that well we could have a reset  form where the user enters their email address   and a new password but this would clearly allow  anyone to change any user's password which would   be ridiculous so we can't do that if we assume  though that the user is the only one with access   to their email account then we can use that to  reset their password if we generate a unique URL   in other words one that contains a unique token  like this we can send them this URL in an email   when they open the link in the email they're taken  to a form where they can reset their password this   form will identify the user using the unique token  from the URL which is linked to their user account   in the database using a hash of that token so the  user can securely change their own password and   only their own password to whatever they're like  meaning they're less likely to forget it again   we'll start with the sign up and login  code from the end of the previous video   if you need this you can get it in this  Repository first let's create the page   where the user can provide their email address  to start the password reset process so let's   create a new file in the root folder called forgot  password.php in here we need the HTML for the form   to do this we'll just copy the start of the HTML  from the index page and paste it in the forgot   password file you might want to extract this  out into a separate header file you can include   on each page but in the interests of keeping  this video and the code as simple as possible   I'll just copy and paste it like this in this  code let's change the title element then add a   heading element and the closing body and HTML tags  then let's add a form that uses the post method   inside the form We'll add an email input  with an Associated label and a submit button in the login.php script after the  form let's add a link to this page in the browser on the login page There's the link  and there's the forgot password page with its form   next let's add a script that will  process this form when it's submitted   so let's add a new file called send password  reset.php we'll start this script with the   PHP opening tag then let's get the value  of the email that was supplied in the form back in the forgot password page  let's add an action attribute to   the farm so that the farm will  submit its data to this new page in this script we'll generate a unique  token store it in the database and send   the user an email with a link  that contains the token value before we add code to do that let's add fields  in the database to store the token value   in the user table let's add two columns  we'll call the First Column reset token hash   this will be a 64 character voucher that accepts  null values and has a default value of null   we'll also specify a unique index on this column  as we'll be using this column in a where clause   we'll call the other column reset token expires at  this will be a date time type that also accepts no   values and has a default value of null let's click  save and there are the new columns and the index a script containing the SQL  to add these columns is in   the code repository for this video  and the link is in the description in the send password reset page first  let's generate a random token value   we'll use the random byte function for this  passing in 16 as the length we need this   token to contain characters we can include in  a URL though the random bytes function returns   unprintable characters so let's use the bin to hex  function to convert this to a hexadecimal string   as with the password for extra security we'll  store a hash of this token in the database   instead of the plain value so let's create a  hash of this value using the sha-256 algorithm   this returns a 64 character string which is why  the column we added to the database is that length   next let's generate an expiry for this token  so that's a Brute Force attack can't be used   to guess a valid token value will make  the token only be valid for a short time   if it does expire then the user can just request  a new one the time function Returns the current   time represented as a number of seconds so  let's add 60 times 30 to this which is the   number of seconds in 30 minutes meaning that  the token will only be valid for 30 minutes   you can of course change this amount of time  if you prefer then to get a value we can store   in the date time column in the database we'll use  the date function passing in a format string that   represents the format the date time values taken  in the database four digit year month then day   separated by hyphens then the hour minutes  and seconds of the time separated by colons   now we have the token hash and its expiry we can  store them in the database so first let's require   the database file we developed in the previous  video assigning its return value to a variable   then let's write the SQL to save the token  to the database we'll use an update query   to update the user table setting the token hash  and the token expiry columns to the values above   to avoid an SQL injection attack  we'll use a mysqli prepared statement   so for the values in the SQL we'll  just put question marks as placeholders   to identify the row we want to update we'll add  a where clause on the email column again using a   placeholder for its value then let's prepare  the statement then we can bind values to the   placeholders using the bind param function all  the values are strings so we'll pass in three   s characters for the three string parameters  then the values in order of the token hash it's   expiry and the email address once we've  done this we can execute the statement let's give that a try on the forgot password  page I'll enter the email address of a user   that I know exists in the database and  submit the form the blank response is to   be expected as we aren't outputting anything  yet in the database for the record with that   email address we can see the reset token hash and  the reset token expires at columns have been set this worked because a record was found that  matched the email address supplied in the form   however if no record is found that matches  the supplied email address then no records   will be updated we can check for this with the  affected rows property of the mysqli connection   this is an integer containing the  number of rows that were updated   if a record was updated this means a record  with the supplied email address was found   so now we can send an email to  this address containing the token to send an email from PHP we'll use the phpmailer  library and you'll need access to an SMTP server   I have already gone into detail on how to do this  in another video there's a link in the description   we'll install the phpmailer package using composer   with this command in the terminal  from the root folder of the code this will install the package  into the vendor folder   as with the database code let's put the  email configuration code in a separate file   so let's create a new file called mailer.php  in here we'll start with the PHP opening tag to use the phpmailer package we need  to require the files the classes are in   you can do this directly as described here in  the phpmailer documentation or use composer's   autoloader which does this automatically  we can also include some U statements so   we can use phpmailers classes without  having to include their full namespace   so let's add some U statements to input  phpmailis classes into the current namespace   then we'll require composer's autoloader to  load the class files then let's create a new   PHP mailer object passing in true to enable  exceptions we'll be using an SMTP server   with authentication so we'll call the is SMTP  method and set the SMTP auth property to true   then we'll configure the SMTP server you  need to set the host authentication type   which is probably TLS the port username and  password to those that your SMTP server uses   note that in practice you'd probably put these  values in a separate configuration file like a   DOT end file but for the purposes of keeping this  video simple we'll just hard code these in here   one more setting we need to change is to  enable HTML content in emails by calling   the is HTML method passing in true finally  in this script we'll return the mail variable then back in the send password  reset script we can use this script   so if the email address was found and there was  a row updated we'll load the mailer script we   just created assigning the return value  of the require statement to a variable then we can set the properties on the mailer  object for the message we're going to send   we'll call the set from method to  set the email address of the sender   this is typically set to a no reply  email address at your domain name   then we'll add the recipient email address which  is the email address that the user has supplied   then we'll set the email subject and the body  using a hear doc for the content of the email   we'll just specify a link to a file that we'll  create shortly note that this needs to be an   absolute URL you can't use a relative URL as  the link will be clicked on in an email client   the host name needs to be set to the hostname of  your web server for example localhost if you're   developing locally to send the token to the user  we'll include it in this URL in the query string   then we can send the email using the send  method if this doesn't work an exception   will be thrown so let's wrap this in a try  catch block and output the error details if so note that if you do have issues sending  emails here in the mailer script you can   enable verbose debugging messages by setting the  SMTP debug property to the debug server constant   once the problem is resolved though make  sure you remove this line or comment it out back in the send password reset script once  the message has been sent let's just output a   message for now note that we're doing this at  the end of the script after the if block that   checks if any rows were updated or not this  means that if the email address supplied by   the user wasn't found we'll display this message  anyway you could output a message saying that the   email address wasn't found but it's typical to not  do this and just say the message was sent anyway   this is an additional little bit  of security that prevents someone   from using this script to discover which  email addresses are valid on your system let's give that a try I'll enter an email  address into the Forgotten password form   note that I'm using an example email address  for this demonstration you need to submit an   email address for which you have access to the  inbox so that you can see the email that was sent   if I submit the form we get the  message that the email was sent   in the email client there's the email with the  sender subject and content that we specified at the end of the send password  reset script instead of just   outputting a message like this it will  be better to redirect to another page   just as we're doing in the process signup  script when the sign up is successful   I'll keep it simple however and just leave this  message but I recommend you do add a similar   success page now we have the email with the  token we can add the script that processes it   so let's add the file that we're linking to  in the email body called reset password.php   in here we'll start with the PHP opening tag  the first thing we want to do in here is get   the token from the query string then we can  check if it's valid as the token is stored in   the database as a hash before we can query the  database for this value we need to get its hash   then we can use this value to see if there's  a record in the user table that contains it   so let's get a database Connection by requiring  the database script then let's write the SQL   to select the user record with a where class on  the reset token hash column we'll use a prepared   statement for this so we'll include a question  mark as a placeholder for the value then we can   prepare the statement bind the value of the  token hash to the placeholder and execute it then let's get the result set and an associative  array of the user record if it was found if no   record was found this will be null so let's check  for that and stop the script with a message if so   even if a record that contains the token  hash is found it might have expired   to check for this we'll use the string to  time function to convert the reset token   X bisap column value to a number of seconds if  this has expired then it will be less than or   equal to the current time expressed as a number  of seconds which we can get with the time function   if this is true then the token has expired  so we'll stop the script with a message   next for now let's just  print out a temporary message let's give that a try if I click on the link  in the email we just sent we get the message   saying the token is valid as the token  is in the query string we can change it   so let's change this value and then we get  the message saying the token wasn't found to test the expiration in the database let's   change the expiration date of this  token to a date and time in the past if we go back now we get the  token has expired message instead of showing this message saying the  token is valid we'll display a form that   lets the user change their password so we'll add  the PHP closing tag and create an HTML document   we'll start with the head section including the  link to the style sheet from the other pages   in the body section We'll add a header and a form   we'll add this process reset password.php script  referred to in the action attribute shortly   inside the form let's add a hidden field  for the token value so we can get it in   the script that handles this form we'll escape  the token value as it is untrusted input then an   input and Associated label for the password  and likewise for the password confirmation finally a button to submit the form  and the farm body and HTML closing tags in the browser if we have a valid token we see  the form with its two fields and the submit button then we can add the script that will  process this form when it's submitted   so we'll add a new file called  processresetpassword.php in here before we validate the  supplied password and update   it in the database we still need  to check that the token is valid   this will divide someone bypassing  the check we just added to the form to keep it simple in the reset  password.php script let's just   copy these checks from the top and paste  them in the process reset password script   the only difference is that now however we'll  be getting the token value from the posted form   data instead of the query string so we'll get this  value from the post array instead of the get array   once we know the token is valid we  can validate the data from the form   in the process signup script we're validating  the password and its confirmation then we're   creating the hash of the supplied password  so let's copy these lines and paste them in   the process reset password script this is the  required server-side validation for this data   if you want to include client-side  validation for the password then you   can get this from the original signup  form we developed in the previous video let's give that a try so if I submit an  invalid password we get the validation messages   once all is valid we can update the password  in the database so let's create some SQL to   do that using placeholders for the password  hash and ID fields now that we no longer need   them let's also set the reset token hash and  reset token expires at columns to null then we   can prepare the statement and bind values of the  password hash and the user's ID to the parameters   then we can execute the statement finally  let's just output a message as before it   would be better at this point to redirect to  another page that said this where you could   even include a link to the login page but to keep  this video simple I'll just leave this message let's give that a try from the top we'll go to the  forgot password page and submit an email address we get an email with a link  to the password reset page   if I click on that we can enter a new password in the database we can see that the reset token   hash and reset token expires at columns  have been set to null for that record now if we go to the login page we  can log in with the new password there's a link to all the code shown in this video   in the description along with links to  sites shown and relevant documentation   please don't forget to like comment and  subscribe and as always thank you for watching
Info
Channel: Dave Hollingworth
Views: 30,558
Rating: undefined out of 5
Keywords:
Id: R9bfts9ZFjs
Channel Id: undefined
Length: 20min 56sec (1256 seconds)
Published: Tue Jun 27 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.