Skip navigation
Documentation

Duo Auth API

Last Updated: April 4th, 2024

The Duo Auth API is a low-level, RESTful API for adding strong two-factor authentication to your website or application. Check out the Duo Two-Factor Authentication API for Applications Solution Guide for an Auth API tutorial.

About the Auth API

Duo's Auth API is available in the Duo Premier, Duo Advantage, Duo Essentials, and Duo Free plans.

Documented properties will not be removed within a stable version of the API. Once a given API endpoint is documented to return a given property, a property with that name will always appear (although certain properties may only appear under certain conditions, like if the customer is using a specific edition). When Duo deprecates a property, the API continues to accept that property in requests, although it no longer has any effect.

Properties that enumerate choices may gain new values at any time. Duo may cease to return legacy values for properties as well. Duo will update our API documentation with changes to property values in a timely fashion, adding new property values or indicating changes to existing property values.

New, undocumented properties may also appear at any time. For instance, Duo may make available a beta feature involving extra information returned by an API endpoint. Until the property is documented here its format may change or it may even be entirely removed from our API.

Please note that all Unix timestamps are in seconds, except where noted.

First Steps

Before starting:

  1. Sign up for a Duo account.

  2. Log in to the Duo Admin Panel and navigate to Applications.

  3. Click Protect an Application and locate the entry for Auth API in the applications list. Click Protect to the far-right to configure the application and get your integration key, secret key, and API hostname. You'll need this information to complete your setup. See Protecting Applications for more information about protecting applications in Duo and additional application options.

    Treat your secret key like a password
    The security of your Duo application is tied to the security of your secret key (skey). Secure it as you would any sensitive credential. Don't share it with unauthorized individuals or email it to anyone under any circumstances!

Connectivity Requirements

This application communicates with Duo's service on SSL TCP port 443.

Firewall configurations that restrict outbound access to Duo's service with rules using destination IP addresses or IP address ranges aren't recommended, since these may change over time to maintain our service's high availability. If your organization requires IP-based rules, please review Duo Knowledge Base article 1337.

Effective June 30, 2023, Duo no longer supports TLS 1.0 or 1.1 connections or insecure TLS/SSL cipher suites. See Duo Knowledge Base article 7546 for additional guidance.

Review the API Details to see how to construct your first API request. Adding Duo requires some understanding of your application's language and authentication process.

API Clients

Duo Security has demonstration clients available on GitHub to call the Duo API methods.

Endpoints

/ping

The /ping endpoint acts as a "liveness check" that can be called to verify that Duo is up before trying to call other Auth API endpoints. Unlike the other endpoints, this one does not have to be signed with the Authorization header.

This endpoint is also suitable for use with Duo's v2 Web SDK to verify that Duo's service is responding before initializing frame authentication.

GET /auth/v2/ping

Parameters

None.

Response Codes

Response Meaning
200 Success.

Response Format

Key Value
time Current server time. Formatted as a UNIX timestamp. Integer.

Example Response

{
  "stat": "OK",
  "response": {
    "time": 1357020061
  }
}

/check

The /check endpoint can be called to verify that the Auth API integration and secret keys are valid, and that the signature is being generated properly.

This endpoint is also suitable for use with Duo's v2 Web SDK to verify integration information before initializing frame authentication.

GET /auth/v2/check

Parameters

None required.

Response Codes

Response Meaning
200 Success.
401 The "Authorization" and/or "Date" headers were missing or invalid.

Response Format

Key Value
time Current server time. Formatted as a UNIX timestamp. Integer.

Example Response

{
  "stat": "OK",
  "response": {
    "time": 1357020061
  }
}

/logo

The /logo endpoint provides a programmatic way to retrieve your stored logo.

GET /auth/v2/logo

Parameters

None required.

Response Codes

Response Meaning
200 Success.
404 No logo was found.

Response Format

On success, the response body is Content-Type image/png, containing the logo.

On failure, the response is the standard error JSON.

/enroll

