Sample code for 30+ languages & platforms
Lua Requires Chilkat v11.0.0+

Duo Auth API - Async Auth

See more Duo Auth MFA Examples

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.

Chilkat Lua Downloads

Lua
local chilkat = require("chilkat")

-- This example assumes the Chilkat API to have been previously unlocked.
-- See Global Unlock Sample for sample code.

local integrationKey = "DIMS3V5QDVG9J9ABRXC4"
local secretKey = "HWVQ46nubLBxhnRlKddTltWIi3hL0fIQF2qTvLab"

local http = chilkat.Http.new()

http.accept = "application/json"

-- Use your own hostname here:
local url = "https://api-a03782e1.duosecurity.com/auth/v2/auth"

-- Chilkat will automatically
-- generate and send the HMAC signature for the requires based on the integration key and secret key.
http.login = integrationKey
http.password = secretKey

local req = chilkat.HttpRequest.new()
req:add_param("username", "matt")
req:add_param("factor", "push")
-- The device ID can be obtained from the preauth response.  See Duo Preauth Example
req:add_param("device", "DP6GYVTQ5NK82BMR851F")
-- Add the async param to get an immediate response, then periodically check for updates to find out when the MFA authentication completes for fails.
req:add_param("async", "1")

req.http_verb = "POST"
req.content_type = "application/x-www-form-urlencoded"

local resp = chilkat.HttpResponse.new()
local success = http:http_req(url, req, resp)
if not success then
    print(http.last_error_text)
    return
end

print("status code = " .. resp.status_code)

local json = chilkat.JsonObject.new()
success = json:load(resp.body_str)
json.emit_compact = false
print(json:emit())

if resp.status_code ~= 200 then
    return
end

-- Sample successful output:

-- status code = 200

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

local txid = json:string_of("response.txid")

-- Use your own hostname here:
local sbUrl = chilkat.StringBuilder.new()
sbUrl:append("https://api-a03782e1.duosecurity.com/auth/v2/auth_status?txid=")
sbUrl:append(txid)
url = sbUrl:get_as_string()

print("Auth status URL: " .. url)

local sbResult = chilkat.StringBuilder.new()
local responseStatus = ""
local responseStatus_msg = ""

-- Wait for a response...
local i = 0
local maxWaitIterations = 100
while i < maxWaitIterations do
    -- Wait 3 seconds.
    http:sleep_ms(3000)

    print("Polling...")

    success = http:http_no_body("GET", url, resp)
    if not success then
        print(http.last_error_text)
        return
    end

    if resp.status_code ~= 200 then
        print("error status code = " .. resp.status_code)
        print(resp.body_str)
        print("Failed.")
        return
    end

    -- Sample response:

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

    json:load(resp.body_str)

    -- The responseResult can be "allow", "deny", or "waiting"
    sbResult:clear()
    json:string_of_sb("response.result", sbResult)
    responseStatus = json:string_of("response.status")
    responseStatus_msg = json:string_of("response.status_msg")

    print(sbResult:get_as_string())
    print(responseStatus)
    print(responseStatus_msg)
    print("")

    if sbResult:contents_equal("waiting", true) then
        i = i + 1
    else
        -- Force loop exit..
        i = maxWaitIterations
    end
end

print("Finished.")