Skip to content

Latest commit

 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

Token-Authenticated Library Management System

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Token Management
  5. Project Information

About the Project

The Library Management System offers a reliable and streamlined solution for managing books, authors, users, and their associations. It supports comprehensive CRUD functionality for users (including registration, authentication, retrieval, updates, and deletion), as well as for books, authors, and their relationships. Secure access is ensured through token-based authentication, which includes validation and usage tracking to limit actions to authorized users. A dedicated book-author relationship table provides enhanced flexibility by effectively linking books with their authors. The system is designed to simplify library data management while prioritizing robust security measures.

(back to top)

Getting Started

Prerequisites

  • XAMPP
  • SQLyog (optional, can use phpMyAdmin)
  • Composer
  • Node.js
  • PHP (version 7.2 or higher)
  • Slim Framework
  • JWT PHP Library
  • ThunderClient

Installing

  1. Clone the Repository

    git clone https://github.com/github_username/library_4a.git
    cd /path/to/xampp/htdocs/library_4a
    
  2. Install Dependencies

    • Use Composer to install PHP dependencies:
    composer install
    
  3. Set Up Database

    • Open SQLyog or phpMyAdmin and create a new database called library.
    • Run the following SQL queries to create the required tables:
    CREATE TABLE users (
        userid INT(9) NOT NULL AUTO_INCREMENT,
        username CHAR(255) NOT NULL,
        password TEXT NOT NULL,
        PRIMARY KEY (userid)
    );
    
    CREATE TABLE authors (
        authorid INT(9) NOT NULL AUTO_INCREMENT,
        name CHAR(255) NOT NULL,
        PRIMARY KEY (authorid)
    );
    
    CREATE TABLE books (
        bookid INT(9) NOT NULL AUTO_INCREMENT,
        title CHAR(255) NOT NULL,
        PRIMARY KEY (bookid)
    );
    
    CREATE TABLE books_authors (
        collectionid INT(9) NOT NULL AUTO_INCREMENT,
        bookid INT(9) NOT NULL,
        authorid INT(9) NOT NULL,
        PRIMARY KEY (collectionid)
    );
    
    CREATE TABLE used_tokens (
        token VARCHAR(512) PRIMARY KEY,
        used_at DATETIME NOT NULL
    );
  4. Configure Database Connection

    • Edit the connection details in index.php as follows:
    <?php
    $servername = "localhost";
    $username = "root";
    $password = "password";
    $dbname = "library";
    ?>

    Replace these values with your actual database settings to connect to the library database.

  5. Start XAMPP Server

    • Ensure that both Apache and MySQL are running in the XAMPP control panel.
  6. Testing the Application

    • You can now use API testing tools like Postman or Thunder Client to test the CRUD operations and authentication endpoints.

(back to top)

Usage

1. User Endpoints

a. User Registration - Registers a new user with a unique username and a hashed password.

  • Endpoint: /user/register

  • Method: POST

  • Sample Payload:

    {
      "username": "uniqueUser",
      "password": "uniquePassword"
    }
  • Expected Response:

    • Success:

      {
        "status": "success",
        "data": null
      }
    • Failure:

      {
        "status": "fail",
        "data": {
          "title": "<Error Message Here>"
        }
      }

b. User Authentication - Authenticates a user and generates a JWT token.

  • Endpoint: /user/authenticate

  • Method: POST

  • Sample Payload:

    {
      "username": "existingUser",
      "password": "uniquePassword"
    }
  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": null
      }
    • Failure:

      {
        "status": "fail",
        "data": {
          "title": "Authentication Failed"
        }
      }

c. Display Users - Retrieves a list of all users in the system; requires a valid token.

  • Endpoint: /user/display

  • Method: GET

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": [
          {
            "userid": 1,
            "username": "username"
          }
        ]
      }
    • Failure: Token Already Used

      {
        "status": "fail",
        "data": {
          "title": "Token has already been used"
        }
      }
    • Failure: Invalid or Expired Token

      {
        "status": "fail",
        "data": {
          "title": "Invalid or expired token"
        }
      }

d. Update User Information - Updates the user's username and/or password; requires a valid token.

  • Endpoint: /user/update

  • Method: PUT

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Sample Payload:

    {
      "username": "updatedUser",
      "password": "newUniquePassword"
    }
  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": null
      }
    • Failure: If the new username is taken, if there’s nothing to update, or if the token is invalid, expired, or already used, an appropriate error message.