The /enroll endpoint provides a programmatic way to enroll new users with Duo two-factor authentication. It creates the user in Duo and returns a code (as a QR code) that Duo Mobile can scan with its built-in camera. Scanning the QR code adds the user's account to the app so that they receive and respond to Duo Push login requests. This endpoint may be limited by an effective new user policy. For example, if an Auth API application has an effective "New User policy" set to Deny access, you will not be able to use this enrollment endpoint, and will receive a deny response instead of an enrollment link.

POST /auth/v2/enroll

Parameters

Parameter Required? Description
username Optional Username for the created user. If not given, a random username will be assigned and returned.
valid_secs Optional Seconds for which the activation code will remain valid. Default: 86400 (one day).

Response Codes

Response Meaning
200 Success.
400 Invalid or missing parameters, or a user with username already exists.

Response Format

Key Value
activation_barcode URL for an image of a scannable QR code with the activation code.
activation_code Code to enter into the Duo Mobile app to add the account. On phones with Duo Mobile already installed it will be a clickable link.
expiration Time at which this activation code will expire. Formatted as a UNIX timestamp. Integer.
user_id Permanent, unique identifier for the user in Duo. Always generated.
username Unique name for the user in Duo. Either specified as a parameter or auto-generated.

Example Response

{
  "stat": "OK",
  "response": {
    "activation_barcode": "https://api-eval.duosecurity.com/frame/qr?value=8LIRa5danrICkhHtkLxi-cKLu2DWzDYCmBwBHY2YzW5ZYnYaRxA",
    "activation_code": "duo://8LIRa5danrICkhHtkLxi-cKLu2DWzDYCmBwBHY2YzW5ZYnYaRxA",
    "expiration": 1357020061,
    "user_id": "DU94SWSN4ADHHJHF2HXT",
    "username": "49c6c3097adb386048c84354d82ea63d"
  }
}

If a new user policy which denies access to unenrolled users was effective on the Auth API application:

{
  "response": {
        "result": "deny",
        "status": "Access is not allowed because you are not enrolled in Duo. Please contact your organization's IT help desk."},
        "stat": "OK"}

/enroll_status

The /enroll_status endpoint checks whether a user has completed enrollment. This endpoint may be limited by an effective new user policy. For example, if an Auth API application has an effective "New User policy" set to Deny access, you will not be able to use this enrollment endpoint, and will receive a deny response instead of an enrollment link.

POST /auth/v2/enroll_status

Parameters

Parameter Required? Description
user_id Required ID of the user.
activation_code Required Activation code, as returned from /enroll.

Response Codes

Response Meaning
200 Success.
400 Invalid or missing parameters.

Response Format

One of the following strings:

Value Meaning
success The user successfully added the account to Duo Mobile.
invalid The code is expired or otherwise not valid for the specified user.
waiting The code has not been claimed yet.

Example Response

{
  "stat": "OK",
  "response": "success"
}

If a new user policy which denies access to unenrolled users was effective on the Auth API application:

{
  "response": {
        "result": "deny",
        "status": "Access is not allowed because you are not enrolled in Duo. Please contact your organization's IT help desk."},
        "stat": "OK"}

/preauth

The /preauth endpoint determines whether a user is authorized to log in, and (if so) returns the user's available authentication factors.

POST /auth/v2/preauth

Parameters

Param Required? Description
user_id Required if username is not specified Permanent, unique identifier for the user as generated by Duo upon user creation (e.g. DUYHV6TJBC3O4RITS1WC).

Exactly one of user_id or username must be specified.
username Required if user_id is not specified Unique identifier for the user that is commonly specified by your application during user creation (e.g. user@domain.com). This value may also represent a username alias assigned to a user

Exactly one of user_id or username must be specified.
client_supports_verified_push Optional

Provide this parameter with a value of 1 if your client supports Verified Duo Push. When the effective authentication methods policy for the user's authentication request requires Verified Duo Push, or if Risk-based Factor Selection policy "steps up" the authentication to require secure methods, push will be available in the device capabilities response, and the user will be able to perform a Verified Duo Push.

