- Introduction
- Architecture
- Getting Started
- API Endpoints
- Project Structure
- Technologies Used
- Database Schema
- Service Methods
- Configuration
- Security Features
- Development
- Testing
- Deployment
- Roadmap
- Contributing
- License
This repository contains a production-ready authentication service built with Golang. The service demonstrates modern authentication practices using cookie-based sessions, JWT tokens, and PostgreSQL for user data persistence. It includes real-time messaging capabilities via Pusher WebSocket and comprehensive security features.
The architecture is composed of several core components:
- Authentication Handler: Manages user signup, signin, and logout operations
- Session Management: Cookie-based session storage with JWT tokens
- User Management: PostgreSQL database for persistent user data
- Real-Time Messaging: Pusher integration for WebSocket communication
- Health Monitoring: Service health check endpoints
- Validation Layer: Input validation and sanitization
Before you begin, ensure you have the following installed:
- Golang 1.19 or higher
- Docker
- Docker Compose
- sqlc (for generating type-safe SQL code)
-
Clone the repository:
git clone https://github.com/KunalKumar-1/auth-golang-cookies.git cd auth-golang-cookies -
Create an
.envfile in the root directory and set the necessary environment variables:cp .env.example .env
-
Example
.envfile:# PostgreSQL Configuration POSTGRES_USER=postgres POSTGRES_PASSWORD=postgres POSTGRES_HOST=localhost POSTGRES_PORT=5432 # Database URL DB_URL=postgres://postgres:postgres@localhost:5432/golangcookies?sslmode=disable # Application Configuration PORT=4000 # JWT Configuration JWT_SECRET=your_secure_jwt_secret_here # Pusher Configuration (for real-time messaging) PUSHER_APP_ID=your_pusher_app_id PUSHER_APP_KEY=your_pusher_app_key PUSHER_APP_SECRET=your_pusher_app_secret PUSHER_APP_CLUSTER=ap2
-
Build and run the service using Docker Compose:
docker-compose up --build
-
For local development without Docker:
# Install dependencies go mod download # Run database migrations psql -U your_db_user -d auth_db -f sql/schema/0001_users.sql # Generate database code sqlc generate # Run the application go run cmd/main.go
-
The service will be available at:
- API Server:
http://localhost:4000
- API Server:
GET /health-checkResponse:
{
"status": "healthy",
"timestamp": "2025-11-23T10:30:00Z",
"services": {
"database": "connected",
"redis": "connected"
}
}POST /signup
Content-Type: application/json
{
"name": "Kunal Kumar",
"username": "kunal",
"email": "[email protected]",
"password": "securePassword123"
}Response:
{
"message": "User registered successfully",
"user": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Kunal Kumar",
"username": "kunal",
"email": "[email protected]"
}
}POST /sign-in
Content-Type: application/json
{
"email": "[email protected]",
"password": "securePassword123"
}Response:
{
"message": "Login successful",
"user": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"username": "kunal",
"email": "[email protected]"
}
}Sets session cookie in response headers
POST /logout
Content-Type: application/json
Cookie: session_token=<token>
{}Response:
{
"message": "Logout successful"
}GET /auth-route
Accept: application/json
Cookie: session_token=<token>Response:
{
"message": "You are authenticated!",
"user": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"username": "kunal",
"email": "[email protected]"
}
}GET /check-ws
Accept: application/jsonResponse:
{
"status": "WebSocket available",
"endpoint": "ws://localhost:4000/ws",
"pusher": {
"cluster": "ap2",
"connected": true
}
}POST /send-message
Content-Type: application/json
{
"message": "Hello world!",
"username": "kunal"
}Response:
{
"status": "Message sent successfully",
"message": "Hello world!",
"username": "kunal",
"timestamp": "2025-11-23T10:30:00Z"
}auth-golang-cookies/
├── cmd/
│ └── main.go # Application entry point
├── handlers/
│ ├── handler_health.go # Health check endpoints
│ ├── handler_auth.go # Authentication handlers (signup, signin, logout)
│ ├── handler_pusher.go # WebSocket/SSE handlers for real-time messaging
│ └── handler_user.go # User management handlers
├── internal/
│ ├── config/
│ │ └── config.go # Configuration management & environment variables
│ └── database/
│ ├── db.go # Database connection setup
│ ├── models.go # Generated database models (sqlc)
│ └── user.sql.go # Generated SQL queries (sqlc)
├── models/
│ └── user_model.go # Application-level user models
├── sql/
│ ├── queries/
│ │ └── user.sql # SQL queries for sqlc
│ └── schema/
│ └── 0001_users.sql # Database schema migrations
├── utils/
│ └── validation.go # Input validation utilities
├── tmp/ # Temporary build files (gitignored)
│ ├── build-errors.log
│ └── main
├── docker-compose.yml # Docker Compose configuration
├── Dockerfile # Docker build configuration
├── sqlc.yaml # sqlc configuration
├── go.mod # Go module dependencies
├── go.sum # Go module checksums
├── .env.example # Environment variables template
└── README.md # Project documentation
- Golang: Primary language for building the service
- Docker: Containerization of the application
- Docker Compose: Orchestrating multi-container Docker application
- PostgreSQL: Database for persistent user data storage
- sqlc: Generate type-safe Go code from SQL queries
- bcrypt: Password hashing library
- JWT: JSON Web Tokens for authentication
- Pusher: Real-time bidirectional communication and WebSocket management
- HTTP Cookies: Secure session management
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
username VARCHAR(255) UNIQUE NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_username ON users(username);# Apply migrations
psql -U your_db_user -d auth_db -f sql/schema/0001_users.sql
# Generate type-safe code from SQL queries
sqlc generatefunc (h *HealthHandler) CheckHealth(c *gin.Context)func (h *AuthHandler) SignUp(c *gin.Context)
func (h *AuthHandler) SignIn(c *gin.Context)
func (h *AuthHandler) Logout(c *gin.Context)
func (h *AuthHandler) ValidateSession(c *gin.Context)func (h *UserHandler) GetCurrentUser(c *gin.Context)
func (h *UserHandler) UpdateUserProfile(c *gin.Context)
func (h *UserHandler) DeleteUser(c *gin.Context)func (h *PusherHandler) ConnectWebSocket(c *gin.Context)
func (h *PusherHandler) SendMessage(c *gin.Context)
func (h *PusherHandler) BroadcastMessage(message string)
func (h *PusherHandler) CheckWebSocketStatus(c *gin.Context)func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (User, error)
func (q *Queries) GetUserByEmail(ctx context.Context, email string) (User, error)
func (q *Queries) GetUserByUsername(ctx context.Context, username string) (User, error)
func (q *Queries) GetUserByID(ctx context.Context, id uuid.UUID) (User, error)
func (q *Queries) UpdateUser(ctx context.Context, arg UpdateUserParams) (User, error)
func (q *Queries) DeleteUser(ctx context.Context, id uuid.UUID) errorfunc ValidateEmail(email string) error
func ValidatePassword(password string) error
func ValidateUsername(username string) error
func SanitizeInput(input string) stringfunc (r *RedisClient) SetSession(sessionID string, userID uuid.UUID, expiry time.Duration) error
func (r *RedisClient) GetSession(sessionID string) (uuid.UUID, error)
func (r *RedisClient) DeleteSession(sessionID string) error
func (r *RedisClient) ExtendSession(sessionID string, expiry time.Duration) error| Variable | Description | Default | Required |
|---|---|---|---|
POSTGRES_USER |
PostgreSQL username | postgres |
Yes |
POSTGRES_PASSWORD |
PostgreSQL password | postgres |
Yes |
POSTGRES_HOST |
PostgreSQL host | localhost |
Yes |
POSTGRES_PORT |
PostgreSQL port | 5432 |
Yes |
DB_URL |
Full database connection URL | - | Yes |
PORT |
Application port | 4000 |
Yes |
JWT_SECRET |
Secret key for JWT token generation | - | Yes |
PUSHER_APP_ID |
Pusher application ID | - | Yes |
PUSHER_APP_KEY |
Pusher application key | - | Yes |
PUSHER_APP_SECRET |
Pusher secret key | - | Yes |
PUSHER_APP_CLUSTER |
Pusher cluster region | ap2 |
Yes |
- Password Hashing: Bcrypt algorithm with configurable cost
- Secure Cookies: HttpOnly, Secure, and SameSite flags enabled
- Session Tokens: Cryptographically secure random token generation
- Input Validation: Comprehensive validation for all user inputs
- SQL Injection Prevention: Type-safe queries using sqlc
- CORS Protection: Configurable CORS middleware
- Session Expiration: Automatic cleanup of expired sessions in Redis
- Rate Limiting: Protection against brute force attacks
- XSS Protection: Input sanitization and output encoding
Install Air for development with live reload:
go install github.com/air-verse/air@latestRun with live reload:
airAfter modifying SQL queries in sql/queries/user.sql:
sqlc generate# Install dependencies
go mod download
# Run tests
go test ./... -v
# Run with coverage
go test ./... -cover
# Build binary
go build -o auth-service cmd/main.go
# Run linter
golangci-lint run
# Format code
go fmt ./...# Run all tests
go test ./... -v
# Run tests with coverage
go test ./... -cover -coverprofile=coverage.out
# View coverage report
go tool cover -html=coverage.out
# Run specific package tests
go test ./handlers/... -v
# Run with race detection
go test -race ./...auth-golang-cookies/
├── handlers/
│ ├── handler_auth_test.go
│ ├── handler_user_test.go
│ └── handler_pusher_test.go
├── utils/
│ └── validation_test.go
└── internal/
└── database/
└── db_test.go
Build and deploy using Docker Compose:
# Build and start services
docker-compose up -d --build
# View logs
docker-compose logs -f
# Stop services
docker-compose down
# Remove volumes (caution: deletes data)
docker-compose down -v- Build the production binary:
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o auth-service cmd/main.go- Set environment variables for production:
ENVIRONMENT=production
SECRET_KEY=<generate-secure-random-key>
DB_URL=<production-database-url>
REDIS_HOST=<production-redis-host>- Run with systemd or process manager:
./auth-service- Use HTTPS/TLS for all communications
- Enable secure cookie flags in production
- Set up database connection pooling
- Configure Redis persistence (RDB/AOF)
- Implement proper logging and monitoring
- Set up automated backups for PostgreSQL
- Use environment-specific configuration
- Enable rate limiting on all endpoints
- Set up log rotation
- Use a reverse proxy (nginx/Caddy)
- Cookie-based authentication
- Session management with Redis
- User signup and signin
- WebSocket support for real-time messaging
- Health check endpoints
- OAuth2 integration (Google, GitHub, Facebook)
- Two-factor authentication (2FA/TOTP)
- Password reset functionality
- Email verification system
- JWT token support (optional alternative)
- Role-based access control (RBAC)
- API rate limiting with Redis
- Comprehensive API documentation (Swagger/OpenAPI)
- Integration tests
- Performance benchmarks
- Admin dashboard
- User profile management
- Account deletion workflow
- Audit logging
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow Effective Go guidelines
- Write meaningful commit messages
- Add tests for new features
- Update documentation as needed
- Run
go fmtandgolangci-lintbefore committing
This project is licensed under the MIT License - see the LICENSE file for details.