Skip to content

Security Best Practices

Security guidelines for enterprise-ready deployment

Authentication

JWT Token Management

typescript
// Token structure
{
  email: string;
  _id: string;       // MongoDB ObjectId
  image: string;     // Profile image URL
  username: string;
  iat: number;       // Issued at timestamp
}

Best practices:

  • ✅ Store JWT_SECRET in environment variables, never in code
  • ✅ Use strong random secrets (256+ bits)
  • ✅ Rotate secrets periodically (implement token versioning)
  • ✅ Consider short-lived tokens with refresh mechanism

Password Security

Passwords are hashed using bcrypt (cost factor 10):

typescript
import * as bcrypt from 'bcrypt';

// Hash password
const hash = await bcrypt.hash(password, 10);

// Verify password
const isMatch = await bcrypt.compare(password, hash);

Status:

  • ✅ bcrypt 6 with native C++ bindings (upgraded from SHA-512)
  • ✅ Automatic salt generation per hash
  • ✅ Timing-safe comparison built in

API Security

Input Validation

Use class-validator decorators on DTOs:

typescript
import { IsEmail, IsString, MinLength } from 'class-validator';

export class CreateUserDto {
  @IsEmail()
  email: string;

  @IsString()
  @MinLength(8)
  password: string;
}

Rate Limiting

Implement NestJS throttling:

typescript
import { ThrottlerModule } from '@nestjs/throttler';

@Module({
  imports: [
    ThrottlerModule.forRoot([{
      ttl: 60000,    // Time window (ms)
      limit: 100,    // Max requests per window
    }]),
  ],
})

CORS Configuration

typescript
app.enableCors({
  origin: process.env.ORIGIN || 'http://localhost:3000',
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
});

Azure Security

Storage Access

The platform uses SAS tokens instead of public blob access:

typescript
// SAS tokens provide:
// - Time-limited access (1 year expiry)
// - Read-only permissions
// - HTTPS-only protocol

BlobSASPermissions.parse('r') // Read only
SASProtocol.Https
FeatureStatusRecommendation
Managed IdentityNot implementedUse for Container Apps
Key VaultNot implementedStore secrets securely
Private EndpointsNot implementedLimit network access
RBACPartialImplement least-privilege
typescript
import { SecretClient } from '@azure/keyvault-secrets';
import { DefaultAzureCredential } from '@azure/identity';

const client = new SecretClient(
  'https://your-vault.vault.azure.net',
  new DefaultAzureCredential()
);

const secret = await client.getSecret('JWT_SECRET');

File Upload Security

Current Validations

typescript
// MIME type based extension detection
if (mimetype === 'audio/mpeg') fileType = 'mp3';
else fileType = mimetype.split('/')[1];
typescript
// 1. File size limits
@UseInterceptors(FileInterceptor('file', { limits: { fileSize: 50 * 1024 * 1024 } }))

// 2. Magic byte validation
import * as fileType from 'file-type';
const detected = await fileType.fromBuffer(buffer);
if (!detected || !allowedTypes.includes(detected.mime)) {
  throw new BadRequestException('Invalid file type');
}

// 3. Filename sanitization (already implemented)
const sanitized = filename.replace(/[<>:"/\\|?*]/g, '_');

Mobile App Considerations

Token Storage

  • Use secure storage (Keychain on iOS, EncryptedSharedPreferences on Android)
  • Implement biometric authentication for token access
  • Clear tokens on logout

API Security for Mobile

  • Implement certificate pinning
  • Use short-lived tokens with silent refresh
  • Add device identification headers

Security Checklist

Development

  • [ ] JWT_SECRET is not committed to version control
  • [ ] .env files are in .gitignore
  • [ ] Dependencies are audited (npm audit)
  • [ ] CORS is configured for specific origins

Production

  • [ ] HTTPS is enforced everywhere
  • [ ] Secrets stored in Key Vault
  • [ ] Rate limiting enabled
  • [ ] Logging configured for security events
  • [ ] Database access uses connection pooling
  • [ ] Container Apps use managed identity

Compliance

  • [ ] GDPR data deletion endpoint exists
  • [ ] User data export capability
  • [ ] Password reset flow is secure
  • [ ] Session invalidation on password change

Last Updated: February 2026

Ctrl-Audio Platform Documentation