If this parameter is not provided or the value is not 1, then the Auth API will assume your client does not support Verified Duo Push. The “Require Verified Duo Push” authentication methods policy setting will be ignored if enabled, and if the authenticating user's available methods are limited by Risk-based Factor Selection, they will not be able to use push as an authenticating factor.

ipaddr Optional The IP address of the user to be authenticated, in dotted quad format. This will cause an "allow" response to be sent if appropriate for requests from a trusted network.
hostname Optional The host name of the device accessing the application.
trusted_device_token Optional If the trusted_device_token is present and the Auth API application has an effective policy that enables Remembered Devices for each browser-based application, return an "allow" response for the lifetime of the token as set by the Duo administrator in the policy.

Response Codes

Response Meaning
200 Success.
400 400 Invalid or missing parameters, or the specified username is not in a state that allows preauth to complete successfully

Response Format

Key Value
devices

A list of the user's devices, where each device is a series of key/value pairs.

This field will only be present if result is "auth".

Key Value
capabilities

List of strings, each a factor that can be used with the device. The factors available for use may be limited by an effective authentication methods policy or Risk-based Factor Selection policy that disables use of some factors. Note that hardware tokens do not have any associated capabilities.

Capability Meaning
auto The device is valid for automatic factor selection (e.g. phone or push).
push The device is activated for Duo Push.
sms The device can receive batches of SMS passcodes.
phone The device can receive phone calls.
mobile_otp The device is capable of generating passcodes with the Duo Mobile app.
device Identifies which of the user's devices this is.
display_name A short string which can be used to identify the device in a prompt.
name Device's name. Or, if the device has not been named, the empty string ("").
number Phone number of the device, with all but the last four digits obscured. Or, if the device has no associated number, the empty string ("").
sms_nextcode

Single-character string containing the starting number of the next acceptable passcode previously SMSed to the user, if any. For example, if a user has received a batch of SMS passcodes and authenticated with those that began with 1 and 3, then sms_nextcode will be "2".

This field will only be present if the device has the "sms" capability and has previously received passcodes.

type "phone" or "token".
enroll_portal_url

If result is "enroll" a unique, enrollment portal URL is returned. This URL may be passed to the user and opened in a new browser window to access a portal that will help the user associate a device with the user_id specified or returned when calling /preauth. The enrollment URL is valid for five minutes after generation.

This enrollment portal URL should be used instead of calling /enroll if your users need to enroll phones that are not capable of running Duo Mobile, such as landlines or cell phones. /enroll only supports enrolling smartphones that can run Duo Mobile.

This field will only be present if result is "enroll".

expiration

Unix timestamp of time at which the txid and verification_code for completing a Verified Duo Push authentication expires, 60 seconds after issuance. Not present in the response when a regular Duo Push would be accepted.

Your client application should not proceed to /auth once the txid expires.

result One of the following strings:
Value Meaning
auth The user is known and permitted to authenticate. Your client application should use the /auth endpoint to perform authentication.
allow The user is not required to complete secondary authentication, either because the user has "bypass" status or the effective policy for the user's access of this application allows access without 2FA or Duo enrollment. Your client application should immediately grant access.
deny The user is not permitted to authenticate at this time. Your client application should immediately deny access.
enroll The user is not known to Duo and needs to enroll. Your application should deny access.
status_msg

Human-readable message describing the result. This string is intended for display to the user.

txid

A transaction ID to submit to the /auth endpoint to perform Verified Duo Push. Not present in the response when a regular Duo Push would be accepted.

verification_code

A numeric string of three to six digits matching the Verified Duo Push code length configured in the authentication methods or Risk-based Factor Selection policy options. If present in the response, your client should show this code to the user for entry in Duo Mobile as they approve a Verified Duo Push request. Not present in the response when a regular Duo Push would be accepted.

Example Responses

If result was "auth":

