3.9 KiB
3.9 KiB
Token Prefix Security Recommendations
Current Security Issues
1. Information Disclosure
- Prefixes like "KMS", "TEST", "PROD" expose system architecture
- Makes it easy for attackers to identify token origins and purposes
- Leaks information about internal applications and environments
2. Predictable Token Structure
- Static tokens:
PREFIX + "T-" + token_data - User tokens:
PREFIX + "UT-" + jwt_token - Highly predictable format aids in token identification and potential attacks
3. Application Fingerprinting
- Trivial to map tokens to specific applications
- Easy to identify different environments (dev/staging/prod)
- Reveals system architecture from leaked tokens
Recommended Security Improvements
Option 1: Remove Custom Prefixes (Recommended)
// Use a single, non-descriptive prefix for all tokens
const SecureTokenPrefix = "kms_"
// All tokens would be: kms_<random_data>
// No application or type information revealed
Option 2: Opaque Application Identifiers
// Use random/hashed identifiers instead of descriptive names
type Application struct {
AppID string `json:"app_id"`
TokenPrefix string `json:"token_prefix"` // Random: "A7B2", "X9K5", etc.
}
// Generate random 4-character prefixes
func GenerateSecurePrefix() string {
const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
result := make([]byte, 4)
for i := range result {
result[i] = charset[rand.Intn(len(charset))]
}
return string(result)
}
Option 3: No Type Indicators
// Remove "T-" and "UT-" type indicators
// Token type should be determined by validation, not structure
func GenerateToken(appPrefix string, tokenType string) string {
token := appPrefix + randomTokenData // No type suffix
return token
}
Option 4: Encrypted Token Metadata
// Encrypt sensitive information within tokens
type TokenMetadata struct {
AppID string `json:"app_id"`
TokenType string `json:"token_type"`
IssuedAt time.Time `json:"issued_at"`
}
func CreateSecureToken(metadata TokenMetadata, key []byte) string {
// Encrypt metadata and embed in token
encrypted := encrypt(metadata, key)
return "kms_" + base64.URLEncoding.EncodeToString(encrypted)
}
Implementation Priority
- Immediate: Remove descriptive prefixes ("KMS", "TEST", "PROD")
- Short-term: Remove type indicators ("T-", "UT-")
- Long-term: Implement encrypted token metadata
Security Best Practices
Token Storage
- Always hash tokens before database storage
- Use strong hashing algorithms (bcrypt, scrypt, Argon2)
- Never log or expose full tokens
Token Validation
- Validate tokens by content, not by prefix patterns
- Use cryptographic verification for all tokens
- Implement proper token revocation mechanisms
Monitoring
- Monitor for token enumeration attempts
- Alert on suspicious prefix-based attacks
- Log token validation failures for security analysis
Code Changes Required
1. Update Token Generation
// Before: Predictable structure
token := "TESTT-" + tokenData
// After: Opaque structure
token := "kms_" + secureRandomToken()
2. Update Validation Logic
// Before: Prefix-based type detection
if strings.HasPrefix(token, app.TokenPrefix + "UT-") {
return TokenTypeUser
}
// After: Cryptographic validation
tokenType, err := validateAndExtractType(token, app.HMACKey)
3. Database Migration
-- Remove descriptive prefixes from existing tokens
UPDATE applications
SET token_prefix = 'kms_'
WHERE token_prefix IN ('KMS', 'TEST', 'PROD', 'DEV');
Risk Assessment
Current Risk Level: HIGH
- Token structure reveals sensitive system information
- Easy application and environment fingerprinting
- Predictable token patterns aid in attacks
Mitigated Risk Level: LOW
- Opaque token structure prevents information leakage
- No application or environment identification possible
- Cryptographic validation ensures security