This is the most basic implementation of JWT-based authentication using login and password credentials. Upon successful login, the server returns a signed JWT in the response body, which the client must store and send with each request using the Authorization header. The security middleware verifies the JWT token, extracts the user ID from its payload, and injects this ID into the request object for downstream processing.
⚠ Security Advisory: Current JWT authentication level lacks production-grade security measures
- Features
- Tech Stack
- How It Works
- Endpoints
- Example Request
- Security Notes
- Testing
- Installation
- Environment Variables
- Running the App
- License
- Basic user authentication with login and password functionality
- JWT tokens for secure session management
- Secure Routes:
Authorization: Bearer <token>header required for protected routes, ensuring that only authenticated users can access sensitive data or perform critical actions.
- Prisma ORM: Utilize Prisma's type-safe PostgreSQL interactions to simplify database queries and schema management.
- Database Schema: Leverage a pre-defined database schema for efficient data storage and retrieval.
- DTO-based Request/Response Schemas: Ensure data consistency and security with request/response schemas based on Data Transfer Objects (DTOs).
- Validation Middleware: Built-in validation middleware to catch and handle invalid input data.
- Built-in Middleware: Deployed with CORS, Helmet, and rate limiting for comprehensive security protection.
- Cross-Site Scripting (XSS) Protection: Helmet middleware ensures that user input is properly sanitized to prevent XSS attacks.
- Rate Limiting: Mitigate brute-force attacks by enforcing reasonable request limits.
- End-to-End Test Suite: Utilize Supertest for comprehensive testing of API endpoints, ensuring seamless integration with the application.
- Test Coverage: Robust test coverage ensures that critical functionality is thoroughly validated and reliable.
- Interactive Swagger UI: Access an interactive and user-friendly documentation interface at
/api, providing a clear understanding of available endpoints and parameters.
- Docker Support: Leverage Docker containers for efficient deployment, isolation, and scalability.
- Backend Framework: NestJS
- Programming Language: TypeScript
- Database: PostgreSQL
- ORM: Prisma
- Authentication: JWT
- API Documentation: Swagger
- Rate Limiting: NestJS Throttler
- Password Hashing: Bcrypt
- Security Enhancements: Helmet
- Testing: Supertest
The journey begins when a user attempts to register or log in through our application. They send their credentials (login and password) to one of two routes:
/auth/sign-up: For new users who want to create an account./auth/sign-in: For existing users who need to authenticate.
The server receives the user's request and verifies their credentials against the database. If everything checks out, we proceed with the next step.
Upon successful verification, the server generates a JSON Web Token (JWT) for the user. This token contains essential information about the user, such as their ID.
The client-side application receives the JWT token from the server and stores it securely for future use. You can use LocalStorage or SessionStorage to store the token on the client side.
When a user attempts to access a protected route, their client-side application sends the stored JWT token in an Authorization header with each request:
Authorization: Bearer <token>
The backend server receives the request and verifies the validity of the JWT token. If everything checks out, it grants access to the protected route.
| Method | Endpoint | Description | Required Body |
|---|---|---|---|
| POST | /auth/sign-up |
Register a new user and get JWT | login: string, password: string |
| POST | /auth/sign-in |
Login and get JWT | login: string, password: string |
For a detailed overview of the available API endpoints, request/response structures, and data models, the Swagger documentation is available at /api. This documentation provides interactive API exploration and helps developers understand and integrate with the API efficiently.
POST /auth/sign-up
{
"login": "Pier228
"password": "password123"
}{
"token": "eyJhbGciOiJIUzI1NiIsInR5..."
}Authorization: Bearer <token>This JWT authentication implementation is designed for educational purposes or prototyping, but it's not recommended for production use due to several security limitations. The current implementation falls short in several critical areas:
- Refresh Token Mechanism: There is no refresh token in place, making it difficult for users to obtain a new token when their current one expires.
- Logout / Token Invalidation: Users cannot log out or invalidate their tokens, potentially leaving their accounts vulnerable to unauthorized access.
To ensure the application is working correctly, comprehensive testing has been implemented to cover all aspects of the JWT authentication flow. The application utilizes Supertest for E2E testing, which allows making HTTP requests directly from test code and verifying expected responses. Here's a snapshot of the test results:
As you can see, all tests passed successfully. This gives confidence in the correctness of the JWT authentication implementation and ensures it works as expected in different scenarios. You can also run this test cases using npm run test:e2e command.
$ git clone https://github.com/Pier228/level-0-basic-token-auth.git
$ cd level-0-basic-token-auth
$ npm installThe Docker image for this project is available on Docker Hub.
To run this application, you need to configure several environment variables.
- Create a .env file in the root directory of the project.
- Add required environment variables:
PORT: The port on which the server will run. This field is optional. By default will run on 3000 port.DATABASE_URL: MongoDB connection URL used to connect to the database.SALT_ROUNDS: Number of rounds for hashing passwords (bcrypt).JWT_SECRET: Secret key for signing and verifying JWT tokens.CORS_ALLOWED_ORIGIN: The URL of the domain from which it is allowed to send requests to the server (CORS settings).
You can also refer to the .env.example file for a complete list of required environment variables.
After setting up the .env file, you can start the application using the following commands:
# Generate prisma client
$ npx prisma generate
# Build the application
$ npm run build
# Start in development mode
$ npm run start
# Start in watch mode
$ npm run start:dev
# Start in production mode
$ npm run start:prodThis project is licensed under the MIT License - see the LICENSE file for details.