{
  "stat": "OK",
  "response": {
    "devices": [
      {
        "capabilities": [
            "auto",
            "push",
            "sms",
            "phone",
            "mobile_otp"
        ],
        "device": "DPFZRS9FB0D46QFTM891",
        "display_name": "iOS (XXX-XXX-0100)",
        "name": "",
        "number": "XXX-XXX-0100",
        "type": "phone"
      },
      {
        "device": "DHEKH0JJIYC1LX3AZWO4",
        "name": "0",
        "type": "token"

      }
    ],
    "result": "auth",
    "status_msg": "Account is active"
  }
}

If result was "auth" and client_supports_verified_push=1:

{
  "stat": "OK",
  "response": {
    "devices": [
      {
        "capabilities": [
            "auto",
            "push",
            "sms",
            "phone",
            "mobile_otp"
        ],
        "device": "DPFZRS9FB0D46QFTM891",
        "display_name": "iOS (XXX-XXX-0100)",
        "name": "",
        "number": "XXX-XXX-0100",
        "type": "phone"
      },
      {
        "device": "DHEKH0JJIYC1LX3AZWO4",
        "name": "0",
        "type": "token"

      }
    ],
    "expiration": 1710428517,
    "result": "auth",
    "status_msg": "Account is active",
    "txid": "7b333558-f3ff-4fe9-8200-f43a8d2d2f29",
    "verification_code": "867"
  }
}

If result was "enroll":

{
  "stat": "OK",
  "response": {
    "enroll_portal_url": "https://api-abcd1234.duosecurity.com/portal?code=48bac5d9393fb2c2&akey=DIXXXXXXXXXXXXXXXXXX",
    "result": "enroll",
    "status_msg": "Enroll an authentication device to proceed"
  }
}

If the result was "allow" because the request included a valid trusted_device_token:

{
  "stat": "OK",
  "response": {
        "result": "allow",
        "status_msg": "Device is trusted."
  },
}

/auth

The /auth endpoint performs second-factor authentication for a user by sending a push notification to the user's smartphone app, verifying a passcode, or placing a phone call. It is also used to send the user a new batch of passcodes via SMS.

POST /auth/v2/auth

Parameters

Param Required? Description
user_id Required if username is not specified Permanent, unique identifier for the user as generated by Duo upon user creation (e.g. DUYHV6TJBC3O4RITS1WC).

Exactly one of user_id or username must be specified.
username Required if user_id is not specified Unique identifier for the user that is commonly specified by your application during user creation (e.g. user@domain.com). This value may also represent a username alias assigned to a user.

Exactly one of user_id or username must be specified.
factor Required Factor to use for authentication. Currently, the following choices are supported:
Value Meaning
auto Use the out-of-band factor (push or phone) recommended by Duo as the best for the user's devices.
push Authenticate the user with Duo Push.
passcode Authenticate the user with a passcode (from Duo Mobile, SMS, hardware token, or bypass code).
sms Send a new batch of SMS passcodes to the user. Note that this will not actually authenticate the user (it will automatically return "deny"). Thus, if the user elects to do this then you should re-prompt to authenticate after the call has completed.
phone Authenticate the user with phone callback.

Also see below for additional parameters that are necessary depending on the factor you specify.

ipaddr Optional The IP address of the user to be authenticated, in dotted quad format. This will cause an "allow" response to be sent if appropriate for requests from a trusted network.
hostname Optional The host name of the device accessing the application.
async Optional

If this parameter is not provided, then the /auth endpoint will only return a response when the authentication process has completed. If, however, your application provides this parameter with a value of "1", then /auth will immediately return a transaction ID, and your application will need to subsequently query the /auth_status endpoint to get the status (and, eventually, result) of the authentication process.

If you enable async, then your application will be able to retrieve real-time status updates from the authentication process, rather than receiving no information until the process is complete.

Additionally, you will need to pass some factor-specific parameters depending on the authentication method.

Duo Push or Verified Duo Push

