Implementing Node.js OTP/2FA with Express and AWS SNS - code-examples -

Frequently Asked Questions

Use the AWS SDK for JavaScript v3 (@aws-sdk/client-sns) to interact with the SNS service. Configure the SNSClient with your AWS credentials and region. The sendSms function in the provided snsService.js example demonstrates how to publish SMS messages using the PublishCommand, including setting the message type (Transactional or Promotional).
The AWS SDK for JavaScript v3 (@aws-sdk/client-sns) is the recommended way to integrate with AWS SNS in Node.js projects. It offers a modular architecture, improved performance, and better security compared to previous versions.
Transactional SMS messages have higher delivery priority and are more likely to reach users, even those on Do Not Disturb (DND) lists. This makes them ideal for time-sensitive messages like OTPs, ensuring users receive their codes promptly, though they may cost slightly more than Promotional messages.
You should move your AWS account out of the SNS sandbox when you're ready to send SMS messages to unverified phone numbers and need higher spending limits. While in the sandbox, you can only send SMS to verified numbers and have restricted spending.
No, an in-memory store like a JavaScript Map is not suitable for production OTP storage. Data will be lost if the server restarts. Use a persistent store like Redis or DynamoDB for production environments to maintain OTP data reliably.
The provided otpService.js example uses crypto.randomInt to generate secure OTPs of a configurable length (OTP_LENGTH). It pads the OTP with leading zeros to maintain a consistent format.
You need an AWS account, Node.js and npm installed, basic understanding of Node.js, Express, and REST APIs, and access to a phone number for testing.
The verifyOtp function in otpService.js handles OTP verification. It retrieves the stored OTP, checks expiry and attempts remaining. If the submitted OTP matches the stored value, it marks the OTP as used. If the attempt is unsuccessful the number of allowed attempts is decreased.
Rate limiting is crucial to prevent SMS pumping fraud and brute-force attacks. It limits the number of OTP requests and verification attempts from a given IP address within a specified time window.
E.164 is an international standard for phone number formatting, ensuring consistent representation of numbers. It's required by AWS SNS for sending SMS messages and helps avoid formatting issues.
Use keys like otp:{phoneNumber} to store OTP data in Redis. Store data as a JSON string or Redis Hash including the OTP, attempts remaining, and set a TTL for automatic expiry.
Use short expiry times, CSPRNG for generation, avoid logging OTPs in production, ensure single-use, enforce E.164 format, and implement rate limiting.
The snsService.js example includes checks for specific SNS errors like InvalidParameterException and AuthorizationErrorException, providing clearer feedback if sending fails.
Redis is recommended due to its speed and TTL features, which align well with OTP requirements. A SQL database with proper indexing and cleanup mechanisms could also be used if you need more structured data storage.