Lesson 75 of 158 – User Profile API
75%

User Profile API

A User Profile API is a protected REST API that returns information about the currently authenticated user. In this lesson, we will create a PHP User Profile API using JWT authentication, MySQL, PDO, and a React Native client.

Note: The profile API should identify the user from the verified JWT instead of trusting a user ID sent by the mobile application.

1. What is a User Profile API?

A User Profile API returns information about the currently authenticated user.

React Native
     ↓
JWT Token
     ↓
Profile API
     ↓
Verify JWT
     ↓
Find User
     ↓
Return Profile

2. Why Use a Profile API?

After login, a mobile application often needs to display the user's profile information.

  • User name
  • Email address
  • Phone number
  • Profile image
  • Course information
  • Account information

3. Profile API URL

Suppose our profile API is:

GET /api/user_profile.php

The API will require a valid JWT.

4. HTTP Method

Because the API is retrieving profile information, we use the GET method.

GET /api/user_profile.php

5. Send JWT with Request

The React Native application sends the JWT through the Authorization header.

Authorization:
Bearer YOUR_JWT_TOKEN

6. Set JSON Response Header

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

This tells the client that the API response is JSON.

7. Include Database Connection

The profile API needs access to the database to retrieve the authenticated user's profile.

require_once '../db.php';

The exact path depends on your project structure.

8. Include JWT Library

require_once
    __DIR__ . '/vendor/autoload.php';

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

The Firebase PHP JWT library can be used to verify the JWT.

9. JWT Secret Key

$secretKey =
    "YOUR_SECURE_SERVER_SECRET";
Important: Keep the secret key on the server. Do not send it to React Native.

10. Read Authorization Header

$authorization =
    $_SERVER['HTTP_AUTHORIZATION'] ?? '';

if ($authorization === '') {

    http_response_code(401);

    echo json_encode([
        "success" => false,
        "message" => "Token required"
    ]);

    exit;
}

11. Extract JWT

if (
    !preg_match(
        '/Bearer\s+(.+)/i',
        $authorization,
        $matches
    )
) {

    http_response_code(401);

    echo json_encode([
        "success" => false,
        "message" =>
            "Invalid authorization header"
    ]);

    exit;
}

$token = trim($matches[1]);

12. Verify JWT

try {

    $decoded = JWT::decode(
        $token,
        new Key($secretKey, 'HS256')
    );

} catch (Throwable $e) {

    http_response_code(401);

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

    exit;
}

13. Get User ID from JWT

The JWT generated during login can contain the user ID in the sub claim.

$userId =
    $decoded->sub ?? null;

The API should use the verified token to determine the authenticated user.

14. Validate User ID

if (!$userId) {

    http_response_code(401);

    echo json_encode([
        "success" => false,
        "message" =>
            "Invalid token payload"
    ]);

    exit;
}

15. Find User in Database

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

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

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

The query uses a prepared statement to safely retrieve the profile.

16. Check User Exists

if (!$user) {

    http_response_code(404);

    echo json_encode([
        "success" => false,
        "message" => "User not found"
    ]);

    exit;
}

17. Return Profile Data

echo json_encode([
    "success" => true,
    "message" =>
        "Profile loaded successfully",
    "user" => $user
]);

The API returns the profile as JSON.

18. Profile JSON Response

A successful response may look like this:

{
    "success": true,
    "message": "Profile loaded successfully",
    "user": {
        "id": 101,
        "name": "Rahul",
        "email": "student@example.com"
    }
}

19. Do Not Return Password

The profile API should never return the user's password or password hash.

For example, avoid:

{
    "id": 101,
    "name": "Rahul",
    "email": "student@example.com",
    "password": "$2y$10$..."
}

Only return fields required by the application.

20. Profile API and Security

  • Require a valid JWT.
  • Verify the JWT before using its claims.
  • Use HTTPS.
  • Use prepared statements.
  • Do not expose passwords.
  • Do not trust a user ID supplied directly by the client.
  • Return only necessary profile information.

21. Why Not Send user_id in URL?

Suppose the mobile application sends:

GET /api/user_profile.php?id=101

If the API trusts this value without checking authentication and authorization, a user might attempt to request another user's profile.

A safer design is to obtain the authenticated user's identity from the verified JWT.

JWT
 ↓
Verified User ID
 ↓
Database
 ↓
Own Profile

22. React Native Fetch Request

