Sample code for 30+ languages & platforms
Swift

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 Swift Downloads

Swift

func chilkatTest() {
    var success: Bool = false

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

    var integrationKey: String? = "DIMS3V5QDVG9J9ABRXC4"
    var secretKey: String? = "HWVQ46nubLBxhnRlKddTltWIi3hL0fIQF2qTvLab"

    let http = CkoHttp()!

    http.accept = "application/json"

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

    // This example requires Chilkat v9.5.0.89 or greater because 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

    let req = CkoHttpRequest()!
    req.addParam(name: "username", value: "matt")
    req.addParam(name: "factor", value: "push")
    // The device ID can be obtained from the preauth response.  See Duo Preauth Example
    req.addParam(name: "device", value: "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.addParam(name: "async", value: "1")

    req.httpVerb = "POST"
    req.contentType = "application/x-www-form-urlencoded"

    let resp = CkoHttpResponse()!
    success = http.httpReq(url: url, request: req, response: resp)
    if success == false {
        print("\(http.lastErrorText!)")
        return
    }

    print("status code = \(resp.statusCode.intValue)")

    let json = CkoJsonObject()!
    success = json.load(json: resp.bodyStr)
    json.emitCompact = false
    print("\(json.emit()!)")

    if resp.statusCode.intValue != 200 {
        return
    }

    // Sample successful output:

    // status code = 200

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

    var txid: String? = json.string(of: "response.txid")

    // Use your own hostname here:
    let sbUrl = CkoStringBuilder()!
    sbUrl.append(value: "https://api-a03782e1.duosecurity.com/auth/v2/auth_status?txid=")
    sbUrl.append(value: txid)
    var url: String? = sbUrl.getAsString()

    print("Auth status URL: \(url!)")

    let sbResult = CkoStringBuilder()!
    var responseStatus: String?
    var responseStatus_msg: String?

    // Wait for a response...
    var i: Int = 0
    var maxWaitIterations: Int = 100
    while i < maxWaitIterations {
        // Wait 3 seconds.
        http.sleepMs(millisec: 3000)

        print("Polling...")

        success = http.httpNoBody(verb: "GET", url: url, response: resp)
        if success == false {
            print("\(http.lastErrorText!)")
            return
        }

        if resp.statusCode.intValue != 200 {
            print("error status code = \(resp.statusCode.intValue)")
            print("\(resp.bodyStr!)")
            print("Failed.")
            return
        }

        // Sample response:

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

        json.load(json: resp.bodyStr)

        // The responseResult can be "allow", "deny", or "waiting"
        sbResult.clear()
        json.string(ofSb: "response.result", sb: sbResult)
        responseStatus = json.string(of: "response.status")
        responseStatus_msg = json.string(of: "response.status_msg")

        print("\(sbResult.getAsString()!)")
        print("\(responseStatus!)")
        print("\(responseStatus_msg!)")
        print("")

        if sbResult.contentsEqual(str: "waiting", caseSensitive: true) == true {
            i = i + 1
        }
        else {
            // Force loop exit..
            i = maxWaitIterations
        }

    }

    print("Finished.")

}