A minimal backend micro project that demonstrates how to:
- Issue a JWT access token
- Verify token using middleware
- Protect routes
- Handle invalid or expired tokens
This project intentionally does NOT implement refresh tokens. It focuses only on access token flow.
- Node.js
- Express
- jsonwebtoken
- dotenv
git clone <your-repo-url>
cd jwt-access-token-api
npm installCreate a .env file in root:
PORT=1198
JWT_SECRET=super_secret_change_me
JWT_EXPIRES_IN=15m- PORT: Server port
- JWT_SECRET: Secret key used to sign tokens
- JWT_EXPIRES_IN: Access token expiry duration (example: 15m, 1h)
Development mode:
npm run devProduction mode:
npm startServer will start at:
http://localhost:1198
jwt-access-token-api/
│
├── src/
│ └── index.js
│
├── .env
├── .gitignore
├── rest.http
├── package.json
└── README.md
- Client sends email + password to /auth/login
- Server verifies credentials
- Server issues JWT access token
- Client sends token in Authorization header
- Middleware verifies token
- Protected route returns user data
No refresh token is used in this demo.
Email: admin@example.com
Password: admin123
GET /health
Returns service status.
Response:
{
"ok": true,
"service": "jwt-access-token-api",
"time": "2026-02-13T10:00:00.000Z"
}POST /auth/login
Request Body:
{
"email": "admin@example.com",
"password": "admin123"
}Successful Response:
{
"ok": true,
"message": "login successful",
"accessToken": "<JWT_TOKEN>",
"tokenType": "Bearer",
"expiresIn": "15m"
}Invalid Credentials Response:
{
"ok": false,
"error": "invalid credentials"
}Missing Fields Response:
{
"ok": false,
"error": "email and password are required"
}GET /me
Header:
Authorization: Bearer <JWT_TOKEN>
Successful Response:
{
"ok": true,
"user": {
"sub": "user_001",
"email": "admin@example.com",
"role": "admin",
"iat": 1700000000,
"exp": 1700000900
}
}Invalid or Expired Token Response:
{
"ok": false,
"error": "invalid or expired token"
}When user logs in:
- Payload is created
- Token is signed using JWT_SECRET
- Expiry is added automatically
- Client stores token
- Client sends token in Authorization header
Middleware verifies:
- Signature is valid
- Token not expired
- Extracts payload
- Attaches payload to req.user
- JWT_SECRET must never be committed
- Always use strong secret in production
- Use HTTPS in real deployments
- Do not store sensitive data in token payload
This micro project demonstrates:
- Stateless authentication
- Token signing and verification
- Express middleware for route protection
- Basic API structure
- Environment configuration
- Add refresh token flow
- Add logout with token blacklist
- Add RBAC role middleware
- Add rate limiter
- Move auth middleware to separate file
- Add proper folder structure
MIT