e. Delete User - Deletes the authenticated user’s account from the system; requires a valid token.

  • Endpoint: /user/delete

  • Method: DELETE

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Expected Response:

    • Success:

      {
        "status": "success",
        "data": null
      }
    • Failure: If the user doesn’t exist, or if the token is invalid, expired, or already used, an appropriate error message.

(back to top)

2. Author Endpoints

a. Add Author - Adds a new author to the database.

  • Endpoint: /author/add

  • Method: POST

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Sample Payload:

    {
      "name": "Author Name"
    }
  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": null
      }
    • Failure: If the token is invalid, expired, already used, or if the name is empty or the author already exists, an appropriate error message will be returned.

b. Display Author - Displays a list of authors from the database.

  • Endpoint: /author/display

  • Method: GET

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": [
          {
            "authorid": 1,
            "name": "Author Name"
          }
        ]
      }
    • Failure: If the token has already been used, is invalid, or has expired, an appropriate error message will be returned.

c. Update Author - Updates an author's information in the database.

  • Endpoint: /author/update

  • Method: PUT

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Sample Payload:

    {
      "authorid": 1,
      "name": "Updated Author Name"
    }
  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": null
      }
    • Failure: If the token has already been used, is invalid, expired, or if the author ID is missing or not found, or if there are no fields to update, an appropriate error message will be returned.

d. Delete Author - Deletes an author from the database.

  • Endpoint: /author/delete

  • Method: DELETE

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Sample Payload:

    {
      "authorid": 1
    }
  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": null
      }
    • Failure: If the token has already been used, is invalid, expired, or if the author ID is missing or not found, an appropriate error message will be returned.

(back to top)

3. Book Endpoints

a. Add Book - Adds a new book to the database.

  • Endpoint: /book/add

  • Method: POST

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Sample Payload:

    {
      "title": "Book Title"
    }
  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": null
      }
    • Failure: If the token is invalid, expired, already used, or if the title is empty or the book already exists, an appropriate error message will be returned.

b. Display Books - Displays a list of books from the database.

  • Endpoint: /book/display

  • Method: GET

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": [
          {
            "bookid": 1,
            "title": "Book Title"
          }
        ]
      }
    • Failure: If the token has already been used, is invalid, or expired, an appropriate error message will be returned.

c. Update Book - Updates a book's information in the database.

  • Endpoint: /book/update

  • Method: PUT

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Sample Payload:

    {
      "bookid": 1,
      "title": "Updated Book Title"
    }
  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": null
      }
    • Failure: If the token has already been used, is invalid, expired, or if the book ID is missing or not found, or if there are no fields to update, an appropriate error message will be returned.

d. Delete Book - Deletes a book from the database.

  • Endpoint: /book/delete

  • Method: DELETE

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Sample Payload:

    {
      "bookid": 1
    }
  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": null
      }
    • Failure: If the token has already been used, is invalid, expired, or if the book ID is missing or not found, an appropriate error message will be returned.

(back to top)

4. Book-Author Endpoints

a. Add Book-Author - Adds a new association between a book and an author.

  • Endpoint: /books_author/add

  • Method: POST

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Sample Payload:

    {
      "bookid": 1,
      "authorid": 2
    }
  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": null
      }
    • Failure: If the token is already used, invalid/expired, or if required fields (book ID or author ID) are missing, the response will indicate the specific error.

b. Display All Book-Author - Displays all book-author associations in the database with their corresponding IDs.

  • Endpoint: /books_author/display

  • Method: GET

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": [
          {
            "collectionid": 1,
            "bookid": 1,
            "authorid": 2
          }
        ]
      }
    • Failure: If the token is already used, invalid/expired, or any database issue occurs, the response will indicate the specific error.

c. Display Book-Author with Names - Displays book-author associations with the book and author names instead of IDs.

  • Endpoint: /books_author/display_with_names

  • Method: GET

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": [
          {
            "collectionid": 1,
            "book_name": "Book Title 1",
            "author_name": "Author Name 1"
          }
        ]
      }
    • Failure: If the token is already used, invalid/expired, or any database issue occurs, the response will indicate the specific error.

