MFA with Claude

Learn how to build a production MFA system using ColdFusion and SQL Server, featuring email OTP, WebAuthn passkeys, and a layered security approach for sensitive data.

Building Multi-Factor Authentication with ColdFusion and SQL Server: A Real-World Implementation

Overview

This post walks through a production MFA login system I built for a client with portal using Adobe ColdFusion and Microsoft SQL Server -- with the help of Claude as a coding partner. The system layers email-based one-time codes and WebAuthn passkeys on top of traditional password authentication, creating a defense-in-depth approach appropriate for handling sensitive healthcare-adjacent data.

The Authentication Flow

The login process follows a deliberate multi-step sequence:

Step 1 -- Credential Validation. The user submits their email and password on login.cfm. The password is hashed with SHA-512 and compared against the stored hash in the contacts table. Before any MFA code is generated, the system runs a series of authorization rules -- checking company status, facility status, account type restrictions, password expiration policies, and extranet access flags. This prevents wasted MFA emails for users who would be denied access anyway.

Step 2 -- Email-Based MFA. Once credentials pass, a cryptographically random 6-digit code is generated using Java's SecureRandom class (via ColdFusion's Java interop). The code is stored in a dedicated Email_MFA database in the dbo.MFA_Codes table with a 10-minute expiration window, then delivered via SendGrid SMTP. The verification page presents six individual input fields that auto-advance as the user types -- a small UX detail that makes a difference. Codes are single-use, attempt-limited (max 5 tries), and old codes for the same email are invalidated when a new one is issued.

Step 3 -- Session Establishment. After successful MFA verification, session variables are populated with the user's identity, role, company affiliation, and security level. Sessions timeout after 120 minutes. Every step of the process -- credential checks, MFA attempts, successes, failures -- is logged to a dbo.Login_Activity audit table with IP address and user agent tracking.

WebAuthn Passkey Support

Beyond email codes, the system supports WebAuthn passkeys as an alternative authentication method. This was the more technically challenging piece to build. The implementation includes:

  • Registration flow: Four API endpoints handle the WebAuthn ceremony -- generating registration options with ES256/RS256 algorithm support, verifying attestation responses, generating authentication challenges, and verifying assertion signatures.
  • Replay protection: Sign counts are tracked per credential and validated on each authentication to detect cloned authenticators.
  • Challenge management: A dbo.Passkey_Challenges table stores time-limited (5-minute) challenges tied to the user's session, preventing replay attacks.
  • Credential management: Users can register up to 7 passkeys, name them, and the system tracks last-used timestamps. Credentials are scoped to the medicalcollections.com relying party ID for cross-subdomain support.

The client-side JavaScript uses the standard navigator.credentials.create() and navigator.credentials.get() APIs with base64url encoding for binary data transport.

Password Security and Reset

Password resets use UUID tokens with a 1-hour expiration stored in the database. New passwords must meet complexity requirements (8+ characters, at least one number, one capital letter, can't match the current password). The system supports per-company password expiration policies driven by a configurable Password_Reset_Time setting.

Authorization Rules Engine

One of the more practical pieces is auth_rules.cfm -- a rules engine that runs between credential validation and MFA code generation. It checks:

  • Whether the user's account type is allowed portal access
  • Whether their company is active (not inactive or on credit hold)
  • Whether their facility is active and in good standing
  • Whether their company has extranet access enabled
  • Whether their password has expired per company policy
  • Per-user access restrictions (e.g., bank-searches-only accounts)

This layered approach means the system fails fast and gives meaningful error messages before spending resources on MFA delivery.

The Database Architecture

The authentication data spans two contexts: user/company data lives in the main application database (contactscompanyfacilitiessecurity_levels tables), while MFA-specific data lives in a dedicated Email_MFA database containing MFA_CodesLogin_ActivityPasskeysPasskey_Challenges, and Password_Reset_Tokens tables. This separation keeps auth concerns isolated from business data.

What Claude Helped With

Claude was instrumental in architecting the WebAuthn passkey flow -- the binary data handling, challenge-response ceremony, and signature verification logic are areas where having an AI pair programmer that understands the spec saved significant research time. Claude also helped structure the MFA code generation to use SecureRandom instead of ColdFusion's built-in randRange for better cryptographic properties, designed the audit logging strategy, and helped reason through edge cases like concurrent code requests and session fixation.

Key Takeaways

  • ColdFusion's Java interop is underrated for security work -- accessing SecureRandom directly gives you cryptographic-grade randomness without external libraries.
  • Separating authorization rules from authentication keeps the code clean and lets you fail fast with clear error messages.
  • WebAuthn in ColdFusion is achievable but requires careful handling of binary data encoding between JavaScript and CFML.
  • Audit everything. The Login_Activity table has paid for itself multiple times in troubleshooting access issues.
  • SQL Server works well as the backing store for MFA state -- the transactional guarantees around code issuance and validation prevent race conditions that could arise with simpler storage.

 

 
 
 
Attachments (1)