Skip to main content
RapidDev - Software Development Agency
retool-integrationsREST API Resource

How to Integrate Retool with Duo Security

Connect Retool to Duo Security using a REST API Resource with HMAC-SHA1 signed requests. Duo's Admin API uses integration key and secret key credentials to sign each request. Once configured, you can build MFA administration panels that manage users, view authentication logs, manage enrolled devices, and generate bypass codes for IT security teams.

What you'll learn

  • How to create a Duo Admin API integration and retrieve the integration key, secret key, and API hostname
  • How to implement HMAC-SHA1 request signing for Duo's Admin API in a Retool JavaScript query
  • How to query Duo users, authentication logs, and enrolled devices
  • How to build an MFA administration panel with user management and device enrollment tracking
  • How to generate bypass codes for users from a Retool operations interface
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate16 min read25 minutesAuthLast updated April 2026RapidDev Engineering Team
TL;DR

Connect Retool to Duo Security using a REST API Resource with HMAC-SHA1 signed requests. Duo's Admin API uses integration key and secret key credentials to sign each request. Once configured, you can build MFA administration panels that manage users, view authentication logs, manage enrolled devices, and generate bypass codes for IT security teams.

Quick facts about this guide
FactValue
ToolDuo Security
CategoryAuth
MethodREST API Resource
DifficultyIntermediate
Time required25 minutes
Last updatedApril 2026

Build an MFA Administration Panel with Duo Security and Retool

Duo Security protects thousands of enterprise applications with multi-factor authentication, but managing users at scale — resetting devices, issuing bypass codes, reviewing authentication logs, and auditing enrolled devices — typically requires IT administrators to navigate Duo's admin console one user at a time. For IT security teams managing hundreds or thousands of users, a Retool-based Duo admin panel provides bulk operations, custom filtering, and integrated workflows that Duo's native interface does not support.

The technical challenge with Duo is that its Admin API does not use simple Bearer token authentication. Instead, every request must be signed with HMAC-SHA1 using your integration key and secret key, following a specific canonical request format that includes the HTTP method, date, API hostname, path, and sorted parameters. In Retool, this signing logic is implemented in a JavaScript query that constructs the Authorization header before making the API call.

Once the signing pattern is in place, the full Duo Admin API becomes available: list users with their enrolled devices, view per-user authentication history, create and delete bypass codes for emergency access, manage enrolled phones and hardware tokens, and pull audit logs for compliance reporting. A well-built Retool admin panel can reduce the time IT staff spend in the Duo console by providing a faster, searchable, bulk-operation-capable interface tailored to your team's specific workflows.

Integration method

REST API Resource

Duo Security's Admin API uses HMAC-SHA1 request signing rather than a simple Bearer token. Each request must include a Date header and an Authorization header containing a signature computed from the request parameters using your integration key and secret key. In Retool, you implement this signing logic in a JavaScript query that constructs and signs each request, then calls the API via the REST API Resource.

Prerequisites

  • A Duo Security account with Admin API access (requires Duo Beyond or Duo Access plan or higher)
  • Permission to create Admin API integrations in the Duo Admin Panel
  • A Retool account (Cloud or self-hosted) with permission to create Resources and JavaScript queries
  • Basic understanding of HMAC request signing concepts and JavaScript crypto libraries
  • The Duo Admin API integration key (ikey), secret key (skey), and API hostname from your Duo Admin Panel

Step-by-step guide

1

Create a Duo Admin API integration

Before configuring Retool, you need to create an Admin API integration in Duo. Log into your Duo Admin Panel at admin.duosecurity.com. In the left sidebar, navigate to Applications → Protect an Application. Search for 'Admin API' in the application list and click 'Protect' next to it. Duo creates a new Admin API integration and shows you the configuration page. On this page, you will find three critical values: the Integration Key (ikey, formatted like DIxxxxxxxxxxxxxxxxxx), the Secret Key (skey, a long string — treat this like a password), and the API Hostname (formatted like api-xxxxxxxx.duosecurity.com). Copy all three values and store them securely — you will need them in Retool. On the same page, configure the API access permissions. Under 'Settings', check which grant types your Retool app needs: 'Grant read information' allows listing users and devices, 'Grant write resource' allows creating bypass codes and modifying users, and 'Grant read log' allows accessing authentication logs. Enable the minimum required grants for your use case — avoid enabling grants you do not need. Click 'Save' at the bottom. The integration is now active. Note that Duo Admin API credentials are extremely sensitive — they grant programmatic access to your entire Duo deployment. Store the secret key only in Retool's configuration variables system and never commit it to code or share it in chat.