d. Update Book-Author - Updates an existing book-author association by changing the book and/or author ID.

  • Endpoint: /books_author/update

  • Method: PUT

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Sample Payload:

    {
      "collectionid": 1,
      "bookid": 2,
      "authorid": 3
    }
  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": null
      }
    • Failure: If the token is already used, invalid/expired, if the collection ID is missing or not found, or no fields are provided to update, the response will indicate the specific error.

e. Delete Book-Author - Deletes a specific book-author association.

  • Endpoint: /books_author/delete

  • Method: DELETE

  • Headers: Authorization: Bearer <insert generated jwtTokenHere>

  • Sample Payload:

    {
      "collectionid": 1
    }
  • Expected Response:

    • Success:

      {
        "status": "success",
        "token": "jwtTokenHere",
        "data": null
      }
    • Failure: If the token is already used, invalid/expired, if the collection ID is missing or no association exists for the given ID, the response will indicate the specific error.

(back to top)

Token Management

Token Rotation

The generateToken function creates a JWT for user authentication, with a 2-hour expiration time, including the user ID in the payload, and the token is signed using the HS256 algorithm.

function generateToken($userid)
{
    global $key;

    $iat = time();
    $exp = $iat + 7200;

    $payload = [
        'iss' => 'http://library.org',
        'aud' => 'http://library.com',
        'iat' => $iat,
        'exp' => $exp,
        'data' => [
            'userid' => $userid
        ]
    ];

    return JWT::encode($payload, $key, 'HS256');
}

Check if Token is Used
The isTokenUsed function checks the used_tokens table to see if the token has been recorded as used.

function isTokenUsed($token, $conn)
{
    $stmt = $conn->prepare("SELECT * FROM used_tokens WHERE token = :token");
    $stmt->bindParam(':token', $token);
    $stmt->execute();
    return $stmt->rowCount() > 0;
}

Validate Token
The validateToken function decodes and validates the token using the secret key, returning false if the token is invalid or expired.

function validateToken($token, $key)
{
    try {
        return JWT::decode($token, new Key($key, 'HS256'));
    } catch (Exception $e) {
        return false;
    }
}

Mark Token as Used
The markTokenAsUsed function inserts the token into the used_tokens table, marking it as used to prevent reuse.

function markTokenAsUsed($conn, $token)
{
    try {
        $stmt = $conn->prepare("INSERT INTO used_tokens (token) VALUES (:token)");
        $stmt->bindParam(':token', $token);
        $stmt->execute();
    } catch (PDOException $e) {
        throw new Exception("Error marking token as used: " . $e->getMessage());
    }
}

(back to top)

Token Management

Token Rotation

The generateToken function creates a JWT for user authentication, with a 2-hour expiration time, including the user ID in the payload, and the token is signed using the HS256 algorithm.

function generateToken($userid)
{
    global $key;

    $iat = time();
    $exp = $iat + 7200;

    $payload = [
        'iss' => 'http://library.org',
        'aud' => 'http://library.com',
        'iat' => $iat,
        'exp' => $exp,
        'data' => [
            'userid' => $userid
        ]
    ];

    return JWT::encode($payload, $key, 'HS256');
}

Check if Token is Used
The isTokenUsed function checks the used_tokens table to see if the token has been recorded as used.

function isTokenUsed($token, $conn)
{
    $stmt = $conn->prepare("SELECT * FROM used_tokens WHERE token = :token");
    $stmt->bindParam(':token', $token);
    $stmt->execute();
    return $stmt->rowCount() > 0;
}

Validate Token
The validateToken function decodes and validates the token using the secret key, returning false if the token is invalid or expired.

function validateToken($token, $key)
{
    try {
        return JWT::decode($token, new Key($key, 'HS256'));
    } catch (Exception $e) {
        return false;
    }
}

Mark Token as Used
The markTokenAsUsed function inserts the token into the used_tokens table, marking it as used to prevent reuse.

function markTokenAsUsed($conn, $token)
{
    try {
        $stmt = $conn->prepare("INSERT INTO used_tokens (token) VALUES (:token)");
        $stmt->bindParam(':token', $token);
        $stmt->execute();
    } catch (PDOException $e) {
        throw new Exception("Error marking token as used: " . $e->getMessage());
    }
}

(back to top)

Project Information

This project was developed as a midterm requirement for the ITPC 115 course. It showcases proficiency in designing secure API endpoints and implementing effective token management.

(back to top)

Contact Information

If you need assistance or have any questions, feel free to reach out to me. Below are my contact details:

(back to top)

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages