This is a Go starter template for building a backend service using Gin for HTTP routing, JWT authentication, GORM with PostgreSQL, and other essential tools like Viper for configuration, Logrus for logging, and Migrate for database migrations. It follows a clean architecture structure to keep the project modular and scalable.
- ✅ JWT Authentication (Login, Register, Refresh Token, Logout with Blacklist Token)
- ✅ User Management Module
- ✅ Input Validation using Validator
- ✅ Configuration Management with Viper
- ✅ Structured Logging with Logrus
- ✅ Database ORM using GORM (PostgreSQL)
- ✅ Database Migrations using Migrate
- ✅ HTTP Routing using Fiber
- ✅ Middleware Support for authentication
- ✅ Monitoring with Jaeger and OpenTelemetry for distributed tracing
- ✅ Makefile for easy project commands
- ✅ Middleware Support for authentication
- ✅ YQ for reading YAML configuration files
- ✅ Unit testing using Testify
- ✅ Performance testing using K6
- ✅ Redis Integration for caching
This application implements a secure JWT-based authentication system with cookie-based refresh token storage. Here's how it works:
- User submits registration data (email, password, etc.)
- System validates input and creates new user account
- User receives success response and can proceed to login
- User submits login credentials (email/username and password)
- System validates credentials against database
- If valid, system generates:
- Access Token (JWT) - Short-lived (15-30 minutes)
- Refresh Token (JWT) - Long-lived (7-30 days)
- Access token is returned in response body
- Refresh token is stored in HTTP-only cookie for security
- User can access protected routes using the access token
- When access token expires, client receives 401 Unauthorized
- Client automatically calls
/api/auth/refresh-token
endpoint - System reads refresh token from HTTP-only cookie
- If refresh token is valid and not blacklisted:
- Generate new access token
- Optionally rotate refresh token (generate new one)
- Return new access token in response
- Store new refresh token in cookie (with refresh token rotation)
- Client uses new access token for subsequent requests
- User calls
/api/auth/logout
endpoint - System adds current refresh token to blacklist
- HTTP-only cookie containing refresh token is cleared
- User is successfully logged out
- HTTP-only cookies: Refresh tokens stored in HTTP-only cookies prevent XSS attacks
- Token blacklisting: Logout functionality blacklists refresh tokens
- Short-lived access tokens: Minimizes exposure if access token is compromised
- Secure cookie attributes: Cookies use Secure and SameSite attributes
- Token rotation: Optional refresh token rotation for enhanced security
- Access tokens should be stored in memory (not localStorage)
- Implement automatic token refresh on 401 responses
- Handle logout by clearing local access token and calling logout endpoint
- Cookies are handled automatically by browsers
📦 project-root
┣ 📂 cmd # Application entry point
┃ ┣ 📂 app
┃ ┃ ┗ 📜 main.go # Main file
┃ ┗ 📂 seed
┃ ┗ 📜 main.go # Seeder main file
┣ 📂 db/migration # Database migrations
┃ ┣ 📜 000001_create_user.up.sql
┃ ┣ 📜 000001_create_user.down.sql
┃ ┣ 📜 000002_create_role_and_permission.down.sql
┃ ┗ 📜 000002_create_role_and_permission.up.sql
┣ 📂 internal # Internal business logic
┃ ┣ 📂 config # Configuration files
┃ ┃ ┣ 📂 env
┃ ┃ ┣ 📂 monitoring
┃ ┃ ┣ 📂 validation
┃ ┃ ┣ 📜 app.go
┃ ┃ ┣ 📜 fiber.go
┃ ┃ ┣ 📜 gorm.go
┃ ┃ ┣ 📜 logrus.go
┃ ┃ ┣ 📜 migration.go
┃ ┃ ┗ 📜 viper.go
┃ ┣ 📂 controller # HTTP controllers
┃ ┃ ┣ 📜 auth_controller.go
┃ ┃ ┣ 📜 user_controller.go
┃ ┃ ┗ 📜 welcome_controller.go
┃ ┣ 📂 dto # Data Transfer Objects
┃ ┃ ┣ 📂 converter # Converter Data Transfer Objects
┃ ┃ ┣ 📜 auth_request.go
┃ ┃ ┗ 📜 auth_response.go
┃ ┣ 📂 middleware # Middleware handlers
┃ ┃ ┣ 📜 auth_middleware.go
┃ ┃ ┗ 📜 cors_middleware.go
┃ ┣ 📂 model # Database models
┃ ┃ ┗ 📜 user.go
┃ ┣ 📂 repository # Database repositories
┃ ┃ ┣ 📜 repository.go
┃ ┃ ┗ 📜 user_repository.go
┃ ┣ 📂 route # Routing setup
┃ ┃ ┗ 📜 route.go
┃ ┣ 📂 service # Business logic
┃ ┃ ┗ 📜 auth_service.go
┃ ┣ 📂 utils # Utility packages
┃ ┃ ┗ 📂 errcode
┣ 📂 test # Testing
┃ ┣ 📂 performance # K6 performance tests
┃ ┃ ┣ 📜 get-user.js
┃ 📜 config.example.yml
┃ 📜 config.yml
┣ 📜 go.mod # Go module dependencies
┣ 📜 go.sum # Go module checksum
┣ 📜 Makefile # Makefile for running tasks
- Go (1.24+ recommended)
- PostgreSQL
- Make (for running commands)
- K6 (for performance testing)
make install
To install yq
, use the following command:
sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 && sudo chmod +x /usr/local/bin/yq
To install k6
for performance testing:
# Linux/Ubuntu
sudo apt-get install k6
# macOS
brew install k6
# Windows (using Chocolatey)
choco install k6
Rename config.example.yml
to config.yml
and configure your database settings.
make migrateup
make run
Server will be available at http://localhost:3000
.
Endpoint | Method | Description | Auth Required |
---|---|---|---|
/api/auth/register |
POST | Register new user | No |
/api/auth/login |
POST | Login user | No |
/api/auth/logout |
POST | Logout user | Yes |
/api/auth/refresh-token |
POST | Refresh JWT token | No* |
*Requires valid refresh token in HTTP-only cookie
Endpoint | Method | Description | Auth Required |
---|---|---|---|
/api/users/me |
GET | Get current user | Yes |
curl -X POST http://localhost:3000/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "password123",
"name": "John Doe"
}'
curl -X POST http://localhost:3000/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "[email protected]",
"password": "password123"
}'
curl -X GET http://localhost:3000/api/users/me \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
curl -X POST http://localhost:3000/api/auth/refresh-token \
-H "Content-Type: application/json" \
--cookie "refresh_token=YOUR_REFRESH_TOKEN"
Run unit tests using:
go test ./...
Run performance tests using K6:
# Run specific performance test
k6 run test/performance/get-user.js
Command | Description |
---|---|
make install |
Install the dependencies |
make run |
Start the application |
make migrateschema name=<schema_name> |
Create new migration |
make migrateup |
Apply database migrations |
make migratedown |
Rollback database migrations |
Feel free to fork and modify this template to fit your needs. Pull requests are welcome!
This project is licensed under the MIT License.
🚀 Happy coding!