Pro tip: Create a dedicated Admin API integration for Retool rather than sharing credentials with another application. This allows you to revoke Retool's access independently if needed, and makes audit logs easier to interpret.

Expected result: A Duo Admin API integration is created with the integration key, secret key, and API hostname saved in your credential storage, and the appropriate grants enabled.

2

Store Duo credentials as Retool configuration variables

Duo Admin API credentials must never be exposed to browser clients. Store them as secret configuration variables in Retool so they can only be accessed server-side in resource configurations and workflows. In Retool, navigate to the Settings section (gear icon or admin panel) and click 'Configuration Variables'. Click 'Add new variable'. Create three variables: DUO_IKEY for the integration key, DUO_SKEY for the secret key (mark this one as 'secret' by toggling the secret option — secret variables are never exposed to the frontend or visible in network requests), and DUO_HOST for the API hostname (e.g., api-xxxxxxxx.duosecurity.com). After creating all three, navigate to the Resources tab and create a new REST API resource. Set the Base URL to https://{{ retoolContext.configVars.DUO_HOST }} — or enter the full hostname directly if configuration variable interpolation is not available in the base URL field (in that case, enter it as https://api-xxxxxxxx.duosecurity.com). Leave authentication as 'None' — you will handle authentication in JavaScript queries because Duo requires dynamic HMAC signing rather than a static token. Save the resource as 'Duo Admin API'. You will build the HMAC signing logic in the next step as a reusable JavaScript query pattern.

Pro tip: Mark DUO_SKEY as a 'secret' configuration variable in Retool. Secret variables are restricted to resource configurations and workflows — they cannot be read by frontend app queries or transformers, providing an additional layer of protection.

Expected result: Three configuration variables (DUO_IKEY, DUO_SKEY, DUO_HOST) are created in Retool settings. A REST API resource named 'Duo Admin API' is saved with the correct base URL.

3

Implement HMAC-SHA1 request signing in a JavaScript query

Duo's Admin API requires every request to be signed using HMAC-SHA1. The signing process follows a strict canonical format. In your Retool app, create a new JavaScript query (not a resource query — click '+ New query' → 'Run JavaScript code'). The signing algorithm works as follows: construct a canonical string by joining the current date (in RFC 2822 format), the HTTP method in uppercase, the API hostname in lowercase, the API path, and URL-encoded sorted query parameters — all joined by newline characters. Then compute an HMAC-SHA1 hash of this canonical string using your secret key. Include the result in an Authorization header as 'Basic ' followed by a Base64-encoded string of '{ikey}:{hmac_signature}'. Also include the Date header with the same date string used in signing. In Retool, you can use the built-in btoa() for Base64 encoding, but HMAC-SHA1 requires the crypto-js library. Import it at the top of your JavaScript query using const CryptoJS = require('crypto-js'). Write a helper function named signDuoRequest that accepts method, path, params, and returns the signed headers object. Then call your Duo Admin API resource with these headers appended. Structure the JavaScript query to accept parameters for the specific endpoint and return the parsed response data for use in the rest of your app.

duo-signed-request.js
1// Duo HMAC-SHA1 signed request helper
2const CryptoJS = require('crypto-js');
3
4const ikey = retoolContext.configVars.DUO_IKEY;
5const skey = retoolContext.configVars.DUO_SKEY;
6const host = retoolContext.configVars.DUO_HOST;
7
8const method = 'GET';
9const path = '/admin/v1/users';
10const params = { limit: '100', offset: '0' };
11
12// Build date string
13const date = new Date().toUTCString();
14
15// Build canonical string
16const sortedParams = Object.keys(params)
17 .sort()
18 .map(k => `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`)
19 .join('&');
20
21const canon = [
22 date,
23 method.toUpperCase(),
24 host.toLowerCase(),
25 path,
26 sortedParams
27].join('\n');
28
29// Compute HMAC-SHA1
30const sig = CryptoJS.HmacSHA1(canon, skey).toString(CryptoJS.enc.Hex);
31const auth = btoa(`${ikey}:${sig}`);
32
33// Make the request via fetch (Retool JS queries can use fetch)
34const url = new URL(`https://${host}${path}`);
35Object.entries(params).forEach(([k, v]) => url.searchParams.append(k, v));
36
37const response = await fetch(url.toString(), {
38 method: method,
39 headers: {
40 'Authorization': `Basic ${auth}`,
41 'Date': date,
42 'Content-Type': 'application/x-www-form-urlencoded'
43 }
44});
45
46const json = await response.json();
47return json.response || json;