Parameter Required? Description
device Required

ID of the device. This device must have the "push" capability.

You may also specify "auto" to use the first of the user's devices with the "push" capability.

type Optional

This string is displayed in the Duo Mobile app push notification and UI. You may wish to specify some alternate phrase for this parameter.

The default English string in Duo Mobile v4 is "Verify your identity" and "Are you logging in to" followed by the application's name in the push request notification text, and "Are you logging in to" followed by the application's name in the request details screen as shown in Duo Mobile. With type specified, the notification text changes to "Verify request" and shows your customized string followed by a colon and the application's name, and the request details screen also shows your customized string and the application's name. Duo Mobile shows the equivalent localization in the languagues supported by the app, but does not attempt to localize your custom string or support multiple string values (for different languages).

In Duo Mobile v3, the default string shown is "Login Request" followed by the application's name in both the push notification text and on the request details screen.

display_username Optional String to display in Duo Mobile in place of the user's Duo username.
pushinfo Optional

A set of URL-encoded key/value pairs with additional contextual information associated with this authentication attempt. The Duo Mobile app will display this information to the user.

For example: from=login%20portal&domain=example.com

The URL-encoded string's total length must be less than 20,000 bytes.

txid Optional

The transaction ID received in the /preauth endpoint response when the request specified client_supports_verified_push=1 for Verified Duo Push.

Providing a txid which does not match the value received in the /preauth response or sending the request once the expiration time has passed results in an error response.

If no txid value is provided then Auth API assumes Verified Duo Push is not supported. The Verified Duo Push requirement in an authentication methods policy is ignored, and Duo Push will not be available as a factor if the user's factors have been limited by Risk-based Factor Selection.

Passcode

Parameter Required? Description
passcode Required Passcode entered by the user.

Phone callback

Parameter Required? Description
device Required

ID of the device to call. This device must have the "phone" capability.

You may also specify "auto" to use the first of the user's devices with the "phone" capability.

Sending new SMS passcodes

Parameter Required? Description
device Required

ID of the device to send passcodes to. This device must have the "sms" capability.

You may also specify "auto" to use the first of the user's devices with the "sms" capability.

The response will be returned in the container format described above. For successful responses, the payload will contain the following key/value pairs:

Response Codes

Response Meaning
200 Success.
400 Invalid or missing parameters. For example, the user does not exist or does not have any device capable of performing the requested authentication, or the txid sent for Verified Duo Push has expired.

Response formats

If async was not enabled:

Key Value
result Either "allow" or "deny". If "allow" was returned, your application should grant access to the user. If "deny", it should not.
status String detailing the progress or outcome of the authentication attempt.
Value Meaning
calling Currently calling the user's phone. The result will be "waiting".
answered Phone call answered. The result will be "waiting".
pushed A Duo Push authentication request has been sent to the device. The result will be "waiting".
push_failed An error occurred while sending the push notification to the user's device. The user should retrieve the request manually using the Duo Push button in the Duo Mobile app. The result will be "waiting".
timeout Authentication timed out. Duo Push times out after 60 seconds and phone calls will also time out after approximately one minute. The result will be "deny".
fraud The authentication request was reported as fraudulent. The result will be "deny".
allow Authentication succeeded. The result will be "allow".
bypass Authentication has been skipped for a user in bypass mode. The result will be "allow".
deny Authentication denied. The result will be "deny".
locked_out The user has been disabled due to authentication failures. The result will be "deny".
sent Passcodes have been sent to the device. The result will be "deny".
status_msg Human-readable string describing the status of the authentication attempt. If the authentication attempt was denied, it may identify a reason. This string is intended for display to the user.
trusted_device_token A string containing a token for that trusted device, which can be passed into the next /preauth call to bypass 2FA for the lifetime of the token. Requires an effective policy on the Auth API application that enables Remembered Devices per application, not for all applications.

If async was enabled:

Key Value
txid

>A transaction ID to be used to query the authentication status using the /auth_status endpoint.

