282 lines
7.0 KiB
Markdown
282 lines
7.0 KiB
Markdown
# Registration Control Guide
|
|
|
|
## Overview
|
|
|
|
The application now supports controlling user registration through an environment variable. This is a critical security feature that allows administrators to disable new user registrations in production environments while keeping existing user login functionality intact.
|
|
|
|
## Environment Variable
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `ALLOW_REGISTRATION` | `true` | Controls whether new user registration is allowed |
|
|
|
|
## Configuration
|
|
|
|
### Enable Registration (Default)
|
|
```bash
|
|
ALLOW_REGISTRATION=true
|
|
```
|
|
or simply omit the variable (defaults to `true`)
|
|
|
|
### Disable Registration
|
|
```bash
|
|
ALLOW_REGISTRATION=false
|
|
```
|
|
|
|
## Usage Scenarios
|
|
|
|
### Development Environment
|
|
**Recommended**: Enable registration for testing
|
|
```bash
|
|
# .env or .env.local
|
|
ALLOW_REGISTRATION=true
|
|
```
|
|
|
|
### Production Environment
|
|
**Recommended**: Disable registration after initial setup
|
|
```bash
|
|
# .env.production
|
|
ALLOW_REGISTRATION=false
|
|
```
|
|
|
|
### Staging Environment
|
|
**Optional**: Enable for testing, disable for demos
|
|
```bash
|
|
# .env.staging
|
|
ALLOW_REGISTRATION=true # or false depending on needs
|
|
```
|
|
|
|
## Implementation Details
|
|
|
|
### Backend Behavior
|
|
|
|
**When `ALLOW_REGISTRATION=true` (default)**:
|
|
- `POST /api/users/register` accepts new registrations
|
|
- Returns 201 with user data and JWT token on success
|
|
- Returns 400 if user already exists
|
|
|
|
**When `ALLOW_REGISTRATION=false`**:
|
|
- `POST /api/users/register` returns 403 Forbidden
|
|
- Response: `{"error": "Registration is currently disabled"}`
|
|
- Login functionality remains unaffected
|
|
|
|
### Frontend Considerations
|
|
|
|
The frontend should handle the 403 response gracefully:
|
|
|
|
```javascript
|
|
// Example error handling in registration form
|
|
try {
|
|
const response = await api.post('/users/register', userData);
|
|
// Handle success
|
|
} catch (error) {
|
|
if (error.response?.status === 403) {
|
|
// Registration disabled
|
|
setError('Registration is currently disabled. Please contact an administrator.');
|
|
} else {
|
|
// Other errors (validation, user exists, etc.)
|
|
setError(error.response?.data?.error || 'Registration failed');
|
|
}
|
|
}
|
|
```
|
|
|
|
## Deployment Examples
|
|
|
|
### Quick Setup Commands
|
|
|
|
**Enable registration**:
|
|
```bash
|
|
echo "ALLOW_REGISTRATION=true" >> .env
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
**Disable registration**:
|
|
```bash
|
|
echo "ALLOW_REGISTRATION=false" >> .env
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
**Toggle without rebuild** (if container is already running):
|
|
```bash
|
|
# Update .env file
|
|
sed -i 's/ALLOW_REGISTRATION=.*/ALLOW_REGISTRATION=false/' .env
|
|
|
|
# Restart backend container to pick up new env var
|
|
docker-compose restart backend
|
|
```
|
|
|
|
### Environment-Specific Deployments
|
|
|
|
**Development with registration enabled**:
|
|
```bash
|
|
# .env.dev
|
|
ALLOW_REGISTRATION=true
|
|
REACT_APP_API_URL=http://localhost:5000/api
|
|
JWT_SECRET=dev-secret-key
|
|
|
|
# Deploy
|
|
cp .env.dev .env
|
|
docker-compose up -d
|
|
```
|
|
|
|
**Production with registration disabled**:
|
|
```bash
|
|
# .env.prod
|
|
ALLOW_REGISTRATION=false
|
|
REACT_APP_API_URL=https://your-domain.com/api
|
|
JWT_SECRET=super-secure-production-key
|
|
|
|
# Deploy
|
|
cp .env.prod .env
|
|
docker-compose up -d --build
|
|
```
|
|
|
|
## Security Best Practices
|
|
|
|
### 1. Disable Registration in Production
|
|
```bash
|
|
# Always set this in production
|
|
ALLOW_REGISTRATION=false
|
|
```
|
|
|
|
### 2. Create Initial Admin User
|
|
Before disabling registration, ensure you have at least one admin user:
|
|
|
|
```bash
|
|
# Method 1: Enable registration temporarily
|
|
ALLOW_REGISTRATION=true docker-compose up -d
|
|
# Register your admin user via frontend/API
|
|
# Then disable registration
|
|
ALLOW_REGISTRATION=false docker-compose restart backend
|
|
|
|
# Method 2: Create user directly in database (advanced)
|
|
docker-compose exec mongodb mongosh scoffer
|
|
# Use MongoDB commands to create user
|
|
```
|
|
|
|
### 3. Monitor Registration Attempts
|
|
Consider adding logging for blocked registration attempts:
|
|
|
|
```javascript
|
|
// In backend/routes/users.js (optional enhancement)
|
|
if (!registrationEnabled) {
|
|
console.log(`Registration attempt blocked from IP: ${req.ip}`);
|
|
return res.status(403).json({
|
|
error: 'Registration is currently disabled'
|
|
});
|
|
}
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Registration Still Working After Disabling
|
|
**Cause**: Environment variable not picked up by container
|
|
|
|
**Solutions**:
|
|
1. Restart the backend container:
|
|
```bash
|
|
docker-compose restart backend
|
|
```
|
|
|
|
2. Rebuild if env var was added after initial build:
|
|
```bash
|
|
docker-compose up -d --build backend
|
|
```
|
|
|
|
3. Verify environment variable in container:
|
|
```bash
|
|
docker-compose exec backend env | grep ALLOW_REGISTRATION
|
|
```
|
|
|
|
### Frontend Shows Registration Form When Disabled
|
|
**Cause**: Frontend doesn't know registration is disabled until API call
|
|
|
|
**Solutions**:
|
|
1. Add API endpoint to check registration status:
|
|
```javascript
|
|
// GET /api/users/registration-status
|
|
router.get('/registration-status', (req, res) => {
|
|
res.json({
|
|
enabled: process.env.ALLOW_REGISTRATION !== 'false'
|
|
});
|
|
});
|
|
```
|
|
|
|
2. Hide registration form based on API response
|
|
3. Handle 403 error gracefully in registration form
|
|
|
|
### Users Can't Login After Disabling Registration
|
|
**Issue**: This should NOT happen - login is separate from registration
|
|
|
|
**Check**:
|
|
1. Verify `ALLOW_REGISTRATION` only affects `/register` endpoint
|
|
2. Ensure `/login` endpoint is unaffected
|
|
3. Check JWT_SECRET hasn't changed
|
|
|
|
## API Reference
|
|
|
|
### Registration Endpoint
|
|
|
|
**Endpoint**: `POST /api/users/register`
|
|
|
|
**When Enabled** (`ALLOW_REGISTRATION=true`):
|
|
```bash
|
|
curl -X POST http://localhost:5000/api/users/register \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"username":"test","email":"test@example.com","password":"password123"}'
|
|
|
|
# Response: 201 Created
|
|
{
|
|
"message": "User created successfully",
|
|
"token": "jwt-token-here",
|
|
"user": {
|
|
"id": "user-id",
|
|
"username": "test",
|
|
"email": "test@example.com"
|
|
}
|
|
}
|
|
```
|
|
|
|
**When Disabled** (`ALLOW_REGISTRATION=false`):
|
|
```bash
|
|
curl -X POST http://localhost:5000/api/users/register \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"username":"test","email":"test@example.com","password":"password123"}'
|
|
|
|
# Response: 403 Forbidden
|
|
{
|
|
"error": "Registration is currently disabled"
|
|
}
|
|
```
|
|
|
|
### Login Endpoint (Unaffected)
|
|
|
|
**Endpoint**: `POST /api/users/login`
|
|
|
|
```bash
|
|
curl -X POST http://localhost:5000/api/users/login \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"email":"existing@example.com","password":"password123"}'
|
|
|
|
# Response: 200 OK (regardless of ALLOW_REGISTRATION setting)
|
|
{
|
|
"message": "Login successful",
|
|
"token": "jwt-token-here",
|
|
"user": {
|
|
"id": "user-id",
|
|
"username": "existing",
|
|
"email": "existing@example.com"
|
|
}
|
|
}
|
|
```
|
|
|
|
## Quick Reference
|
|
|
|
| Action | Command |
|
|
|--------|---------|
|
|
| Enable registration | `ALLOW_REGISTRATION=true` |
|
|
| Disable registration | `ALLOW_REGISTRATION=false` |
|
|
| Check current setting | `docker-compose exec backend env \| grep ALLOW_REGISTRATION` |
|
|
| Restart backend | `docker-compose restart backend` |
|
|
| Test registration | `curl -X POST localhost:5000/api/users/register -H "Content-Type: application/json" -d '{"username":"test","email":"test@test.com","password":"test123"}'` |
|