React JS and PHP Restful API User Authentication for Login and Signup.
Wall Script
MailxEngine
Follow Me:
Monday, October 23, 2017

React JS and PHP Restful API User Authentication for Login and Signup.

Here is the continued article on my previous post for creating a welcome with login and logout using ReactJS. Today’s post explains how to implement login authentication system for your React JS applications. It will show you how to log in with a user and store the user session, so it deals with token-based authentication. Since we are using token-based authentication, it protects if any unauthorized request is made and notices for a new login if required. This makes your application’s authentication to be more secure compared with any other authentication system. Every user details will be stored in an external database and a PHP based API is used in the backend for handling this authentication. Hope you’ll find it more easily using this as your authentication system in your ReactJS projects. Let’s look into the live demo and follow the below code.

React JS and PHP Restful API User Authentication for Login and Signup.


Live Demo


Video Tutorial
ReactJS User Restful Authentication for Login and Signup


Database Design
To build the user feed system, you have to create two tables such as Users and Feed. You can check my previous tutorials for creating token-based API system.

Users
User table contains all the users registration details.
CREATE TABLE users(
user_id int AUTO_INCREMENT PRIMARY KEY,
username varchar(50),
password varchar(300),
name varchar(200),
email varchar(300));

Feed
This table contains user daily updates.
CREATE TABLE feed(
feed_id int PRIMARY KEY AUTO_INCREMENT,
feed text,
user_id_fk int
);

Download PHP Restul Project
$git clone https://github.com/srinivastamada/PHP-Slim-Restful.git

welcome.js
As explain in previous tutorial, just include Login and Signup component links.
import React, {Component} from 'react';
import './Welcome.css';

class Welcome extends Component {
render() {
return (
<div className="row " id="Body">
<div className="medium-12 columns">
<h2 id="welcomeText">Make people fall in love with your ideas</h2>
<a href="/login" className="button">Login</a>
<a href="/signup" className="button success">Signup</a>
</div>
</div>
);
}
}
export default Welcome;


Step 1 - Login.js
Designing Login component, here just include HTML for login form. Created constructor function with super properties for intitiating global this
import React, {Component} from 'react';
import './Login.css';
class Login extends Component {
constructor(){
super();
};
}

render() {
return (
<div className="row" id="Body">
<div className="medium-5 columns left">
<h4>Login</h4>
<label>Username</label>
<input type="text" name="username" placeholder="Username" />
<label>Password</label>
<input type="password" name="password" placeholder="Password" />
<input type="submit" className="button success" value="Login" />
<a href="/signup">Registration</a>
</div>
</div>
);
}
}
export default Login;

Step 2 - Login.js
In constructor function defined the state object for changing input fields. Login() function will communicate with RESTful API and onChange function set the state value based on the user input value.
import React, {Component} from 'react';
import './Login.css';
class Login extends Component {

constructor(){
super();
this.state = {
username: '',
password: '',
redirectToReferrer: false
};
this.login = this.login.bind(this);
this.onChange = this.onChange.bind(this);
}
login() {
//API Action Here
}

onChange(e){
this.setState({[e.target.name]:e.target.value});
}

render() {
return (
<div className="row" id="Body">
<div className="medium-5 columns left">
<h4>Login</h4>
<label>Username</label>
<input type="text" name="username" onChange={this.onChange}/>
<label>Password</label>
<input type="password" name="password" onChange={this.onChange}/>
<input type="submit" value="Login" onClick={this.login}/>
<a href="/signup">Registration</a>
</div>
</div>
);
}
}
export default Login;


PostData.js
In src/service create an export class for fetching RESTful calls and returns Promise.
export function PostData(type, userData) {
let BaseURL = 'https://api.thewallscript.com/restful/';
//let BaseURL = 'http://localhost/PHP-Slim-Restful/api/';
return new Promise((resolve, reject) =>{
fetch(BaseURL+type, {
method: 'POST',
body: JSON.stringify(userData)
})
.then((response) => response.json())
.then((res) => {
resolve(res);
})
.catch((error) => {
reject(error);
});
});
}


Final Login.js
Imported Redirect and PostData components. Login function set the state redirtion value to true, one the API is succesful. Based on the state.redirection value, the page will redirect to the home page.
import React, {Component} from 'react';
import {Redirect} from 'react-router-dom';
import {PostData} from '../../services/PostData';
import './Login.css';
class Login extends Component {
constructor(){
super();
this.state = {
username: '',
password: '',
redirectToReferrer: false
};
this.login = this.login.bind(this);
this.onChange = this.onChange.bind(this);
}

login() {
if(this.state.username && this.state.password){
PostData('login',this.state).then((result) => {
let responseJson = result;
if(responseJson.userData){
sessionStorage.setItem('userData',JSON.stringify(responseJson));
this.setState({redirectToReferrer: true});
}
});
}
}

onChange(e){
this.setState({[e.target.name]:e.target.value});
}
render() {

if (this.state.redirectToReferrer || sessionStorage.getItem('userData')){
return (<Redirect to={'/home'}/>)
}

return (
<div className="row" id="Body">
<div className="medium-5 columns left">
<h4>Login</h4>
<label>Username</label>
<input type="text" name="username" onChange={this.onChange}/>
<label>Password</label>
<input type="password" name="password" onChange={this.onChange}/>
<input type="submit" value="Login" onClick={this.login}/>
<a href="/signup">Registration</a>
</div>
</div>
);
}
}
export default Login;