If you specify async in conjunction with a txid value for Verified Duo Push received from the /preauth response, then the same txid value is returned in the /auth response.

Example Responses

If async was not enabled and the auth attempt succeeded:

{
  "stat": "OK",
  "response": {
    "result": "allow",
    "status": "allow",
    "status_msg": "Success. Logging you in..."
  }
}

If async was not enabled and the auth attempt failed due to factor restriction as a result of Risk-based Factor Selection policy:

{
  "stat": "OK",
  "response": {
        "result": "deny",
        "status": "deny",
        "status_msg": "Selected number is restricted from Duo Push authentication"
  },
}

If async was enabled:

{
  "stat": "OK",
  "response": {
    "txid": "45f7c92b-f45f-4862-8545-e0f58e78075a"
  }
}

If async was not enabled and a Remembered Devices per-application policy was effective on the Auth API application:

{
  "stat": "OK",
  "response": {
        "result": "allow",
        "status": "allow",
        "status_msg": "Success. Logging you in...",
        "trusted_device_token": "REkxSzP00Ld4ddEVTRZOUlYMEl8RFVVQkdJ05HwUldRRThJR1VTNE0=||1627133735|8356ef7779bb0ec4c28ca9b04dc50493c4d2e05e"
  },
}

/auth_status

The /auth_status endpoint "long-polls" for the next status update from the authentication process for a given transaction. That is to say, if no status update is available at the time the request is sent, it will wait until there is an update before returning a response.

GET /auth/v2/auth_status

Parameters

Param Required? Description
txid Required The transaction ID of the authentication attempt, as returned by the /auth endpoint.

Response Codes

Response Meaning
200 Success.
400 Invalid or missing parameters.

Response Format

Key Value
result One of the following values:
Value Meaning
allow Authentication succeeded. Your application should grant access to the user.
deny Authentication denied. Your application should deny access.
waiting Authentication is still in-progress. Your application should poll again until it finishes. Check the status for more details on the progress.
status String detailing the progress or outcome of the authentication attempt.
Value Meaning
calling Currently calling the user's phone. The result will be "waiting".
answered Phone call answered. The result will be "waiting".
pushed A Duo Push or Verified Duo Push authentication request has been sent to the device. The result will be "waiting".
push_failed An error occurred while sending the push notification to the user's device. The user should retrieve the request manually using the Duo Push button in the Duo Mobile app. The result will be "waiting".
timeout Authentication timed out. Duo Push times out after 60 seconds and phone calls will also time out after approximately one minute. The result will be "deny".
fraud The authentication request was reported as fraudulent. The result will be "deny".
allow Authentication succeeded. The result will be "allow".
bypass Authentication has been skipped for a user in bypass mode. The result will be "allow".
deny Authentication denied. The result will be "deny".
locked_out The user has been disabled due to authentication failures. The result will be "deny".
sent Passcodes have been sent to the device. The result will be "deny".
status_msg

Human-readable string describing the status of the authentication attempt. If the authentication attempt was denied, it may identify a reason. This string is intended for display to the user.

When Verified Duo Push is required for an asynchronous authentication then the message contains the Duo Mobile verification code and usage instructions.

trusted_device_token When /auth was called with async enabled, the value of trusted_device_token will be a string containing a token for that trusted device. This can be passed into the next /preauth call to bypass 2FA for the lifetime of the token. Requires an effective policy on the Auth API application that enables Remembered Devices

Example Response for Duo Push:

{
  "stat": "OK",
  "response": {
    "result": "waiting",
    "status": "pushed",
    "status_msg": "Pushed a login request to your phone..."
  }
}

Example Response for Verified Duo Push:

{
  "stat": "OK",
  "response": {
    "result": "waiting",
    "status": "pushed",
    "status_msg": "Please enter verification code 074 into Duo Mobile..."
  }
}

API Details

Base URL

All API methods use your API hostname, https://api-XXXXXXXX.duosecurity.com. Obtain this value from the Duo Admin Panel and use it exactly as shown there.