Pro tip: The Date header value must be the same string used in the canonical signing string. Generate it once with new Date().toUTCString() and reuse it in both the canonical string and the request header.

Expected result: The JavaScript query runs successfully and returns a JSON response from Duo's Admin API with a 'response' array of user objects. The query appears in the Code panel and can be referenced by other components.

4

Build the user management panel

With the HMAC signing pattern established, adapt the JavaScript query to create modular queries for different Duo Admin API endpoints. Create a getDuoUsers query by modifying the path to /admin/v1/users and the params to include search, limit, and offset. Create a getUserDetails query with path /admin/v1/users/{{ usersTable.selectedRow.user_id }}. Create a getAuthLogs query with path /admin/v1/logs/authentication and params for mintime (Unix timestamp from a DatePicker component) and maxtime. Each of these is a separate JavaScript query with the same HMAC signing header construction. After creating queries, build the UI: drag a Table component onto the canvas, set its Data source to {{ getDuoUsers.data }}. Configure columns for username, email, status (active, bypass, disabled), realname, and enrolled devices count. Add a TextInput above the table for searching by username and wire it to the search parameter in getDuoUsers. When a row is selected, display a detail Container on the right showing the user's enrolled devices (phones, tablets, hardware tokens) fetched by getUserDetails. Add buttons to the detail panel for common admin actions: 'Generate Bypass Code', 'Disable User', and 'Reset Enrollment' — each wired to a corresponding POST or DELETE JavaScript query. For compliance reporting and complex multi-user audit workflows, RapidDev's team can help architect a comprehensive Retool security operations dashboard.

transformer.js
1// Transformer: flatten Duo user list for table display
2const users = data || [];
3return users.map(user => ({
4 user_id: user.user_id,
5 username: user.username,
6 realname: user.realname || 'N/A',
7 email: user.email || 'N/A',
8 status: user.status,
9 enrolled_devices: (user.phones || []).length + (user.tokens || []).length,
10 last_login: user.last_login
11 ? new Date(user.last_login * 1000).toLocaleDateString()
12 : 'Never',
13 created: new Date(user.created * 1000).toLocaleDateString()
14}));

Pro tip: Duo returns Unix timestamps (seconds since epoch) for date fields like created and last_login. Multiply by 1000 before passing to JavaScript's Date constructor, which expects milliseconds.

Expected result: The users Table displays all Duo users with status, device count, and last login information. Clicking a row shows the detail panel with enrolled devices and admin action buttons.

5

Add authentication log viewer and bypass code generation

Complete the MFA admin panel by adding authentication log viewing and bypass code management. For the auth log viewer, add two DatePicker components to the canvas for selecting a date range. Create a getAuthLogs JavaScript query that converts the DatePicker values to Unix timestamps (divide JavaScript Date.getTime() by 1000, round to integer) and passes them as mintime and maxtime parameters to the /admin/v1/logs/authentication endpoint. Include a users filter parameter set to {{ userSearchInput.value }} if provided. Drag a second Table component and bind it to {{ getAuthLogs.data }}. Configure columns for timestamp (convert Unix to locale string), username, application, factor (push, phone, passcode), and result (success, denied, fraud). Add a result filter Select dropdown above the table wired to a client-side filter: {{ getAuthLogs.data.filter(log => !resultFilter.value || log.result === resultFilter.value) }}. For bypass codes, add a 'Generate Bypass Code' Button below the user detail panel. Wire it to a JavaScript query that signs a POST request to /admin/v1/users/{user_id}/bypass_codes with a payload specifying count (number of codes) and valid_secs (expiration in seconds). On success, trigger a refresh of the user details query and show a notification displaying the generated codes. The codes appear once in the API response — display them in a Modal component so the helpdesk agent can copy them before they close the dialog.

