Lesson 140 of 158 – Project User Login API
89%

Project User Login API

In this lesson, we will create the login API for our Student Management mobile application.

The login API will receive the user's email and password, find the corresponding user in MySQL, verify the password, and prepare the authentication response.

Project Goal: Create a secure PHP login API that verifies registered users and returns safe user information for the React Native application.

1. Login Flow

React Native Login Screen
          ↓
       Axios POST
          ↓
       PHP API
          ↓
    Find User by Email
          ↓
   Verify Password
          ↓
     Create Response
          ↓
      React Native

JWT authentication will be added to the login process in the next project lesson.

2. Login API Endpoint

Create a PHP file named:

login.php

The mobile application will send:

POST /api/login.php

3. Login Request Data

The React Native application will send email and password as JSON.

{
    "email": "rahul@example.com",
    "password": "secret123"
}

4. Set JSON Response Header

header(
    "Content-Type: application/json"
);

This tells the client that the API response is JSON.

5. Database Connection

require_once '../config/database.php';

The PHP API will use the PDO connection created for the student_management database.

6. Allow Only POST Requests

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {

    http_response_code(405);

    echo json_encode([
        "success" => false,
        "message" => "Method not allowed"
    ]);

    exit;
}

Login creates an authentication response, so POST is appropriate.

7. Read JSON Input

$input = json_decode(
    file_get_contents("php://input"),
    true
);

The JSON request body is converted into a PHP associative array.

8. Get Email and Password

$email = trim($input['email'] ?? '');
$password = $input['password'] ?? '';

The null coalescing operator prevents errors when fields are missing.

9. Validate Required Fields

if ($email === '' || $password === '') {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" => "Email and password are required"
    ]);

    exit;
}

10. Validate Email Format

if (!filter_var(
    $email,
    FILTER_VALIDATE_EMAIL
)) {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" => "Invalid email address"
    ]);

    exit;
}

11. Find User by Email

The API should find the registered user using a prepared statement.

$stmt = $pdo->prepare(
    "SELECT id, name, email, password, role
     FROM users
     WHERE email = ?"
);

$stmt->execute([$email]);

$user = $stmt->fetch(PDO::FETCH_ASSOC);

12. User Not Found

If no user is found, the login should fail.

if (!$user) {

    http_response_code(401);

    echo json_encode([
        "success" => false,
        "message" => "Invalid email or password"
    ]);

    exit;
}

A generic message is preferable to revealing whether a particular email address exists.

13. Password Verification

The stored password is a hash. We should use password_verify() to compare the submitted password with that hash.

if (!password_verify(
    $password,
    $user['password']
)) {

    http_response_code(401);

    echo json_encode([
        "success" => false,
        "message" => "Invalid email or password"
    ]);

    exit;
}

14. Authentication Success

At this point:

Email exists
      +
Password is correct
      ↓
Authentication successful

The next step is to create a safe response for the mobile application.

15. Safe User Data

We can return information such as:

id
name
email
role

The password hash must never be included in the API response.

16. Successful Login Response

http_response_code(200);

echo json_encode([
    "success" => true,
    "message" => "Login successful",
    "data" => [
        "id" => $user['id'],
        "name" => $user['name'],
        "email" => $user['email'],
        "role" => $user['role']
    ]
]);

17. Login Response Example

{
    "success": true,
    "message": "Login successful",
    "data": {
        "id": 1,
        "name": "Rahul Kumar",
        "email": "rahul@example.com",
        "role": "user"
    }
}

JWT authentication will later add a token to this response.

18. Failed Login Response

{
    "success": false,
    "message": "Invalid email or password"
}

The same generic message can be used for an unknown email or an incorrect password.

19. HTTP Status Codes

Status Meaning
200 Login successful
401 Invalid authentication credentials
422 Invalid request data
405 Method not allowed
500 Server error

20. Complete PHP Login API

<?php

header(
    "Content-Type: application/json"
);

require_once '../config/database.php';

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {

    http_response_code(405);

    echo json_encode([
        "success" => false,
        "message" => "Method not allowed"
    ]);

    exit;
}

$input = json_decode(
    file_get_contents("php://input"),
    true
);

$email = trim($input['email'] ?? '');
$password = $input['password'] ?? '';

if ($email === '' || $password === '') {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" =>
            "Email and password are required"
    ]);

    exit;
}