Methods always use HTTPS. Unsecured HTTP is not supported.

Request Format

All requests must have "Authorization" and "Date" headers.

If the request method is GET or DELETE, URL-encode parameters and send them in the URL query string like this: ?realname=First%20Last&username=root. They still go on a separate line when creating the string to sign for an Authorization header.

Send parameters for POST requests in the body as URL-encoded key-value pairs (the same request format used by browsers to submit form data). The header "Content-Type: application/x-www-form-urlencoded" must also be present.

When URL-encoding, all bytes except ASCII letters, digits, underscore ("_"), period ("."), tilde ("~"), and hyphen ("-") are replaced by a percent sign ("%") followed by two hexadecimal digits containing the value of the byte. For example, a space is replaced with "%20" and an at-sign ("@") becomes "%40". Use only upper-case A through F for hexadecimal digits.

A request with parameters, as a complete URL, would look something like this: https://api-XXXXXXXX.duosecurity.com/admin/v1/users?realname=First%20Last&username=root (substituting the actual API method path and parameters used in your request).

Response Format

Responses are formatted as a JSON object with a top-level stat key.

Successful responses will have a stat value of "OK" and a response key. The response will either be a single object or a sequence of other JSON types, depending on which endpoint is called.

{
  "stat": "OK",
  "response": {
    "key": "value"
  }
}

Values are returned as strings unless otherwise documented.

Unsuccessful responses will have a stat value of "FAIL", an integer code, and a message key that further describes the failure. A message_detail key may be present if additional information is available (like the specific parameter that caused the error).

{
  "stat": "FAIL",
  "code": 40002,
  "message": "Invalid request parameters",
  "message_detail": "username"
}

The HTTP response code will be the first three digits of the more specific code found inside the JSON object. Each endpoint's documentation lists HTTP response codes it can return. Additionally, all API endpoints that require a signed request can return the following HTTP response codes:

Response Meaning
200 The request completed successfully.
401 The "Authorization", "Date", and/or "Content-Type" headers were missing or invalid.
403

This integration is not authorized for this endpoint or the ikey was created for a different integration type (for example, using an Auth API ikey with Admin API endpoints).

405 The request's HTTP verb is not valid for this endpoint (for example, POST when only GET is supported).
429 The account has made too many requests of this type recently. Try again later.

Authentication

The API uses HTTP Basic Authentication to authenticate requests. Use your Duo application's integration key as the HTTP Username.

Generate the HTTP Password as an HMAC signature of the request. This will be different for each request and must be re-generated each time.

To construct the signature, first build an ASCII string from your request, using the following components:

Component Description Example
date The current time, formatted as RFC 2822. This must be the same string as the "Date" header. Tue, 21 Aug 2012 17:29:18 -0000
method The HTTP method (uppercase) POST
host Your API hostname (lowercase) api-xxxxxxxx.duosecurity.com
path

The specific API method's path

params

The URL-encoded list of key=value pairs, lexicographically sorted by key. These come from the request parameters (the URL query string for GET and DELETE requests or the request body for POST requests).

If the request does not have any parameters one must still include a blank line in the string that is signed.

Do not encode unreserved characters. Use upper-case hexadecimal digits A through F in escape sequences.

An example params list:

realname=First%20Last&username=root

Then concatenate these components with (line feed) newlines. For example:

Tue, 21 Aug 2012 17:29:18 -0000
POST
api-xxxxxxxx.duosecurity.com
/auth/v2/auth
device=auto&factor=push&hostname=wks01&ipaddr=10.2.3.4&username=narroway

GET requests also use this five-line format (note the blank line as this request has no parameters):

Tue, 21 Aug 2012 17:29:18 -0000
GET
api-xxxxxxxx.duosecurity.com
/auth/v2/check
 

Lastly, compute the HMAC-SHA1 of this canonical representation, using your Duo application's secret key as the HMAC key. Send this signature as hexadecimal ASCII (i.e. not raw binary data). Use HTTP Basic Authentication for the request, using your integration key as the username and the HMAC-SHA1 signature as the password.