generate-bypass-code.js
1// Generate bypass code for selected user
2const CryptoJS = require('crypto-js');
3
4const ikey = retoolContext.configVars.DUO_IKEY;
5const skey = retoolContext.configVars.DUO_SKEY;
6const host = retoolContext.configVars.DUO_HOST;
7const userId = usersTable.selectedRow.user_id;
8
9const method = 'POST';
10const path = `/admin/v1/users/${userId}/bypass_codes`;
11const params = { count: '1', valid_secs: '3600' };
12
13const date = new Date().toUTCString();
14const sortedParams = Object.keys(params).sort()
15 .map(k => `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`).join('&');
16const canon = [date, method, host.toLowerCase(), path, sortedParams].join('\n');
17const sig = CryptoJS.HmacSHA1(canon, skey).toString(CryptoJS.enc.Hex);
18const auth = btoa(`${ikey}:${sig}`);
19
20const response = await fetch(`https://${host}${path}`, {
21 method: 'POST',
22 headers: {
23 'Authorization': `Basic ${auth}`,
24 'Date': date,
25 'Content-Type': 'application/x-www-form-urlencoded'
26 },
27 body: sortedParams
28});
29
30return await response.json();

Pro tip: Bypass codes returned by Duo's API are only shown once. Display them immediately in a Modal component so the helpdesk agent can copy them to the user — after the modal is closed, codes cannot be retrieved via the API.

Expected result: The auth log viewer shows filterable authentication events by date range and user. The bypass code button successfully generates and displays a temporary code for the selected user. The user detail panel refreshes to show the new bypass code entry.

Common use cases

Build a user device enrollment monitoring panel

Your IT team needs to verify that all active directory users have enrolled a Duo device before a mandatory MFA deadline. A Retool app queries Duo for all users, cross-references enrollment status, and displays a table showing who has enrolled and who has not — with a send-enrollment-reminder button that triggers a notification via a connected messaging resource.

Retool Prompt

Build an MFA enrollment dashboard that lists all Duo users with columns for username, email, enrollment status, number of enrolled devices, and last authentication date. Add a filter to show only users with no enrolled devices. Include a 'Send Enrollment Reminder' button that fires a POST to a Slack Resource to message the user's manager.

Copy this prompt to try it in Retool

Create an authentication log audit dashboard

For compliance and security investigations, your SecOps team needs to quickly search Duo authentication logs by user, application, result (success, denied, fraud), and time range. A Retool app queries Duo's authentication logs endpoint with filter parameters and displays results in a searchable Table with Chart components showing authentication patterns over time.

Retool Prompt

Build a Duo authentication log viewer with date range pickers, a user email search input, a result filter dropdown (success, denied, fraud), and an application name filter. Display matching log entries in a Table with columns for timestamp, user, application, factor used, and result. Add a Line Chart showing authentication volume by hour.

Copy this prompt to try it in Retool

Build a bypass code management panel

When employees lock themselves out of Duo during travel or device loss, your IT helpdesk needs to quickly generate temporary bypass codes. A Retool panel lets helpdesk staff search for a user, view their current bypass codes, generate a new code with a specified number of uses, and delete old codes — all without needing full Duo admin console access.

Retool Prompt

Build a bypass code management panel with a user search input that fetches the matching Duo user. Display their current bypass codes in a Table showing code ID, uses remaining, and expiration. Add a 'Generate Bypass Code' button that calls the POST /admin/v1/users/{user_id}/bypass_codes endpoint. Add a Delete button for each row.

Copy this prompt to try it in Retool

Troubleshooting

API returns 40103 'Invalid signature' error

Cause: The HMAC-SHA1 signature does not match. This is typically caused by a mismatch between the Date header value and the date string used in the canonical signing string, parameters not being sorted alphabetically, or the secret key being incorrectly stored.

Solution: Verify that the exact same date string (new Date().toUTCString()) is used in both the canonical string and the Date request header — generate it once and assign to a const. Confirm parameters are sorted alphabetically by key before building the canonical string. Verify the DUO_SKEY configuration variable contains the full secret key without trailing whitespace. Test with a simple GET /admin/v1/users request with no parameters first to isolate the signing logic.

typescript
1// Ensure date is generated once and reused
2const date = new Date().toUTCString();
3// Use the same 'date' variable in BOTH the canonical string and the header
4const canon = [date, method, host.toLowerCase(), path, sortedParams].join('\n');
5// ...
6headers: { 'Date': date, ... }

API returns 40301 'Insufficient permissions' for specific operations

Cause: The Admin API integration in Duo does not have the required grants enabled for the operation being attempted. For example, creating bypass codes requires the 'Grant write resource' permission.

Solution: Log into the Duo Admin Panel at admin.duosecurity.com → Applications → find your Retool Admin API integration → click on it and review the enabled grants. Enable the specific grant required for your operation: 'Grant read information' for listing users/devices, 'Grant write resource' for creating/deleting bypass codes, 'Grant read log' for authentication logs. Save and retry the query.

