Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion templates.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@
{
"id": "verify-totp",
"name": "Authenticator app (TOTP) authentication",
"description": "Use authenticator apps like Authy or Google Authenticator that support Time-based One-Time Passwords (TOTP) with the Verify API."
"description": "Two-factor authentication (2FA) with authenticator apps like Google Authenticator or Authy, using TOTP and the Verify API."
},
{
"id": "verify-totp-sms",
Expand Down
1 change: 1 addition & 0 deletions verify-totp/.github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Refer to [AGENTS.md](../AGENTS.md) for all repo instructions.
84 changes: 84 additions & 0 deletions verify-totp/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Authenticator App (TOTP) Authentication with Twilio Verify

Serverless two-factor authentication (2FA) using the Twilio Verify API's TOTP factor, so users can enroll an authenticator app (Google Authenticator, Microsoft Authenticator, Authy, 1Password) by scanning a QR code and then authenticate with the 6-digit time-based code it generates.

## Environment Variables

`.env` ships with the template. `twilio serverless:init` populates `ACCOUNT_SID` and `AUTH_TOKEN` from your Twilio CLI profile; you must fill in `VERIFY_SERVICE_SID` yourself. Never commit `.env`.

| Variable | Where to find | Format |
| -------- | ------------- | ------ |
| `ACCOUNT_SID` | [Console](https://console.twilio.com) homepage — auto-populated by `serverless:init` | Starts with `AC` |
| `AUTH_TOKEN` | Console homepage → click to reveal — auto-populated by `serverless:init` | 32-char string. Treat as a password. |
| `VERIFY_SERVICE_SID` | Console → Verify → Services (create one if none exists) | Starts with `VA` |

## Commands

```bash
# Install the Twilio CLI serverless plugin (once)
twilio plugins:install @twilio-labs/plugin-serverless

# Initialize a new project from this template
twilio serverless:init totp-sample-app --template=verify-totp && cd totp-sample-app
# Then add VERIFY_SERVICE_SID to .env

# Run locally at http://localhost:3000/index.html
twilio serverless:start

# Test (from the function-templates repo root)
npm test verify-totp

# Deploy
twilio serverless:deploy
```

No Twilio webhooks are involved — the browser calls the Functions directly, so ngrok is not needed.

## Project Structure

```
functions/
create-factor.js # Creates a TOTP factor; returns identity, factorSid, otpauth URI, and secret
verify-new-factor.js # Completes enrollment by validating the first code from the authenticator app
create-challenge.js # Ongoing authentication: creates a challenge with a code the user supplies
assets/
index.html # Demo UI: QR code enrollment, factor verification, ongoing challenges
helpers.js # Public browser helpers (status messages, sessionStorage state)
utils.private.js # Server-side only: detectMissingParams (private assets are not web-accessible)
tests/ # Jest tests for all three functions
```

## Agent Boundaries

**Always:**

- Confirm `.env` is configured before running any command
- Use the Environment Variables section to guide the user to each credential — don't ask them to find values without direction
- Create a Verify Service first if the user has no `VERIFY_SERVICE_SID` (Console → Verify → Services)
- Confirm the app is running before asking the user to test it
- Use `--template=verify-totp` when initializing a new project
- Keep `identity` a random, opaque value (the template uses `uuidv4()`) — Verify entity identities must not contain PII
- Keep server-only helpers in `*.private.js` assets so they are not served to the browser

**Never:**

- Run the app with missing or placeholder credentials
- Hardcode credentials, secrets, or TOTP seeds in source files
- Log or persist the `secret` / `uri` returned by `create-factor` beyond showing the QR code once during enrollment
- Assume an unverified factor persists — unverified factors are deleted between 1 and 24 hours after creation, so re-enroll rather than reusing a stale `factorSid`

## Verify It's Working

1. Open http://localhost:3000/index.html and enter a username, then click "Set up two-factor authentication" — a QR code and a text secret appear.
2. Scan the QR code (or type the secret) into an authenticator app, then enter the 6-digit code to verify the new factor. Success shows "Factor setup complete!" in green.
3. Enter a fresh code from the authenticator app in the ongoing authentication form — a valid code returns "Verification success." and an invalid or expired one returns "Incorrect token."

Errors surface in the page status line and the browser console; a 400 with "Missing parameter" means the request omitted `identity`, `factorSid`, or `code`.

## Twilio Resources

- [Twilio Console](https://console.twilio.com) — credentials and Verify Service configuration
- [Verify TOTP Quickstart](https://www.twilio.com/docs/verify/quickstarts/totp) — end-to-end walkthrough and TOTP service settings
- [Verify Factor API](https://www.twilio.com/docs/verify/api/factor) — creating and verifying factors
- [Verify Challenge API](https://www.twilio.com/docs/verify/api/challenge) — ongoing authentication
- [What is TOTP?](https://www.twilio.com/docs/glossary/totp) — how time-based codes work
1 change: 1 addition & 0 deletions verify-totp/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
9 changes: 8 additions & 1 deletion verify-totp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ This demo of the [Twilio Verify API](https://www.twilio.com/docs/verify/api) inc
## Pre-requisites

* A Verify Service. [Create one in the Twilio Console](https://www.twilio.com/console/verify/services)
* An authenticator app such as [Authy](https://authy.com/download/), Google Authenticator or Microsoft Authenticator

### Environment variables

Expand Down Expand Up @@ -70,7 +71,7 @@ Make sure variables are populated in your `.env` file. See [Environment variable
twilio serverless:start
```

5. Open the web page at https://localhost:3000/index.html and enter your phone number to test
6. Open the web page at http://localhost:3000/index.html and enter a username to set up your authenticator app

ℹ️ Check the developer console and terminal for any errors, make sure you've set your environment variables.

Expand All @@ -83,3 +84,9 @@ With the [Twilio CLI](https://www.twilio.com/docs/twilio-cli/quickstart):
```
twilio serverless:deploy
```
## Related resources

* [Verify TOTP Quickstart](https://www.twilio.com/docs/verify/quickstarts/totp) — step-by-step tutorial, including the TOTP settings (issuer, code length, time skew) on your Verify Service
* [Verify Factor API reference](https://www.twilio.com/docs/verify/api/factor) and [Challenge API reference](https://www.twilio.com/docs/verify/api/challenge) — the two resources these Functions call
* [How to use the Authy API with Google Authenticator](https://www.twilio.com/en-us/blog/developers/tutorials/product/authy-api-and-google-authenticator)
* [Verify API overview](https://www.twilio.com/docs/verify/api) — all supported verification channels
13 changes: 13 additions & 0 deletions verify-totp/package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
{
"name": "verify-totp",
"version": "0.0.1",
"description": "Two-factor authentication with authenticator apps using time-based one-time passwords (TOTP) and the Twilio Verify API",
"keywords": [
"twilio",
"verify",
"totp",
"2fa",
"two-factor-authentication",
"authenticator-app",
"google-authenticator",
"authy",
"serverless"
],
"private": true,
"dependencies": {
"twilio": "^3.67.2",
Expand Down