if (!filter_var(
    $email,
    FILTER_VALIDATE_EMAIL
)) {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" => "Invalid email address"
    ]);

    exit;
}

try {

    $stmt = $pdo->prepare(
        "SELECT id, name, email, password, role
         FROM users
         WHERE email = ?"
    );

    $stmt->execute([$email]);

    $user = $stmt->fetch(
        PDO::FETCH_ASSOC
    );

    if (!$user ||
        !password_verify(
            $password,
            $user['password']
        )) {

        http_response_code(401);

        echo json_encode([
            "success" => false,
            "message" =>
                "Invalid email or password"
        ]);

        exit;
    }

    http_response_code(200);

    echo json_encode([
        "success" => true,
        "message" => "Login successful",
        "data" => [
            "id" => $user['id'],
            "name" => $user['name'],
            "email" => $user['email'],
            "role" => $user['role']
        ]
    ]);

} catch (PDOException $e) {

    error_log($e->getMessage());

    http_response_code(500);

    echo json_encode([
        "success" => false,
        "message" => "Server error"
    ]);
}

21. React Native Login State

const [email, setEmail] =
    useState("");

const [password, setPassword] =
    useState("");

const [loading, setLoading] =
    useState(false);

These states can be connected to TextInput controls and a login button.

22. Login Request Interface

interface LoginRequest {
    email: string;
    password: string;
}

This interface describes the JSON data sent to the login API.

23. Login Response Interface

interface LoginResponse {
    success: boolean;
    message: string;
    data?: {
        id: number;
        name: string;
        email: string;
        role: string;
    };
}

Later, a JWT token property will be added to the response interface.

24. Axios Login Request

const response =
    await api.post<LoginResponse>(
        "/login.php",
        {
            email,
            password
        }
    );

console.log(response.data);

The Axios request sends the login credentials to the PHP API.

25. Handling Login Success

if (response.data.success) {

    const user =
        response.data.data;

    console.log(user);

    // Navigate to student screen

}

Once the login is successful, the application can navigate to the authenticated part of the application.

26. Handling Login Failure

try {

    const response =
        await api.post<LoginResponse>(
            "/login.php",
            {
                email,
                password
            }
        );

} catch (error) {

    console.log(
        "Login failed"
    );

}

A reusable Axios error handler can later display API validation or authentication messages.

27. Testing Login with Postman

Test the login API before connecting it to React Native.

Method: POST

URL:

https://example.com/api/login.php

Body → raw → JSON:

{
    "email": "rahul@example.com",
    "password": "secret123"
}

A valid user should receive HTTP 200 with safe user information.

28. Login Security

  • Use HTTPS in production.
  • Never store plain passwords.
  • Use password_verify() for password checking.
  • Use prepared SQL statements.
  • Do not return password hashes.
  • Use generic invalid credential messages.
  • Do not expose database errors to the client.
  • Validate input on the server.
  • Do not put passwords in URLs.

29. Login Process Before JWT

Login Screen
      ↓
Email + Password
      ↓
Axios POST
      ↓
PHP login.php
      ↓
Find User
      ↓
password_verify()
      ↓
Authentication Success
      ↓
User JSON
      ↓
React Native

In the next lesson, we will improve this flow by generating a JWT after successful authentication.

30. Login API Project Summary

The login API is responsible for verifying the identity of a registered user.

  • React Native sends email and password.
  • Axios sends a POST request to PHP.
  • PHP validates the request.
  • The user is searched by email.
  • password_verify() checks the password.
  • Invalid credentials return HTTP 401.
  • Successful login returns HTTP 200.
  • Password information is never returned.
  • The next step is JWT authentication.

After JWT is added, the mobile application will be able to access protected student APIs securely.

📌 Key Points

  • Login should use the HTTP POST method.
  • JSON input can be read using php://input.
  • The API should find the user using a prepared statement.
  • password_verify() checks the submitted password against the stored hash.
  • Invalid credentials should return HTTP 401.
  • Successful login can return HTTP 200.
  • Never return the password or password hash.
  • React Native can use Axios to call the login API.
  • TypeScript interfaces can define login requests and responses.
  • JWT authentication will be added in the next project lesson.

🧠 Quick Quiz

Question: Which PHP function should be used to verify a user's submitted password against the stored password hash?