Breaking a JWT Authentication API: Identifying Critical Vulnerabilities using AI & Structured Test Cases
This project gave me a practical understanding of how small validation issues can lead to serious security risks in real-world applications.

Introduction :
Modern applications rely heavily on authentication systems to protect user data and control access. Among these, JSON Web Token (JWT)-based authentication is widely used due to its simplicity and scalability. However, improper implementation or missing validations can introduce serious security vulnerabilities.
In this project, I analyzed and tested a JWT-based authentication API using structured test cases. Instead of only verifying normal behavior, the focus was on exploring edge cases, uncovering hidden flaws, and observing how the system behaves under unexpected or invalid inputs.
Using manual testing along with automated test execution, several critical issues were identified. These findings highlight how a system can appear functional while still containing serious security weaknesses.
Setup & Tools
To perform this analysis, I used a Node.js-based JWT authentication API along with a structured testing approach.
Tech Stack:
Backend: bezkoder/jwt-auth
Database: MongoDB + docker
Authentication: JWT (JSON Web Tokens)
Testing: Vitest + Axios
Supporting Tools: passmark (for structured execution),
The API provides basic authentication features such as user signup, login, and role-based access control.
Testing Approach
Instead of focusing only on normal application behavior, I designed test cases to simulate real-world attack scenarios.
The testing approach included:
Functional Testing (valid signup/login)
Edge Case Testing (empty inputs, invalid data)
Security Testing (authentication bypass, brute force attempts)
AI-assisted test generation for identifying unusual cases
This structured approach ensured both coverage and depth in testing.
Test Cases Overview
Total Test Cases: 25+
Categories:
- Functional: 5
- Edge Cases: 10
- Security: 10
Critical Vulnerabilities Found
1: Signup with empty password
Test Case: Signup with empty password
Expected: Request rejected
Actual: Account created successfully
Response : { message: 'User was registered successfully!' }
The API allows users to register with an empty password due to missing validation. This results in accounts that have effectively no authentication protection.
Impact:
* Weak account security
* Increased risk of unauthorized access
Severity: CRITICAL
2: Signin with empty password
Test Case: Signin with empty password
Expected: Request rejected
Actual: Login successfully
Response : {
id: '69e9edfc945298a18efac351',
username: 'usernae',
email: 'test@test20.com',
roles: [ 'ROLE_USER' ],
accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY5ZTllZGZjOTQ1Mjk4YTE4ZWZhYzM1MSIsImlhdCI6MTc3NjkzODQ5MiwiZXhwIjoxNzc3MDI0ODkyfQ.XldWnJM4UFuVnVFde9ZFEVK_gmg6-TSNScrLQ9y4SQo'
}
The API allows users to login with an empty password due to missing validation. This results in accounts that have effectively no authentication protection.
Impact:
* Weak account security
* Increased risk of unauthorized access
Severity: CRITICAL
3: User Enumeration Vulnerability
Test Case:
- Non-existing user → 404
- Wrong password → 401
Observation: The API returns consistent error responses for invalid login attempts.
Result: No user enumeration vulnerability detected.
4: No Rate Limiting (Brute Force)
after multiple attempts I see:
delay
blocking
same response
throttling
Observation: Multiple login attempts were handled without exposing system weakness or instability.
Result: No brute-force vulnerability detected under tested conditions.
5 : MongoDB Injection Attempt
$ne(not equal) — classic probegt(greater than) — type coercion probe$regex(pattern match) — enumeration-styleNested operator
### NoSQL Injection Testing (MongoDB)
Multiple NoSQL injection payloads were tested against the authentication endpoint, including operators such as `\(ne`, `\)gt`, and `$regex`.
**Test Input Example:**
**Expected Behavior:**
The system should reject non-string inputs and prevent query manipulation.
**Actual Behavior:**
The API rejected all crafted payloads and did not allow manipulation of database queries.
**Conclusion:**
No NoSQL injection vulnerability was detected in the authentication flow.
**Impact:**
This indicates that the application properly handles unexpected input types and prevents injection-based attacks.
**Severity:**
None (Secure Implementation)
6: JWT Security Testing
Invalid Token Test
Missing Token Test
Tampered Token
Payload Manipulation
### JWT Security Testing
Several attack scenarios were tested against the JWT authentication mechanism, including invalid tokens, tampered tokens, and missing tokens.
**Observations:**
* Invalid tokens were correctly rejected
* Tampered tokens were not accepted
* Requests without tokens were denied
**Conclusion:**
The JWT implementation correctly verifies token integrity and prevents unauthorized access through token manipulation.
**Impact:**
* Protects against token forgery attacks
* Ensures integrity of authentication system
**Severity:**
Secure Implementation
Test Results Summary
Total Tests: 7
Passed: 3
Failed: 4
High Severity Issues: 3
Medium: 1
Low: 0
Role of AI in Testing
AI was used to generate additional edge cases and security-focused test scenarios. This helped uncover vulnerabilities that might not be immediately obvious through manual testing alone.
Examples included:
* Injection-based inputs
* Unusual payload structures
* Boundary condition testing
AI significantly improved the breadth of testing and helped identify deeper issues.
My Experience
Working on this project completely changed how I look at web applications. Initially, everything seemed to be working fine — signup, login, and token-based authentication all behaved as expected. But once I started testing edge cases, I realized how easy it is for serious issues to go unnoticed.
The most interesting part was discovering that the system allowed empty passwords during both signup and login. At first, it felt surprising because the application looked fully functional from a normal user’s perspective. This made me understand that functionality and security are very different things.
Another important learning was around testing approach. Running simple test cases was not enough — I had to think like an attacker. Trying unusual inputs, breaking assumptions, and observing responses helped uncover deeper issues. At the same time, some areas like JWT validation and injection handling were implemented correctly, which showed that the system was partially secure.
I also learned the importance of structured testing. Writing organized test cases made it easier to track what was tested, what failed, and what needed further analysis. It gave a clearer picture of the system instead of random testing.
Overall, this experience helped me understand how real-world security testing works. It’s not about forcing the system to break, but about carefully analyzing behavior, identifying weaknesses, and understanding their impact.
