add toggle for allowing registrations from the frontend
This commit is contained in:
281
REGISTRATION_CONTROL.md
Normal file
281
REGISTRATION_CONTROL.md
Normal file
@@ -0,0 +1,281 @@
|
||||
# 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"}'` |
|
||||
Reference in New Issue
Block a user