Sample code for 30+ languages & platforms
Unicode C

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 Unicode C Downloads

Unicode C
#include <C_CkHttpW.h>
#include <C_CkHttpRequestW.h>
#include <C_CkHttpResponseW.h>
#include <C_CkJsonObjectW.h>
#include <C_CkStringBuilderW.h>

void ChilkatSample(void)
    {
    BOOL success;
    const wchar_t *integrationKey;
    const wchar_t *secretKey;
    HCkHttpW http;
    const wchar_t *url;
    HCkHttpRequestW req;
    HCkHttpResponseW resp;
    HCkJsonObjectW json;
    const wchar_t *txid;
    HCkStringBuilderW sbUrl;
    const wchar_t *url;
    HCkStringBuilderW sbResult;
    const wchar_t *responseStatus;
    const wchar_t *responseStatus_msg;
    int i;
    int maxWaitIterations;

    success = FALSE;

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

    integrationKey = L"DIMS3V5QDVG9J9ABRXC4";
    secretKey = L"HWVQ46nubLBxhnRlKddTltWIi3hL0fIQF2qTvLab";

    http = CkHttpW_Create();

    CkHttpW_putAccept(http,L"application/json");

    // Use your own hostname here:
    url = L"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.
    CkHttpW_putLogin(http,integrationKey);
    CkHttpW_putPassword(http,secretKey);

    req = CkHttpRequestW_Create();
    CkHttpRequestW_AddParam(req,L"username",L"matt");
    CkHttpRequestW_AddParam(req,L"factor",L"push");
    // The device ID can be obtained from the preauth response.  See Duo Preauth Example
    CkHttpRequestW_AddParam(req,L"device",L"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.
    CkHttpRequestW_AddParam(req,L"async",L"1");

    CkHttpRequestW_putHttpVerb(req,L"POST");
    CkHttpRequestW_putContentType(req,L"application/x-www-form-urlencoded");

    resp = CkHttpResponseW_Create();
    success = CkHttpW_HttpReq(http,url,req,resp);
    if (success == FALSE) {
        wprintf(L"%s\n",CkHttpW_lastErrorText(http));
        CkHttpW_Dispose(http);
        CkHttpRequestW_Dispose(req);
        CkHttpResponseW_Dispose(resp);
        return;
    }

    wprintf(L"status code = %d\n",CkHttpResponseW_getStatusCode(resp));

    json = CkJsonObjectW_Create();
    success = CkJsonObjectW_Load(json,CkHttpResponseW_bodyStr(resp));
    CkJsonObjectW_putEmitCompact(json,FALSE);
    wprintf(L"%s\n",CkJsonObjectW_emit(json));

    if (CkHttpResponseW_getStatusCode(resp) != 200) {
        CkHttpW_Dispose(http);
        CkHttpRequestW_Dispose(req);
        CkHttpResponseW_Dispose(resp);
        CkJsonObjectW_Dispose(json);
        return;
    }

    // Sample successful output:

    // status code = 200

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

    txid = CkJsonObjectW_stringOf(json,L"response.txid");

    // Use your own hostname here:
    sbUrl = CkStringBuilderW_Create();
    CkStringBuilderW_Append(sbUrl,L"https://api-a03782e1.duosecurity.com/auth/v2/auth_status?txid=");
    CkStringBuilderW_Append(sbUrl,txid);
    url = CkStringBuilderW_getAsString(sbUrl);

    wprintf(L"Auth status URL: %s\n",url);

    sbResult = CkStringBuilderW_Create();

    // Wait for a response...
    i = 0;
    maxWaitIterations = 100;
    while (i < maxWaitIterations) {
        // Wait 3 seconds.
        CkHttpW_SleepMs(http,3000);

        wprintf(L"Polling...\n");

        success = CkHttpW_HttpNoBody(http,L"GET",url,resp);
        if (success == FALSE) {
            wprintf(L"%s\n",CkHttpW_lastErrorText(http));
            CkHttpW_Dispose(http);
            CkHttpRequestW_Dispose(req);
            CkHttpResponseW_Dispose(resp);
            CkJsonObjectW_Dispose(json);
            CkStringBuilderW_Dispose(sbUrl);
            CkStringBuilderW_Dispose(sbResult);
            return;
        }

        if (CkHttpResponseW_getStatusCode(resp) != 200) {
            wprintf(L"error status code = %d\n",CkHttpResponseW_getStatusCode(resp));
            wprintf(L"%s\n",CkHttpResponseW_bodyStr(resp));
            wprintf(L"Failed.\n");
            CkHttpW_Dispose(http);
            CkHttpRequestW_Dispose(req);
            CkHttpResponseW_Dispose(resp);
            CkJsonObjectW_Dispose(json);
            CkStringBuilderW_Dispose(sbUrl);
            CkStringBuilderW_Dispose(sbResult);
            return;
        }

        // Sample response:

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

        CkJsonObjectW_Load(json,CkHttpResponseW_bodyStr(resp));

        // The responseResult can be "allow", "deny", or "waiting"
        CkStringBuilderW_Clear(sbResult);
        CkJsonObjectW_StringOfSb(json,L"response.result",sbResult);
        responseStatus = CkJsonObjectW_stringOf(json,L"response.status");
        responseStatus_msg = CkJsonObjectW_stringOf(json,L"response.status_msg");

        wprintf(L"%s\n",CkStringBuilderW_getAsString(sbResult));
        wprintf(L"%s\n",responseStatus);
        wprintf(L"%s\n",responseStatus_msg);
        wprintf(L"\n");

        if (CkStringBuilderW_ContentsEqual(sbResult,L"waiting",TRUE) == TRUE) {
            i = i + 1;
        }
        else {
            // Force loop exit..
            i = maxWaitIterations;
        }

    }

    wprintf(L"Finished.\n");


    CkHttpW_Dispose(http);
    CkHttpRequestW_Dispose(req);
    CkHttpResponseW_Dispose(resp);
    CkJsonObjectW_Dispose(json);
    CkStringBuilderW_Dispose(sbUrl);
    CkStringBuilderW_Dispose(sbResult);

    }