Request returns 40002 'Clock skew too large' error

Cause: The Date header in the request is more than 5 minutes off from Duo's server time. Duo rejects requests with timestamps outside a ±5 minute window to prevent replay attacks.

Solution: Ensure the Retool server or the client machine running the JavaScript query has accurate system time synchronized via NTP. In Retool Cloud, this is automatically handled. For self-hosted Retool, verify the server's time zone and NTP configuration. The Date must be in RFC 2822 format — use new Date().toUTCString() which generates the correct format.

Users list is empty or returns fewer users than expected

Cause: Duo's API paginates results at 100 users per request by default. If your organization has more than 100 Duo users, additional pages must be fetched using the offset parameter.

Solution: Check the response from getDuoUsers for a metadata object containing total_count and next_offset fields. If next_offset is present, make additional requests with offset set to that value until all pages are retrieved. Implement pagination in Retool's Table component using server-side pagination, passing Table's paginationOffset to the offset parameter in your query.

Best practices

  • Store all three Duo credentials (ikey, skey, host) as Retool configuration variables — mark the secret key as 'secret' so it cannot be accessed by frontend queries or displayed in Retool's state panel.
  • Create a dedicated Admin API integration in Duo specifically for Retool, separate from integrations used by other tools. This allows independent revocation and makes audit logs easier to attribute.
  • Enable only the minimum Duo grants required for your Retool app: if the app is read-only, enable only 'Grant read information' and 'Grant read log' — never enable 'Grant administrator' unless absolutely necessary.
  • Implement request logging in your JavaScript queries by capturing the endpoint path, timestamp, and user who triggered the action (using current_user.email in Retool) and writing it to Retool Database or a connected PostgreSQL table for audit trails.
  • Use Retool's Permissions feature to restrict access to the Duo admin app to IT security team members only — do not expose bypass code generation or user disable actions to general employees.
  • Add a confirmation modal before executing destructive actions like disabling users or deleting bypass codes — wire a Modal component's 'Confirm' button to the actual action query to prevent accidental operations.
  • Test the HMAC signing logic with a read-only endpoint like GET /admin/v1/users before implementing write operations, to confirm the signing pattern is working correctly before exposing mutation buttons.

Alternatives

Frequently asked questions

Why does Duo require HMAC signing instead of a simple API key?

Duo uses HMAC-SHA1 request signing to prevent replay attacks — a signed request includes the current timestamp, so a stolen request cannot be reused after a few minutes. This is a stronger security model than static Bearer tokens, which remain valid indefinitely until revoked. For a tool managing enterprise MFA for potentially thousands of users, this additional security is appropriate.

Can I use Duo's user sync API to pull in users from Active Directory instead of listing all Duo users?

Yes. Duo's Admin API includes directory sync endpoints under /admin/v1/users and /admin/v1/groups that can be queried to list users synced from Active Directory or LDAP. The same HMAC-SHA1 signing pattern applies. Use the status filter parameter to distinguish between Active Directory-synced users and manually-created Duo users.

How do I implement pagination for large organizations with thousands of Duo users?

Duo's API returns up to 100 users per request and includes a metadata.next_offset field in the response when more pages are available. In Retool, enable server-side pagination on the users Table component and pass the Table's paginationOffset to the offset parameter in your signed JavaScript query. The query fetches only the current page each time the user navigates, keeping response times fast regardless of total user count.

Is it safe to store the Duo secret key in Retool?

Yes, when stored as a secret configuration variable in Retool (Settings → Configuration Variables, marked as secret). Secret config vars are never exposed to browser clients, cannot be read by frontend JavaScript queries, and are only accessible server-side in resource configurations and workflows. Retool's architecture ensures these values are encrypted at rest and in transit.

Can Retool automate Duo authentication log review on a schedule?

Yes, using Retool Workflows. Create a Workflow with a Schedule trigger that runs your HMAC-signed Duo authentication log query nightly. Configure the workflow to filter for denied or fraud authentication events, and trigger a Slack or email notification when anomalies are detected. Workflows run server-side on Retool's infrastructure, so the HMAC signing JavaScript runs in a server context just as it does in app queries.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Integrations are where projects stall

We wire Retool integrations like this one every week — auth, webhooks, edge cases included. Fixed-price builds from $13K, delivered in 6–10 weeks.

Talk to an integration engineer

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.