A high-performance JWT authentication microservice written in Go, featuring Redis caching and Docker support.
- π JWT-based authentication
- β‘ High-performance Redis caching
- β»οΈ Token refresh mechanism
- π Auto-logout functionality
- π Structured logging
- π³ Docker support
- π Fast and lightweight
- π§ͺ Comprehensive test coverage
graph LR
Client --> NGINX[π NGINX]
subgraph Docker Network
NGINX --> DNS[π‘ Docker DNS]
DNS --> JWT1[π’ JWT Service 1]
DNS --> JWT2[π’ JWT Service 2]
DNS --> JWTn[π’ JWT Service n]
end
subgraph Shared State
direction LR
JWT1 --> Redis[(πΎ Redis)]
JWT2 --> Redis
JWTn --> Redis
end
Endpoint | Method | Description | Auth Required |
---|---|---|---|
/ping |
GET | Health check endpoint | β No |
/login |
POST | Login and get token pair | β No |
/refresh |
POST | Refresh token pair | β Yes |
/logout |
POST | Invalidate token pair | β Yes |
/authenticate |
GET | Validate access token | β Yes |
- π³ Docker
- π οΈ Docker Compose
The service supports horizontal scaling through Docker's built-in DNS-based load balancing:
docker compose up --build --scale jwt=5
This command will:
- πββοΈ Start 5 instances of the JWT service
- π Register them with Docker's DNS service
- π Enable automatic load balancing through Docker's embedded DNS server
- πΎ Maintain shared state through Redis
NGINX acts as a reverse proxy, forwarding requests to the Docker DNS service, which routes them to the appropriate JWT service instance.
-
Clone the repository
git clone https://github.com/GregoryKogan/jwt-microservice.git cd jwt-microservice
-
Choose a startup option:
docker compose up --build
# Start 5 instances with load balancing
docker compose up --build --scale jwt=5
# Live-reloading for single instance
docker compose up --build --watch
# Live-reloading with multiple instances
docker compose up --build --watch --scale jwt=3
The service will be available at http://localhost:4000
.
The service is configured via config.yml
:
server:
port: 8080
max_processors: 2 # sets GOMAXPROCS
logging:
mode: text # text or json
level: debug
cache:
host: cache
port: 6379
auth:
issuer: jwt-microservice
access_lifetime: 15m
refresh_lifetime: 720h
auto_logout: 24h
Also, take a look at the docker-compose.yml
file for more configuration options such as CPU resource limits and port mappings.
Run all tests with cache mocking:
go test ./... -v
Load testing is performed using Grafana K6. To execute the load tests with the load-test
profile, run:
docker compose --profile load-test up --build --scale jwt=5
The xk6 dashboard will be available at http://localhost:5665
during load testing.
Instances | CPU Limit per Instance | Max Processors | Avg Response Time | RPS | Error Rate |
---|---|---|---|---|---|
1 | 0.1 | 1 | 895.21ms | 974 | 72.51% |
2 | 0.1 | 1 | 274.59ms | 1097 | 53.54% |
4 | 0.2 | 2 | 8.07ms | 1163 | 0.39% |
8 | 0.25 | 2 | 6.7ms | 1154 | 0.21% |
16 | 0.5 | 4 | 15.84ms | 978 | 0.59% |
32 | - | - | 91.54ms | 1031 | 1.81% |
Note: Charts and graphs are generated on the fly using xk6. Here's an example of the performance chart:
- π UUID-based token tracking
- π Token Rotation Mechanism
- β Automatic token invalidation
- β° Configurable token lifetimes
- π Secure token refresh mechanism
- π Auto-logout for inactive users
The service implements a secure token rotation mechanism to enhance security:
- Single-Use Refresh Tokens: Each refresh token is valid for only one use. Upon using it to obtain a new token pair, the old refresh token is invalidated.
- Prevents Replay Attacks: This mechanism mitigates the risk of replay attacks by ensuring that stolen or leaked refresh tokens cannot be reused.
- Seamless User Experience: Token rotation happens transparently, providing continuous access without requiring the user to re-authenticate.
curl -X POST http://localhost:8080/login \
-H "Content-Type: application/json" \
-d '{"user_id": 1}'
curl -X POST http://localhost:8080/refresh \
-H "Content-Type: application/json" \
-d '{"refresh": "your-refresh-token"}'
curl -X GET http://localhost:8080/authenticate \
-H "Authorization: Bearer your-access-token"
curl -X POST http://localhost:8080/logout \
-H "Authorization: Bearer your-access-token"
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.