For example, here are the headers for the above POST request to api-XXXXXXXX.duosecurity.com/auth/v2/auth, using DIWJ8X6AEYOR5OMC6TQ1 as the integration key and Zh5eGmUq9zpfQnyUIu5OL9iWoMMv5ZNmk3zLJ4Ep as the secret key:

Date: Tue, 21 Aug 2012 17:29:18 -0000
Authorization: Basic RElXSjhYNkFFWU9SNU9NQzZUUTE6NGUxMzY2MGVmMGEwZTQ5MWFhNzg2ZGNhZmM2MDgwMjU0NzFkOTg5Nw==
Host: api-XXXXXXXX.duosecurity.com
Content-Length: 92
Content-Type: application/x-www-form-urlencoded

Separate HTTP request header lines with CRLF newlines.

The following Python function can be used to construct the "Authorization" and "Date" headers:

import base64, email.utils, hmac, hashlib, urllib
  ​ ​
def sign(method, host, path, params, skey, ikey):
    """
    Return HTTP Basic Authentication ("Authorization" and "Date") headers.
    method, host, path: strings from request
    params: dict of request parameters
    skey: secret key
    ikey: integration key
    """
  ​
    # create canonical string
    now = email.utils.formatdate()
    canon = [now, method.upper(), host.lower(), path]
    args = []
    for key in sorted(params.keys()):
        val = params[key].encode("utf-8")
        args.append(
            '%s=%s' % (urllib.parse.
                       quote(key, '~'), urllib.parse.quote(val, '~')))
    canon.append('&'.join(args))
    canon = '\n'.join(canon)
  ​
    # sign canonical string
    sig = hmac.new(bytes(skey, encoding='utf-8'),
                   bytes(canon, encoding='utf-8'),
                   hashlib.sha1)
    auth = '%s:%s' % (ikey, sig.hexdigest())
  ​
    # return headers
    return {'Date': now, 'Authorization': 'Basic %s' % base64.b64encode(bytes(auth, encoding="utf-8")).decode()}
import base64, email, hmac, hashlib, urllib

def sign(method, host, path, params, skey, ikey):
    """
    Return HTTP Basic Authentication ("Authorization" and "Date") headers.
    method, host, path: strings from request
    params: dict of request parameters
    skey: secret key
    ikey: integration key
    """

    # create canonical string
    now = email.Utils.formatdate()
    canon = [now, method.upper(), host.lower(), path]
    args = []
    for key in sorted(params.keys()):
        val = params[key]
        if isinstance(val, unicode):
            val = val.encode("utf-8")
        args.append(
            '%s=%s' % (urllib.quote(key, '~'), urllib.quote(val, '~')))
    canon.append('&'.join(args))
    canon = '\n'.join(canon)

    # sign canonical string
    sig = hmac.new(skey, canon, hashlib.sha1)
    auth = '%s:%s' % (ikey, sig.hexdigest())

    # return headers
    return {'Date': now, 'Authorization': 'Basic %s' % base64.b64encode(auth)}

Troubleshooting

Need some help? Take a look at our Auth API Knowledge Base articles or Community discussions. For further assistance, contact Support.

If you receive 401 error responses to your API requests, check the following:

  • Is the Authorization header correctly formatted? If not, you may receive a 40101 error.
  • Does your framework override the Date header? The HTTP Date: header must be exactly the same string as was signed. This could result in a 40103 error.
  • Are the Date and time zone used RFC 3339 compliant?? If not, you may get a 40104 or 40105 response.
  • Are the parameters lexicographically sorted?
  • Did you include a line for parameters when constructing the signature, even if you're not passing in any parameters?
  • Are any hex digits lower-case?
  • Are the Content-Length and Content-Type parameters correct? If not, your parameters may be ignored or you may receive a 40103 response because your signature considered parameters that the service didn't receive.