This document describes the authentication and security infrastructure implemented for the Tenantly API.
The authentication system provides:
- JWT-based authentication with access and refresh tokens
- Role-based authorization (Admin, PropertyManager, Accountant)
- Password security with strength validation
- Comprehensive audit logging
- Rate limiting and security headers
- Session management with timeout
POST /api/v1/auth/login
{
"username": "user@example.com",
"password": "StrongPass123!"
}
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"id": 1,
"username": "user@example.com",
"role": "Admin",
"active": true
},
"expires_at": "2024-01-01T16:00:00Z"
}POST /api/v1/auth/refresh
{
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
POST /api/v1/auth/logout
Authorization: Bearer <access_token>
- Admin: Full system access, user management
- PropertyManager: Property and tenant management, payment recording
- Accountant: Read-only access to financial data and reports
// Require specific role
router.Use(middleware.RequireAdmin())
// Require one of multiple roles
router.Use(middleware.RequireRole("Admin", "PropertyManager"))
// Convenience middlewares
router.Use(middleware.RequireAdminOrPropertyManager())
router.Use(middleware.RequireAnyRole())- Minimum 8 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one digit
- At least one special character
POST /api/v1/auth/change-password
Authorization: Bearer <access_token>
{
"current_password": "OldPass123!",
"new_password": "NewStrongPass456!"
}
POST /api/v1/auth/reset-password
{
"email": "user@example.com"
}
- 100 requests per minute per IP address
- Failed attempts are logged for monitoring
- X-Frame-Options: DENY
- X-Content-Type-Options: nosniff
- X-XSS-Protection: 1; mode=block
- Strict-Transport-Security
- Content-Security-Policy
All authentication events are logged including:
- Login attempts (successful and failed)
- Token refresh
- Password changes
- Logout events
- API access with user context
- Access tokens expire after 8 hours (configurable)
- Refresh tokens expire after 7 days
- Automatic session timeout tracking
- User activity logging
POST /api/v1/auth/login- User loginPOST /api/v1/auth/refresh- Token refreshPOST /api/v1/auth/reset-password- Password reset request
POST /api/v1/auth/logout- User logoutPOST /api/v1/auth/change-password- Change password
GET /api/v1/users- List users (Admin/PropertyManager)POST /api/v1/users- Create user (Admin only)GET /api/v1/users/:id- Get user (Any role)PUT /api/v1/users/:id- Update user (Admin only)DELETE /api/v1/users/:id- Delete user (Admin only)
All authentication errors include structured error responses:
{
"error": "Invalid credentials",
"code": "LOGIN_FAILED"
}Common error codes:
AUTH_HEADER_MISSINGINVALID_TOKEN_FORMATTOKEN_INVALIDINSUFFICIENT_PERMISSIONSLOGIN_FAILEDPASSWORD_CHANGE_FAILED
Environment variables:
JWT_SECRET- Secret key for JWT signingJWT_EXPIRATION- Token expiration duration (default: 8h)DATABASE_URL- Database connection string
Run authentication tests:
go test ./internal/services -v
go test ./internal/middleware -v- JWT Secret: Use a strong, randomly generated secret in production
- HTTPS: Always use HTTPS in production
- Token Storage: Store tokens securely on the client side
- Rate Limiting: Monitor and adjust rate limits based on usage patterns
- Audit Logs: Regularly review audit logs for suspicious activity
- Password Policy: Enforce strong password requirements
- Session Management: Implement proper token invalidation on logout