A robust authentication system built with Go using the Gin web framework, featuring JWT-based authentication, bcrypt password hashing, and PostgreSQL database.
- ✅ User registration with email validation
- ✅ User login with JWT tokens
- ✅ Access tokens (15 minutes expiry)
- ✅ Refresh tokens (7 days expiry)
- ✅ Password hashing with bcrypt
- ✅ Protected routes with middleware
- ✅ Clean architecture (handlers, services, repositories)
- ✅ CORS support
- ✅ Environment-based configuration
authentication/
├── config/ # Configuration loader
├── database/ # Database connection and migrations
├── dto/ # Data Transfer Objects
├── handlers/ # HTTP handlers
├── middleware/ # Middleware (auth, CORS)
├── models/ # Data models
├── repository/ # Data access layer
├── services/ # Business logic
├── utils/ # Utility functions
├── main.go # Application entry point
├── .env # Environment variables
└── go.mod # Go module file
- Go 1.21 or higher
- PostgreSQL 12 or higher
cd /home/emeka/Desktop/builds/learn-go/authenticationCopy the example environment file and update with your credentials:
cp .env.example .envEdit .env and update the following values:
DB_PASSWORD: Your PostgreSQL passwordJWT_ACCESS_SECRET: Generate a strong random secretJWT_REFRESH_SECRET: Generate a different strong random secret
Important: Use strong, unique secrets in production!
# Connect to PostgreSQL
psql -U postgres
# Create the database
CREATE DATABASE auth_db;
# Exit psql
\qpsql -U postgres -d auth_db -f database/migrations.sqlgo mod tidygo run main.goThe server will start on http://localhost:8080
POST /api/auth/register
Content-Type: application/json
{
"email": "user@example.com",
"password": "SecurePassword123!",
"name": "John Doe"
}Response:
{
"user": {
"id": "uuid",
"email": "user@example.com",
"name": "John Doe",
"created_at": "timestamp"
},
"access_token": "jwt_token",
"refresh_token": "jwt_token"
}POST /api/auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "SecurePassword123!"
}Response: Same as registration
POST /api/auth/refresh
Content-Type: application/json
{
"refresh_token": "your_refresh_token"
}Response:
{
"access_token": "new_jwt_token"
}GET /api/auth/me
Authorization: Bearer <access_token>Response:
{
"id": "uuid",
"email": "user@example.com",
"name": "John Doe",
"created_at": "timestamp"
}GET /healthcurl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{
"email": "test@example.com",
"password": "SecurePass123!",
"name": "Test User"
}'curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "test@example.com",
"password": "SecurePass123!"
}'curl -X GET http://localhost:8080/api/auth/me \
-H "Authorization: Bearer TOKEN"curl -X POST http://localhost:8080/api/auth/refresh \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "REFRESH_TOKEN"
}'- Password Hashing: Bcrypt with default cost (10)
- JWT Tokens: HMAC-SHA256 signing
- Token Expiry: Short-lived access tokens, longer refresh tokens
- Input Validation: Email format, password minimum length (8 chars)
- SQL Injection Protection: Parameterized queries
- CORS: Configurable cross-origin support
| Variable | Description | Default |
|---|---|---|
SERVER_PORT |
HTTP server port | 8080 |
DB_HOST |
PostgreSQL host | localhost |
DB_PORT |
PostgreSQL port | 5432 |
DB_USER |
Database user | postgres |
DB_PASSWORD |
Database password | postgres |
DB_NAME |
Database name | auth_db |
DB_SSLMODE |
SSL mode | disable |
JWT_ACCESS_SECRET |
Access token secret | Required |
JWT_REFRESH_SECRET |
Refresh token secret | Required |
JWT_ACCESS_EXPIRY |
Access token expiry | 15m |
JWT_REFRESH_EXPIRY |
Refresh token expiry | 168h |
APP_ENV |
Environment | development |
All errors follow this format:
{
"error": "error_code",
"message": "Human-readable error message"
}Common error codes:
bad_request(400): Invalid inputunauthorized(401): Invalid or missing tokennot_found(404): Resource not foundinternal_error(500): Server error
- Generate Strong Secrets: Use cryptographically secure random strings for JWT secrets
- Database SSL: Enable SSL for database connections in production
- HTTPS: Always use HTTPS in production
- Rate Limiting: Add rate limiting middleware to prevent abuse
- Logging: Implement proper logging for security events
- Token Blacklisting: Consider implementing token blacklisting for logout
- Password Requirements: Enforce stronger password policies
MIT