const response = await fetch(
    "https://example.com/api/user_profile.php",
    {
        method: "GET",

        headers: {
            "Authorization":
                "Bearer " + token,
            "Accept":
                "application/json"
        }
    }
);

const data =
    await response.json();

console.log(data);

23. Display Profile in React Native

if (data.success) {

    console.log(
        "Name:",
        data.user.name
    );

    console.log(
        "Email:",
        data.user.email
    );
}

The returned profile information can be displayed in a React Native profile screen.

24. Handle 401 Response

if (response.status === 401) {

    console.log(
        "Please login again"
    );

}

A 401 response can indicate that the token is missing, invalid, or expired.

25. Handle 404 Response

If the token is valid but the user record does not exist, the API can return HTTP 404.

http_response_code(404);

echo json_encode([
    "success" => false,
    "message" => "User not found"
]);

26. Complete User Profile API

<?php

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

require_once '../db.php';

require_once
    __DIR__ . '/vendor/autoload.php';

use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$secretKey =
    "YOUR_SECURE_SERVER_SECRET";

try {

    $authorization =
        $_SERVER['HTTP_AUTHORIZATION'] ?? '';

    if (
        !preg_match(
            '/Bearer\s+(.+)/i',
            $authorization,
            $matches
        )
    ) {

        http_response_code(401);

        echo json_encode([
            "success" => false,
            "message" => "Token required"
        ]);

        exit;
    }

    $token = trim($matches[1]);

    $decoded = JWT::decode(
        $token,
        new Key($secretKey, 'HS256')
    );

    $userId =
        $decoded->sub ?? null;

    if (!$userId) {

        http_response_code(401);

        echo json_encode([
            "success" => false,
            "message" =>
                "Invalid token payload"
        ]);

        exit;
    }

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

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

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

    if (!$user) {

        http_response_code(404);

        echo json_encode([
            "success" => false,
            "message" => "User not found"
        ]);

        exit;
    }

    http_response_code(200);

    echo json_encode([
        "success" => true,
        "message" =>
            "Profile loaded successfully",
        "user" => $user
    ]);

} catch (Throwable $e) {

    http_response_code(401);

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

}

?>

27. Profile API Architecture

React Native
      ↓
Profile Screen
      ↓
GET Profile API
      ↓
Authorization Header
      ↓
PHP API
      ↓
Verify JWT
      ↓
Read User ID
      ↓
MySQL
      ↓
Fetch User
      ↓
JSON Response
      ↓
React Native
      ↓
Display Profile

28. Test Profile API with Postman

Step 1: Login through the JWT login API.

POST
http://localhost/api/jwt_login.php

Step 2: Copy the returned JWT.

Step 3: Open:

GET
http://localhost/api/user_profile.php

Step 4: Add the header:

Authorization:
Bearer YOUR_JWT_TOKEN

Step 5: Send the request.

The API should return the authenticated user's profile.

29. Common Profile API Mistakes

  • Not checking the Authorization header.
  • Using an unverified JWT.
  • Trusting user_id directly from the URL.
  • Returning the password hash.
  • Not using prepared statements.
  • Exposing the JWT secret key.
  • Not checking token expiration.
  • Returning too much private information.
  • Not handling 401 responses.
  • Not using HTTPS in production.

30. User Profile API Summary

The User Profile API is a protected endpoint that uses the verified JWT to identify the authenticated user. It retrieves that user's profile from MySQL using PDO and returns safe profile information as JSON. React Native can call this endpoint by sending the JWT in the Authorization header.

React Native
     ↓
Bearer JWT
     ↓
User Profile API
     ↓
Verify JWT
     ↓
Get User ID
     ↓
MySQL
     ↓
Get Profile
     ↓
JSON Response

📌 Key Points

  • A User Profile API returns information about the authenticated user.
  • The profile API should normally be protected with JWT authentication.
  • The API should use the verified JWT to identify the current user.
  • Do not trust a user ID directly from the client for determining identity.
  • Use the sub claim from a verified JWT when it contains the user ID.
  • Use PDO prepared statements for database queries.
  • Never return passwords or password hashes.
  • Return only the profile fields required by the application.
  • HTTP 401 can be used for invalid or missing authentication.
  • HTTP 404 can be used when the authenticated user record does not exist.
  • React Native can call the profile API using Fetch or Axios.
  • The next lesson will cover logout and token invalidation.

🧠 Quick Quiz

Question: How should a protected User Profile API determine which user's profile to return?