Skip to content

Commit dfce3fe

Browse files
authored
feat(templates): add Verify TOTP (#283)
* Add Verify TOTP template * Add verify-totp .env file explicitly * Add verify-totp to templates.json * Use CDN for qrcode * Remove additional dependency explanation * Update factor verification handling * Update factor verification handling https://www.twilio.com/docs/verify/quickstarts/verify-totp-change-in-api-response-when-authpayload-is-incorrect * remove duplicate files Co-authored-by: Kelley Robinson <[email protected]>
1 parent fdf24d6 commit dfce3fe

14 files changed

+1148
-0
lines changed

templates.json

+5
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@
210210
"name": "Verify Testing Dashboard",
211211
"description": "Helpful dashboard for testing and debugging during your development with Twilio Verify."
212212
},
213+
{
214+
"id": "verify-totp",
215+
"name": "Authenticator app (TOTP) authentication",
216+
"description": "Use authenticator apps like Authy or Google Authenticator that support Time-based One-Time Passwords (TOTP) with the Verify API."
217+
},
213218
{
214219
"id": "verify-retry",
215220
"name": "Verification with Retry Logic",

verify-totp/.env

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# description: SID of your Twilio Verify Service
2+
# format: sid
3+
# link: https://www.twilio.com/console/verify/services
4+
# required: true
5+
VERIFY_SERVICE_SID=

verify-totp/README.md

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Twilio Verify Time-based One-time passwords (TOTP)
2+
3+
This demo of the [Twilio Verify API](https://www.twilio.com/docs/verify/api) includes the TOTP factor type for supporting authenticator apps like Authy or Google Authenticator.
4+
5+
**Verify TOTP is in Pilot, which means that you'll need to [contact sales to request access to the API](https://www.twilio.com/help/sales). We expect to have Verify TOTP in Public Beta (at which point the API will be availble for self service) by the end of 2021.**
6+
7+
## Pre-requisites
8+
9+
* A Verify Service. [Create one in the Twilio Console](https://www.twilio.com/console/verify/services)
10+
11+
### Environment variables
12+
13+
This project requires some environment variables to be set. To keep your tokens and secrets secure, make sure to not commit the `.env` file in git. When setting up the project with `twilio serverless:init ...` the Twilio CLI will create a `.gitignore` file that excludes `.env` from the version history.
14+
15+
In your `.env` file, set the following values:
16+
17+
| Variable | Meaning | Required |
18+
| :------------------- | :---------------------------------------------------------------- | :------- |
19+
| `ACCOUNT_SID` | Find in the [console](https://www.twilio.com/console) | Yes |
20+
| `AUTH_TOKEN` | Find in the [console](https://www.twilio.com/console) | Yes |
21+
| `VERIFY_SERVICE_SID` | Create one [here](https://www.twilio.com/console/verify/services) | Yes |
22+
23+
### Function Parameters
24+
25+
`create-factor.js` expects the following parameters:
26+
27+
| Parameter | Description | Required |
28+
| :------------- | :------------------------------------------ | :------- |
29+
| `name` | An identifier that is used in the authenticator app account name. | Yes |
30+
31+
`verify-new-factor.js` expects the following parameters:
32+
33+
| Parameter | Description | Required |
34+
| :------------------ | :------------------------- | :------- |
35+
| `identity` | Unique identity UUID. Returned from `create-factor` function. | Yes |
36+
| `factorSid` | Starts with `YF`. Returned from `create-factor` function. | Yes |
37+
| `code` | Collected from user input. | Yes |
38+
39+
`verify-new-factor` will also return backup codes in the response.
40+
41+
`create-challenge.js` expects the following parameters:
42+
43+
| Parameter | Description | Required |
44+
| :------------------ | :------------------------- | :------- |
45+
| `identity` | Unique identity UUID. Returned from `create-factor` function. | Yes |
46+
| `factorSid` | Starts with `YF`. Returned from `create-factor` function. | Yes |
47+
| `code` | Collected from user input. | Yes |
48+
49+
50+
## Create a new project with the template
51+
52+
1. Install the [Twilio CLI](https://www.twilio.com/docs/twilio-cli/quickstart#install-twilio-cli)
53+
2. Install the [serverless toolkit](https://www.twilio.com/docs/labs/serverless-toolkit/getting-started)
54+
55+
```shell
56+
twilio plugins:install @twilio-labs/plugin-serverless
57+
```
58+
59+
3. Initiate a new project
60+
61+
```
62+
twilio serverless:init totp-sample-app --template=verify-totp && cd totp-sample-app
63+
```
64+
65+
4. Add your environment variables to `.env`:
66+
67+
Make sure variables are populated in your `.env` file. See [Environment variables](#environment-variables).
68+
69+
5. Start the server :
70+
71+
```
72+
twilio serverless:start
73+
```
74+
75+
5. Open the web page at https://localhost:3000/index.html and enter your phone number to test
76+
77+
ℹ️ Check the developer console and terminal for any errors, make sure you've set your environment variables.
78+
79+
## Deploying
80+
81+
Deploy your functions and assets with either of the following commands. Note: you must run these commands from inside your project folder. [More details in the docs.](https://www.twilio.com/docs/labs/serverless-toolkit)
82+
83+
With the [Twilio CLI](https://www.twilio.com/docs/twilio-cli/quickstart):
84+
85+
```
86+
twilio serverless:deploy
87+
```

verify-totp/assets/helpers.js

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
document.getElementById('session-reset').addEventListener('click', (event) => {
2+
event.preventDefault();
3+
sessionStorage.removeItem('name');
4+
sessionStorage.removeItem('identity');
5+
sessionStorage.removeItem('totpFactorSid');
6+
window.location.reload(false);
7+
});
8+
9+
function hide(element) {
10+
element.style.display = 'none';
11+
}
12+
13+
function hideAll(className) {
14+
Array.from(document.getElementsByClassName(className)).forEach((elem) =>
15+
hide(elem)
16+
);
17+
}
18+
19+
function showExplainer(name) {
20+
hideAll('explainer');
21+
document.getElementById(name).style.display = 'block';
22+
}
23+
24+
function clearStatus() {
25+
hideAll('explainer');
26+
document.getElementById('status').textContent = '';
27+
}
28+
29+
function showStatus(message, color = 'gray') {
30+
clearStatus();
31+
const status = document.getElementById('status');
32+
status.style.color = color;
33+
status.textContent = message;
34+
}
35+
36+
function showError(error) {
37+
console.error(error);
38+
showStatus(error, (color = '#a94442'));
39+
}
40+
41+
function showSessionData() {
42+
const identity = sessionStorage.getItem('identity');
43+
const friendlyName = sessionStorage.getItem('name');
44+
45+
if (identity === null) {
46+
hide(document.getElementById('validate-code'));
47+
} else {
48+
document.getElementById(
49+
'session-data'
50+
).textContent = `Demo is running for username '${friendlyName}' with identity '${identity}'.`;
51+
document.getElementById('validate-code').style.display = 'inline';
52+
}
53+
}
54+
55+
showSessionData();
56+
57+
function clearPage() {
58+
clearStatus();
59+
hideAll('dynamic-render');
60+
hideAll('otp-form');
61+
}

0 commit comments

Comments
 (0)