PHP
This code contains login ang sigup function with PDO MySQL connetion and it works with Slim framework. Download this project from GitHub.
<?php
require 'config.php';
require 'Slim/Slim.php';

\Slim\Slim::registerAutoloader();
$app = new \Slim\Slim();

$app->post('/login','login'); /* User login */
$app->post('/signup','signup'); /* User Signup */
$app->post('/feed','feed'); /* User Feeds */
$app->post('/feedUpdate','feedUpdate'); /* User Feeds */
$app->post('/feedDelete','feedDelete'); /* User Feeds */
//$app->post('/userDetails','userDetails'); /* User Details */

$app->run();

/************************* USER LOGIN *************************************/
/* ### User login ### */
function login() {
    $request = \Slim\Slim::getInstance()->request();
    $data = json_decode($request->getBody());
    try {
       $db = getDB();
       $userData ='';
       $sql = "SELECT user_id, name, email, username FROM users WHERE (username=:username or email=:username) and password=:password ";
      $stmt = $db->prepare($sql);
      $stmt->bindParam("username", $data->username, PDO::PARAM_STR);
      $password=hash('sha256',$data->password);
      $stmt->bindParam("password", $password, PDO::PARAM_STR);
      $stmt->execute();
      $mainCount=$stmt->rowCount();
      $userData = $stmt->fetch(PDO::FETCH_OBJ);
if(!empty($userData))
{
     $user_id=$userData->user_id;
     $userData->token = apiToken($user_id);
}
    $db = null;
if($userData){
   $userData = json_encode($userData);
   echo '{"userData": ' .$userData . '}';
} else {
   echo '{"error":{"text":"Bad request wrong username and password"}}';
}

}
catch(PDOException $e) {
echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}


/* ### User registration ### */
function signup() {
   $request = \Slim\Slim::getInstance()->request();   
   $data = json_decode($request->getBody());
   $email=$data->email;
   $name=$data->name;
   $username=$data->username;
   $password=$data->password;
   try {
       $username_check = preg_match('~^[A-Za-z0-9_]{3,20}$~i', $username);
       $email_check = preg_match('~^[a-zA-Z0-9._-][email protected][a-zA-Z0-9._-]+\.([a-zA-Z]{2,4})$~i', $email);
      $password_check = preg_match('~^[[email protected]#$%^&*()_]{6,20}$~i', $password);
     
    if (strlen(trim($username))>0 && strlen(trim($password))>0 && strlen(trim($email))>0 && $email_check>0 && $username_check>0 && $password_check>0)
   {
    $db = getDB();
    $userData = '';
    $sql = "SELECT user_id FROM users WHERE username=:username or email=:email";
    $stmt = $db->prepare($sql);
    $stmt->bindParam("username", $username,PDO::PARAM_STR);
    $stmt->bindParam("email", $email,PDO::PARAM_STR);
    $stmt->execute();
   $mainCount=$stmt->rowCount();
   $created=time();
   if($mainCount==0)
  {
    /*Inserting user values*/
     $sql1="INSERT INTO users(username,password,email,name)VALUES(:username,:password,:email,:name)";
      $stmt1 = $db->prepare($sql1);
      $stmt1->bindParam("username", $username,PDO::PARAM_STR);
      $password=hash('sha256',$data->password);
      $stmt1->bindParam("password", $password,PDO::PARAM_STR);
      $stmt1->bindParam("email", $email,PDO::PARAM_STR);
      $stmt1->bindParam("name", $name,PDO::PARAM_STR);
      $stmt1->execute();
      $userData=internalUserDetails($email);
      }
      $db = null;

if($userData){
      $userData = json_encode($userData);
      echo '{"userData": ' .$userData . '}';
} else {
      echo '{"error":{"text":"Enter valid data"}}';
}

}
else{
      echo '{"error":{"text":"Enter valid data"}}';
}
}
catch(PDOException $e) {
      echo '{"error":{"text":'. $e->getMessage() .'}}';
}
}
?>

Was this article helpful?
Thanks! Your feedback helps us to improve 9lessons.info


10 comments:

  1. Wow nice and informative article sir thanks for sharing

    ReplyDelete
  2. please show structure file json https://api.thewallscript.com/restful/

    ReplyDelete
  3. how to run this project,i try run with npm. this project can be run but login and registration dosen't work

    ReplyDelete
  4. if we need to call with headers in API call with some token value? What will be the call?

    ReplyDelete
  5. how to configure Slim framework set content type, As i am getting an error 400 of not setting up content type?

    ReplyDelete
  6. Thank you for these tutorial sir,for me delete response showing in react positively but when i checked in mysql feed is not deleted.

    ReplyDelete
  7. Hmmmm, your code is just comparing if the tokens match, which to me is not "secure" because anybody can easily get the token value base on the response from the API and use it to submit a JSON data to the API using the token value and exactly the same request headers.

    ReplyDelete

Make in India