Implementing Account Management

1. Creating User Accounts

FieldValidationStorage
emailRFC 5322, lowercased, unique indexVARCHAR(254)
username3–30 chars, ^[a-z0-9_]+$VARCHAR(30), citext
password_hashArgon2id encoded stringTEXT
statuspending|active|locked|deletedENUM
created_atUTC timestampTIMESTAMPTZ

Example: Idempotent user creation

@Transactional
public User createUser(SignupRequest req) {
  if (userRepo.existsByEmailIgnoreCase(req.email())) {
    // Don't reveal existence — send re-confirmation email instead
    mailer.sendDuplicateAttempt(req.email());
    return null;
  }
  var hash = passwordEncoder.encode(req.password());
  var user = new User(req.email(), hash, Status.PENDING);
  userRepo.save(user);
  verificationService.sendEmail(user);
  return user;
}

2. Validating User Input

FieldRuleLibrary
EmailFormat + MX lookup (optional)Joi, Zod, Bean Validation
PhoneE.164 formatlibphonenumber
NamesUnicode letters, length ≤100Regex + normalize NFC
URLsAllowed schemes only (http/https)URL parser, not regex
All inputsReject control chars, normalize whitespaceOWASP ESAPI

3. Implementing Email Verification

Email Verification Flow

  1. User registers → account status = PENDING
  2. Generate token (32 bytes CSPRNG), store SHA-256 hash + expiry (24h)
  3. Send link: https://app/verify?token={raw}
  4. On click: hash token, lookup, check expiry
  5. Set email_verified_at = NOW(), status = ACTIVE
  6. Delete verification token row

4. Handling Username Availability Checks

ConcernMitigation
EnumerationRate-limit checks per IP (5/min)
Race conditionUse DB unique constraint + retry
Reserved namesBlocklist (admin, root, api, ...)
HomoglyphsNFKC normalize + Unicode confusables map

5. Implementing Profile Management

OperationSecurity Requirement
Update emailRe-verify new address before activation
Update phoneSMS OTP confirmation
Change passwordRequire current password + re-auth
Update MFAStep-up authentication required
Sensitive changesEmail user "your X was changed"

6. Allowing Account Deletion

ApproachBehaviorUse Case
Hard deleteRemove row immediatelyGDPR right-to-erasure
Soft deleteSet deleted_at, hide from queriesRecoverable, audit
AnonymizationReplace PII with hashes/nulls, keep FK integrityPreserve analytics
Grace periodSoft-delete + purge after 30 days"Account recovery" window

7. Implementing Account Deactivation

StateBehavior
DEACTIVATEDCannot login, data preserved
SessionsAll revoked immediately
TokensAdded to revocation list
ReactivationEmail confirmation + identity proof

8. Handling Account Recovery

Recovery MethodUse CaseRisk
Email linkLost passwordEmail account takeover
SMS codeLost password + verified phoneSIM swap
Backup codesLost MFA deviceCode theft
Trusted contactLost all factorsSocial engineering
ID verificationHigh-value accountPrivacy + cost

9. Implementing User Impersonation

ControlRequirement
PermissionExplicit support:impersonate role
Token claimsInclude act (actor) claim per RFC 8693
UI indicatorPersistent banner "Acting as ..."
AuditLog start, end, every action with both IDs
ScopeRestrict (e.g., no password change)
DurationShort-lived token (≤15 min)

Example: JWT with actor claim (RFC 8693)

{
  "sub": "user_42",
  "act": { "sub": "support_agent_7", "email": "agent@acme.com" },
  "scope": "read profile orders",
  "exp": 1715000000
}

10. Auditing Account Changes

EventFields Logged
createuser_id, ip, ua, source (web/api)
updatefield_name, old, new, actor_id
deleteuser_id, actor_id, reason
role_changeadded/removed roles, actor_id
password_changetimestamp, ip (NEVER the password)